processInitQueue.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import exportGlobals from 'sentry/bootstrap/exportGlobals';
  2. import {OnSentryInitConfiguration, SentryInitRenderReactComponent} from 'sentry/types';
  3. import {renderDom} from './renderDom';
  4. import {renderOnDomReady} from './renderOnDomReady';
  5. const COMPONENT_MAP = {
  6. [SentryInitRenderReactComponent.INDICATORS]: () =>
  7. import(/* webpackChunkName: "Indicators" */ 'sentry/components/indicators'),
  8. [SentryInitRenderReactComponent.SYSTEM_ALERTS]: () =>
  9. import(/* webpackChunkName: "SystemAlerts" */ 'sentry/views/app/systemAlerts'),
  10. [SentryInitRenderReactComponent.SETUP_WIZARD]: () =>
  11. import(/* webpackChunkName: "SetupWizard" */ 'sentry/views/setupWizard'),
  12. [SentryInitRenderReactComponent.U2F_SIGN]: () =>
  13. import(/* webpackChunkName: "U2fSign" */ 'sentry/components/u2f/u2fsign'),
  14. };
  15. async function processItem(initConfig: OnSentryInitConfiguration) {
  16. /**
  17. * Allows our auth pages to dynamically attach a client side password
  18. * strength indicator The password strength component is very
  19. * heavyweight as it includes the zxcvbn, a relatively byte-heavy
  20. * password strength estimation library. Load it on demand.
  21. */
  22. if (initConfig.name === 'passwordStrength') {
  23. const {input, element} = initConfig;
  24. if (!input || !element) {
  25. return;
  26. }
  27. const passwordStrength = await import(
  28. /* webpackChunkName: "PasswordStrength" */ 'sentry/components/passwordStrength'
  29. );
  30. passwordStrength.attachTo({
  31. input: document.querySelector(input),
  32. element: document.querySelector(element),
  33. });
  34. return;
  35. }
  36. /**
  37. * Allows server rendered templates to render a React component to DOM
  38. * without exposing the component globally.
  39. */
  40. if (initConfig.name === 'renderReact') {
  41. if (!COMPONENT_MAP.hasOwnProperty(initConfig.component)) {
  42. return;
  43. }
  44. const {default: Component} = await COMPONENT_MAP[initConfig.component]();
  45. renderOnDomReady(() =>
  46. // TODO(ts): Unsure how to type this, complains about u2fsign's required props
  47. renderDom(Component as any, initConfig.container, initConfig.props)
  48. );
  49. }
  50. /**
  51. * Callback for when js bundle is loaded. Provide library + component references
  52. * for downstream consumers to use.
  53. */
  54. if (initConfig.name === 'onReady' && typeof initConfig.onReady === 'function') {
  55. initConfig.onReady(exportGlobals);
  56. }
  57. }
  58. /**
  59. * This allows server templates to push "tasks" to be run after application has initialized.
  60. * The global `window.__onSentryInit` is used for this.
  61. *
  62. * Be careful here as we can not guarantee type safety on `__onSentryInit` as
  63. * these will be defined in server rendered templates
  64. */
  65. export async function processInitQueue() {
  66. // Currently, this is run *before* anything is queued in
  67. // `window.__onSentryInit`. We want to provide a migration path for potential
  68. // custom plugins that rely on `window.SentryApp` so they can start migrating
  69. // their plugins ASAP, as `SentryApp` will be loaded async and will require
  70. // callbacks to access it, instead of via `window` global.
  71. if (
  72. typeof window.__onSentryInit !== 'undefined' &&
  73. !Array.isArray(window.__onSentryInit)
  74. ) {
  75. return;
  76. }
  77. const queued = window.__onSentryInit;
  78. // Stub future calls of `window.__onSentryInit.push` so that it is
  79. // processed immediately (since bundle is loaded at this point and no
  80. // longer needs to act as a queue)
  81. //
  82. window.__onSentryInit = {
  83. push: processItem,
  84. };
  85. if (Array.isArray(queued)) {
  86. // These are all side-effects, so no need to return a value, but allow consumer to
  87. // wait for all initialization to finish
  88. await Promise.all(queued.map(processItem));
  89. }
  90. }