(function exposePageModuleRuntime(global) { "use strict"; const definitions = new Map(); let sealed = false; function register(feature, viewIds, lifecycle = {}) { if (sealed) throw new Error("Page module registry is already sealed"); if (!feature || !Array.isArray(viewIds) || !viewIds.length) { throw new Error("Page modules require a feature and at least one view ID"); } viewIds.forEach((viewId) => { if (definitions.has(viewId)) throw new Error(`Duplicate page module: ${viewId}`); definitions.set(viewId, Object.freeze({ feature, viewId, enter: Object.freeze([...(lifecycle.enter || [])]), leave: Object.freeze([...(lifecycle.leave || [])]), })); }); } function create(options) { sealed = true; const pages = options.pages; const actions = Object.freeze({ ...(options.actions || {}) }); const missing = pages.all.filter((page) => !definitions.has(page.id)).map((page) => page.id); if (missing.length) throw new Error(`Missing page modules: ${missing.join(", ")}`); function run(actionNames, context) { actionNames.forEach((actionName) => { const action = actions[actionName]; if (typeof action !== "function") throw new Error(`Unknown page action: ${actionName}`); action(context); }); } function beforeMount(viewId, previousView) { actions.closeTransientUi?.({ viewId, previousView }); if (previousView && previousView !== viewId) { run(definitions.get(previousView)?.leave || [], { viewId, previousView }); } } function afterMount(viewId, previousView) { const context = { viewId, previousView }; actions.applyAccess?.(context); run(definitions.get(viewId)?.enter || [], context); } return Object.freeze({ afterMount, beforeMount, get: (viewId) => definitions.get(viewId) || null, has: (viewId) => definitions.has(viewId), }); } global.XiaobaiPageModules = Object.freeze({ create, register }); })(window);