123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import {createRoot} from 'react-dom/client';
- import throttle from 'lodash/throttle';
- import {exportedGlobals} from 'sentry/bootstrap/exportGlobals';
- import type {OnSentryInitConfiguration} from 'sentry/types/system';
- import {SentryInitRenderReactComponent} from 'sentry/types/system';
- import {renderDom} from './renderDom';
- import {renderOnDomReady} from './renderOnDomReady';
- const COMPONENT_MAP = {
- [SentryInitRenderReactComponent.INDICATORS]: () =>
- import(/* webpackChunkName: "Indicators" */ 'sentry/components/indicators'),
- [SentryInitRenderReactComponent.SYSTEM_ALERTS]: () =>
- import(/* webpackChunkName: "SystemAlerts" */ 'sentry/views/app/systemAlerts'),
- [SentryInitRenderReactComponent.SETUP_WIZARD]: () =>
- import(/* webpackChunkName: "SetupWizard" */ 'sentry/views/setupWizard'),
- [SentryInitRenderReactComponent.U2F_SIGN]: () =>
- import(/* webpackChunkName: "U2fSign" */ 'sentry/components/u2f/u2fsign'),
- [SentryInitRenderReactComponent.SU_STAFF_ACCESS_FORM]: () =>
- import(
- /* webpackChunkName: "SuperuserStaffAccessForm" */ 'sentry/components/superuserStaffAccessForm'
- ),
- };
- async function processItem(initConfig: OnSentryInitConfiguration) {
- /**
- * Allows our auth pages to dynamically attach a client side password
- * strength indicator The password strength component is very
- * heavyweight as it includes the zxcvbn, a relatively byte-heavy
- * password strength estimation library. Load it on demand.
- */
- if (initConfig.name === 'passwordStrength') {
- const {input, element} = initConfig;
- if (!input || !element) {
- return;
- }
- const inputElem = document.querySelector(input);
- const rootEl = document.querySelector(element);
- if (!inputElem || !rootEl) {
- return;
- }
- const {PasswordStrength} = await import(
- /* webpackChunkName: "PasswordStrength" */ 'sentry/components/passwordStrength'
- );
- const root = createRoot(rootEl);
- inputElem.addEventListener(
- 'input',
- throttle(e => {
- root.render(<PasswordStrength value={e.target.value} />);
- })
- );
- return;
- }
- /**
- * Allows server rendered templates to render a React component to DOM
- * without exposing the component globally.
- */
- if (initConfig.name === 'renderReact') {
- if (!COMPONENT_MAP.hasOwnProperty(initConfig.component)) {
- return;
- }
- const {default: Component} = await COMPONENT_MAP[initConfig.component]();
- renderOnDomReady(() =>
- // TODO(ts): Unsure how to type this, complains about u2fsign's required props
- renderDom(Component as any, initConfig.container, initConfig.props)
- );
- }
- /**
- * Callback for when js bundle is loaded. Provide library + component references
- * for downstream consumers to use.
- */
- if (initConfig.name === 'onReady' && typeof initConfig.onReady === 'function') {
- initConfig.onReady(exportedGlobals);
- }
- }
- /**
- * This allows server templates to push "tasks" to be run after application has initialized.
- * The global `window.__onSentryInit` is used for this.
- *
- * Be careful here as we can not guarantee type safety on `__onSentryInit` as
- * these will be defined in server rendered templates
- */
- export async function processInitQueue() {
- // Currently, this is run *before* anything is queued in
- // `window.__onSentryInit`. We want to provide a migration path for potential
- // custom plugins that rely on `window.SentryApp` so they can start migrating
- // their plugins ASAP, as `SentryApp` will be loaded async and will require
- // callbacks to access it, instead of via `window` global.
- if (
- typeof window.__onSentryInit !== 'undefined' &&
- !Array.isArray(window.__onSentryInit)
- ) {
- return;
- }
- const queued = window.__onSentryInit;
- // Stub future calls of `window.__onSentryInit.push` so that it is
- // processed immediately (since bundle is loaded at this point and no
- // longer needs to act as a queue)
- //
- window.__onSentryInit = {
- push: processItem,
- };
- if (Array.isArray(queued)) {
- // These are all side-effects, so no need to return a value, but allow consumer to
- // wait for all initialization to finish
- await Promise.all(queued.map(processItem));
- }
- }
|