processInitQueue.tsx 3.8 KB

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