processInitQueue.tsx 3.8 KB

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