/* eslint-disable max-statements */ import { SubAppDef, SubAppOptions, SubAppFeatureFactory, SubApp } from "./types"; import { envHooks } from "./envhooks"; export * from "./types"; export * from "./envhooks"; export * from "./subapp-ready"; export * from "./client-render-pipeline"; export * from "./subapp-render-pipeline"; export * from "./client-framework-lib"; /** * Load features * * @param subapp : Subapp definition * @param features : Subapp features */ function loadFeatures(subapp: SubAppDef, features: SubAppFeatureFactory[]) { if (features && features.length > 0) { for (const feat of features) { feat.add(subapp); } } } const noop = () => { // }; let id = 1; /** * Load the dynamic import module for a subapp * * Note: not doing async/await to avoid ts transpiling them to non-promise ES5 * https://github.com/microsoft/TypeScript/issues/31621 * * @returns Promise resolving to module loaded */ async function _getModule(): Promise { /* eslint-disable no-invalid-this */ const container = envHooks.getContainer(); const subapp = container.get(this.name); const getMod = typeof subapp.getModule === "function" ? subapp.getModule() : subapp.getModule; if (getMod.then) { try { const mod = await getMod; // get subapp def from container again in case subapp was re-declared by a reloaded module // while getModule was in flight. const subappB = container.get(this.name); if (!subappB) { console.error("_getModule can't find the subapp in container for:", this.name); // eslint-disable-line no-console } else { subappB._module = mod; loadFeatures(this, subappB._getExport()?.wantFeatures); } container.updateReady(); return mod; } catch (err) { const mod = { loadError: err, captureErr: new Error(`load subapp ${this.name} module failed`), warned: false, }; const subappB = container.get(this.name); subappB._module = mod; return mod; } } else { // // allow specifying subapp statically (not using dynamic import) // TODO: update types // const mod = getMod as any; const subappB = container.get(this.name); subappB._module = mod; loadFeatures(this, subappB._getExport()?.wantFeatures); container.updateReady(); return mod; } } /** * Get a subapp's export from its module by looking for export resolveName * * @returns the subapp export or undefined */ function _getExport(): SubApp { if (!this._module || this.resolveName === false) { return {}; } if (this.resolveName) { return this._module[this.resolveName]; } return this._module.subapp || this._module.default || {}; } /** * **internal use only** * * @param opts - declare subapp options * @param override - define overrides * @returns subapp definition */ export function __declareSubApp(opts: SubAppOptions, override?: Partial): SubAppDef { const def = Object.assign( { _id: id++, _getModule, _module: undefined, _ssr: false, _features: {}, _mount: noop, _unmount: noop, _renderPipelines: [], _getExport, }, override, opts ); envHooks.getContainer().declare(opts.name, def); loadFeatures(def, opts.wantFeatures); return def; }