123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- import * as Sentry from '@sentry/react';
- import isUndefined from 'lodash/isUndefined';
- import Reflux from 'reflux';
- import {HookName, Hooks} from 'app/types/hooks';
- /**
- * See types/hooks for hook usage reference.
- */
- const validHookNames = new Set<HookName>([
- '_',
- 'analytics:event',
- 'analytics:init-user',
- 'analytics:track-adhoc-event',
- 'analytics:track-event',
- 'analytics:log-experiment',
- 'component:disabled-member',
- 'component:disabled-member-tooltip',
- 'component:header-date-range',
- 'component:header-selector-items',
- 'component:global-notifications',
- 'component:member-list-header',
- 'component:dashboards-header',
- 'feature-disabled:alerts-page',
- 'feature-disabled:alert-wizard-performance',
- 'feature-disabled:configure-distributed-tracing',
- 'feature-disabled:custom-inbound-filters',
- 'feature-disabled:custom-symbol-sources',
- 'feature-disabled:data-forwarding',
- 'feature-disabled:discard-groups',
- 'feature-disabled:discover-page',
- 'feature-disabled:discover-saved-query-create',
- 'feature-disabled:discover-sidebar-item',
- 'feature-disabled:discover2-page',
- 'feature-disabled:discover2-sidebar-item',
- 'feature-disabled:events-page',
- 'feature-disabled:events-sidebar-item',
- 'feature-disabled:grid-editable-actions',
- 'feature-disabled:open-discover',
- 'feature-disabled:dashboards-edit',
- 'feature-disabled:dashboards-page',
- 'feature-disabled:dashboards-sidebar-item',
- 'feature-disabled:incidents-sidebar-item',
- 'feature-disabled:performance-new-project',
- 'feature-disabled:performance-page',
- 'feature-disabled:performance-quick-trace',
- 'feature-disabled:performance-sidebar-item',
- 'feature-disabled:project-performance-score-card',
- 'feature-disabled:project-selector-checkbox',
- 'feature-disabled:rate-limits',
- 'feature-disabled:sso-basic',
- 'feature-disabled:sso-rippling',
- 'feature-disabled:sso-saml2',
- 'feature-disabled:trace-view-link',
- 'footer',
- 'help-modal:footer',
- 'integrations:feature-gates',
- 'member-invite-modal:customization',
- 'metrics:event',
- 'onboarding:extra-chrome',
- 'onboarding-wizard:skip-help',
- 'organization:header',
- 'routes',
- 'routes:admin',
- 'routes:api',
- 'routes:organization',
- 'routes:organization-root',
- 'settings:api-navigation-config',
- 'settings:organization-navigation',
- 'settings:organization-navigation-config',
- 'sidebar:bottom-items',
- 'sidebar:help-menu',
- 'sidebar:item-label',
- 'sidebar:item-override',
- 'sidebar:organization-dropdown-menu',
- 'sidebar:organization-dropdown-menu-bottom',
- ]);
- type HookStoreInterface = {
- // XXX(epurkhiser): We could type this as {[H in HookName]?:
- // Array<Hooks[H]>}, however this causes typescript to produce a complex
- // union that it complains is 'too complex'
- hooks: any;
- add<H extends HookName>(hookName: H, callback: Hooks[H]): void;
- remove<H extends HookName>(hookName: H, callback: Hooks[H]): void;
- get<H extends HookName>(hookName: H): Array<Hooks[H]>;
- };
- const hookStoreConfig: Reflux.StoreDefinition & HookStoreInterface = {
- hooks: {},
- init() {
- this.hooks = {};
- },
- add(hookName, callback) {
- // Gracefully error on invalid hooks, but maintain registration
- // TODO(ts): With typescript we can remove this in the future
- if (!validHookNames.has(hookName)) {
- // eslint-disable-next-line no-console
- console.error('Invalid hook name: ' + hookName);
- Sentry.withScope(scope => {
- scope.setExtra('hookName', hookName);
- Sentry.captureException(new Error('Invalid hook name'));
- });
- }
- if (isUndefined(this.hooks[hookName])) {
- this.hooks[hookName] = [];
- }
- this.hooks[hookName]!.push(callback);
- this.trigger(hookName, this.hooks[hookName]);
- },
- remove(hookName, callback) {
- if (isUndefined(this.hooks[hookName])) {
- return;
- }
- this.hooks[hookName] = this.hooks[hookName]!.filter(cb => cb !== callback);
- this.trigger(hookName, this.hooks[hookName]);
- },
- get(hookName) {
- return this.hooks[hookName]! || [];
- },
- };
- type HookStore = Reflux.Store & HookStoreInterface;
- /**
- * 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 = Reflux.createStore(hookStoreConfig) as HookStore;
- export default HookStore;
|