import {createStore, StoreDefinition} from 'reflux'; import {HookName, Hooks} from 'sentry/types/hooks'; interface Internals { // XXX(epurkhiser): We could type this as {[H in HookName]?: // Array}, however this causes typescript to produce a complex // union that it complains is 'too complex' hooks: any; } interface HookStoreDefinition extends StoreDefinition, Internals { add(hookName: H, callback: Hooks[H]): void; get(hookName: H): Array; remove(hookName: H, callback: Hooks[H]): void; } const storeConfig: HookStoreDefinition = { hooks: {}, init() { // XXX: Do not use `this.listenTo` in this store. We avoid usage of reflux // listeners due to their leaky nature in tests. this.hooks = {}; }, add(hookName, callback) { if (this.hooks[hookName] === undefined) { this.hooks[hookName] = []; } this.hooks[hookName].push(callback); this.trigger(hookName, this.hooks[hookName]); }, remove(hookName, callback) { if (this.hooks[hookName] === undefined) { return; } this.hooks[hookName] = this.hooks[hookName]!.filter(cb => cb !== callback); this.trigger(hookName, this.hooks[hookName]); }, get(hookName) { return this.hooks[hookName]! || []; }, }; /** * HookStore is used to allow extensibility into Sentry's frontend via * registration of 'hook functions'. * * This functionality is primarily used by the SASS sentry.io product. */ const HookStore = createStore(storeConfig); export default HookStore;