@dxos/app-framework 0.9.0 → 0.9.1-staging.ee54ba693a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/{capability-BOPAKKWG.mjs → capability-S44TE2H7.mjs} +9 -9
- package/dist/lib/browser/{chunk-66IXTIVK.mjs → chunk-3NQLTQCP.mjs} +6 -7
- package/dist/lib/browser/chunk-3NQLTQCP.mjs.map +7 -0
- package/dist/lib/browser/chunk-53HJHMS5.mjs +7 -0
- package/dist/lib/browser/chunk-53HJHMS5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-Y66ELD4U.mjs → chunk-KRJ4KK2W.mjs} +36 -7
- package/dist/lib/browser/chunk-KRJ4KK2W.mjs.map +7 -0
- package/dist/lib/browser/{chunk-KZUDO43J.mjs → chunk-LUH4Y5F2.mjs} +31 -23
- package/dist/lib/browser/chunk-LUH4Y5F2.mjs.map +7 -0
- package/dist/lib/browser/{chunk-CO3XLNUX.mjs → chunk-NKVRSMFN.mjs} +18 -18
- package/dist/lib/browser/chunk-NKVRSMFN.mjs.map +7 -0
- package/dist/lib/browser/{chunk-DC3WRPBV.mjs → chunk-OO53M5UK.mjs} +45 -12
- package/dist/lib/browser/chunk-OO53M5UK.mjs.map +7 -0
- package/dist/lib/browser/{chunk-IW44C7UL.mjs → chunk-OPTS3ZSN.mjs} +1 -1
- package/dist/lib/browser/chunk-OPTS3ZSN.mjs.map +7 -0
- package/dist/lib/browser/{chunk-HFLKXMT7.mjs → chunk-U5MESPM5.mjs} +61 -45
- package/dist/lib/browser/chunk-U5MESPM5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-XHS5KDNX.mjs → chunk-UGYCLOXE.mjs} +25 -25
- package/dist/lib/browser/chunk-UGYCLOXE.mjs.map +7 -0
- package/dist/lib/browser/{chunk-5GY3YOEL.mjs → chunk-VF37YTXJ.mjs} +5 -5
- package/dist/lib/browser/chunk-VF37YTXJ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FO3IYSLV.mjs → chunk-YUVQIOTB.mjs} +29 -37
- package/dist/lib/browser/chunk-YUVQIOTB.mjs.map +7 -0
- package/dist/lib/browser/cli/index.mjs +9 -9
- package/dist/lib/browser/cli/index.mjs.map +2 -2
- package/dist/lib/browser/common/activation-events.mjs +7 -7
- package/dist/lib/browser/common/capabilities.mjs +7 -7
- package/dist/lib/browser/config/index.mjs +8 -0
- package/dist/lib/browser/config/index.mjs.map +7 -0
- package/dist/lib/browser/core/activation-event.mjs +1 -1
- package/dist/lib/browser/core/capability.mjs +1 -1
- package/dist/lib/browser/core/plugin-manager.mjs +4 -4
- package/dist/lib/browser/core/plugin.mjs +12 -2
- package/dist/lib/browser/core/url-loader.mjs +3 -3
- package/dist/lib/browser/index.mjs +14 -10
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{process-manager-capability-GXNUO7AR.mjs → process-manager-capability-QK4BMKMN.mjs} +9 -9
- package/dist/lib/browser/testing/index.mjs +15 -15
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/testing/react.mjs +11 -11
- package/dist/lib/browser/testing/react.mjs.map +3 -3
- package/dist/lib/browser/ui/index.mjs +18 -10
- package/dist/lib/node-esm/{capability-KZWRTX7R.mjs → capability-3YRF77LV.mjs} +9 -9
- package/dist/lib/node-esm/chunk-2UPUZXGU.mjs +9 -0
- package/dist/lib/node-esm/chunk-2UPUZXGU.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-XIGPWXCQ.mjs → chunk-4SE7SX7N.mjs} +45 -12
- package/dist/lib/node-esm/chunk-4SE7SX7N.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-XOCUANHO.mjs → chunk-BMW6P6QA.mjs} +6 -7
- package/dist/lib/node-esm/chunk-BMW6P6QA.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-A5CHGAZE.mjs → chunk-DRT75WGD.mjs} +61 -45
- package/dist/lib/node-esm/chunk-DRT75WGD.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-XGBUKRCK.mjs → chunk-FKMVORZN.mjs} +31 -23
- package/dist/lib/node-esm/chunk-FKMVORZN.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-CTKEZHKF.mjs → chunk-GLH4LGHZ.mjs} +1 -1
- package/dist/lib/node-esm/chunk-GLH4LGHZ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-SX5NVETP.mjs → chunk-IL7O7IRX.mjs} +25 -25
- package/dist/lib/node-esm/chunk-IL7O7IRX.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-FSVGKTF6.mjs → chunk-ND2HETHD.mjs} +36 -7
- package/dist/lib/node-esm/chunk-ND2HETHD.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-KFZEB6BV.mjs → chunk-TLKYZKPW.mjs} +5 -5
- package/dist/lib/node-esm/chunk-TLKYZKPW.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-WK7OIQKI.mjs → chunk-VCPGX7WN.mjs} +29 -37
- package/dist/lib/node-esm/chunk-VCPGX7WN.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-NULBHQYS.mjs → chunk-XSZMX53L.mjs} +18 -18
- package/dist/lib/node-esm/chunk-XSZMX53L.mjs.map +7 -0
- package/dist/lib/node-esm/cli/index.mjs +9 -9
- package/dist/lib/node-esm/cli/index.mjs.map +2 -2
- package/dist/lib/node-esm/common/activation-events.mjs +7 -7
- package/dist/lib/node-esm/common/capabilities.mjs +7 -7
- package/dist/lib/node-esm/config/index.mjs +9 -0
- package/dist/lib/node-esm/config/index.mjs.map +7 -0
- package/dist/lib/node-esm/core/activation-event.mjs +1 -1
- package/dist/lib/node-esm/core/capability.mjs +1 -1
- package/dist/lib/node-esm/core/plugin-manager.mjs +4 -4
- package/dist/lib/node-esm/core/plugin.mjs +12 -2
- package/dist/lib/node-esm/core/url-loader.mjs +3 -3
- package/dist/lib/node-esm/index.mjs +14 -10
- package/dist/lib/node-esm/index.mjs.map +1 -1
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{process-manager-capability-TX5TA6YN.mjs → process-manager-capability-5S7WZ2JR.mjs} +9 -9
- package/dist/lib/node-esm/testing/index.mjs +15 -15
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/testing/react.mjs +11 -11
- package/dist/lib/node-esm/testing/react.mjs.map +3 -3
- package/dist/lib/node-esm/ui/index.mjs +18 -10
- package/dist/plugin/node-esm/index.mjs +414 -81
- package/dist/plugin/node-esm/index.mjs.map +4 -4
- package/dist/plugin/node-esm/meta.json +1 -1
- package/dist/types/src/cli/cli.d.ts +1 -1
- package/dist/types/src/common/activation-events.d.ts.map +1 -1
- package/dist/types/src/common/capabilities.d.ts +2 -2
- package/dist/types/src/common/capabilities.d.ts.map +1 -1
- package/dist/types/src/config/index.d.ts +2 -0
- package/dist/types/src/config/index.d.ts.map +1 -0
- package/dist/types/src/core/activation-event.d.ts +9 -6
- package/dist/types/src/core/activation-event.d.ts.map +1 -1
- package/dist/types/src/core/capability.d.ts +9 -3
- package/dist/types/src/core/capability.d.ts.map +1 -1
- package/dist/types/src/core/edge-registry-plugin-provider.d.ts +6 -11
- package/dist/types/src/core/edge-registry-plugin-provider.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manifest.d.ts +25 -7
- package/dist/types/src/core/plugin-manifest.d.ts.map +1 -1
- package/dist/types/src/core/plugin.d.ts +89 -91
- package/dist/types/src/core/plugin.d.ts.map +1 -1
- package/dist/types/src/core/registry.d.ts +17 -57
- package/dist/types/src/core/registry.d.ts.map +1 -1
- package/dist/types/src/core/url-loader.d.ts +2 -2
- package/dist/types/src/core/url-loader.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/history/capability.d.ts +1 -3
- package/dist/types/src/plugin-process-manager/history/capability.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/meta.d.ts +32 -2
- package/dist/types/src/plugin-process-manager/meta.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts +1 -4
- package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -1
- package/dist/types/src/testing/harness.d.ts +1 -1
- package/dist/types/src/testing/harness.d.ts.map +1 -1
- package/dist/types/src/testing/react.d.ts +6 -5
- package/dist/types/src/testing/react.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/App/App.stories.d.ts +2 -2
- package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +6 -0
- package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +6 -10
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/context.d.ts +6 -2
- package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/index.d.ts +11 -4
- package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/types.d.ts +52 -72
- package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useApp.d.ts +1 -1
- package/dist/types/src/ui/hooks/useCapabilities.d.ts +17 -1
- package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/composer/index.d.ts +11 -4
- package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/index.d.ts +1 -0
- package/dist/types/src/vite-plugin/index.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/load.d.ts +16 -0
- package/dist/types/src/vite-plugin/load.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/manifest.d.ts +16 -4
- package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/packages.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/docs/registry-spec.md +331 -0
- package/moon.yml +1 -0
- package/package.json +50 -39
- package/src/cli/cli.ts +2 -2
- package/src/common/activation-events.ts +3 -3
- package/src/common/capabilities.ts +18 -18
- package/src/config/index.ts +5 -0
- package/src/core/activation-event.ts +15 -8
- package/src/core/capability.ts +18 -6
- package/src/core/edge-registry-plugin-provider.ts +41 -42
- package/src/core/plugin-manager.test.ts +133 -137
- package/src/core/plugin-manager.ts +25 -19
- package/src/core/plugin-manifest.test.ts +5 -5
- package/src/core/plugin-manifest.ts +13 -10
- package/src/core/plugin.ts +58 -114
- package/src/core/registry.ts +20 -60
- package/src/core/url-loader.test.ts +2 -2
- package/src/core/url-loader.ts +23 -19
- package/src/index.ts +1 -0
- package/src/testing/harness.ts +5 -3
- package/src/testing/react.test.tsx +4 -2
- package/src/testing/react.tsx +10 -9
- package/src/testing/service.ts +2 -2
- package/src/testing/withPluginManager.stories.tsx +4 -2
- package/src/testing/withPluginManager.tsx +3 -1
- package/src/ui/components/App/App.stories.tsx +2 -2
- package/src/ui/components/PluginManager/PluginManagerProvider.ts +7 -0
- package/src/ui/components/Surface/SurfaceComponent.stories.tsx +22 -22
- package/src/ui/components/Surface/SurfaceComponent.tsx +90 -79
- package/src/ui/components/Surface/SurfaceProfilerContext.tsx +1 -1
- package/src/ui/components/Surface/context.ts +6 -4
- package/src/ui/components/Surface/index.ts +14 -3
- package/src/ui/components/Surface/types.test.ts +43 -51
- package/src/ui/components/Surface/types.ts +99 -64
- package/src/ui/hooks/useApp.test.tsx +1 -1
- package/src/ui/hooks/useApp.tsx +2 -2
- package/src/ui/hooks/useCapabilities.ts +49 -2
- package/src/vite-plugin/boot-loader/BootLoader.solid-stories.tsx +11 -11
- package/src/vite-plugin/boot-loader/loader.ts +3 -3
- package/src/vite-plugin/composer/index.ts +134 -61
- package/src/vite-plugin/import-map/index.ts +23 -7
- package/src/vite-plugin/index.ts +1 -0
- package/src/vite-plugin/load.ts +57 -0
- package/src/vite-plugin/manifest.test.ts +3 -3
- package/src/vite-plugin/manifest.ts +21 -10
- package/src/vite-plugin/packages.ts +0 -2
- package/tsconfig.json +5 -2
- package/dist/lib/browser/chunk-5GY3YOEL.mjs.map +0 -7
- package/dist/lib/browser/chunk-66IXTIVK.mjs.map +0 -7
- package/dist/lib/browser/chunk-CO3XLNUX.mjs.map +0 -7
- package/dist/lib/browser/chunk-DC3WRPBV.mjs.map +0 -7
- package/dist/lib/browser/chunk-FO3IYSLV.mjs.map +0 -7
- package/dist/lib/browser/chunk-HFLKXMT7.mjs.map +0 -7
- package/dist/lib/browser/chunk-IW44C7UL.mjs.map +0 -7
- package/dist/lib/browser/chunk-KZUDO43J.mjs.map +0 -7
- package/dist/lib/browser/chunk-XHS5KDNX.mjs.map +0 -7
- package/dist/lib/browser/chunk-Y66ELD4U.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-A5CHGAZE.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-CTKEZHKF.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-FSVGKTF6.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-KFZEB6BV.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NULBHQYS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SX5NVETP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-WK7OIQKI.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XGBUKRCK.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XIGPWXCQ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XOCUANHO.mjs.map +0 -7
- /package/dist/lib/browser/{capability-BOPAKKWG.mjs.map → capability-S44TE2H7.mjs.map} +0 -0
- /package/dist/lib/browser/{process-manager-capability-GXNUO7AR.mjs.map → process-manager-capability-QK4BMKMN.mjs.map} +0 -0
- /package/dist/lib/node-esm/{capability-KZWRTX7R.mjs.map → capability-3YRF77LV.mjs.map} +0 -0
- /package/dist/lib/node-esm/{process-manager-capability-TX5TA6YN.mjs.map → process-manager-capability-5S7WZ2JR.mjs.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/vite-plugin/boot-loader/loader.ts", "raw-loader:/__w/dxos/dxos/packages/sdk/app-framework/src/vite-plugin/boot-loader/loader-app/boot-loader.css
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\n// @ts-ignore — @types/babel__core present transitively but not declared here.\nimport * as babel from '@babel/core';\n// @ts-ignore — @babel/preset-typescript ships no .d.ts.\nimport babelPresetTypeScript from '@babel/preset-typescript';\n// @ts-ignore — babel-preset-solid ships no .d.ts.\nimport babelPresetSolid from 'babel-preset-solid';\nimport { build, type Plugin as EsbuildPlugin } from 'esbuild';\nimport { basename, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type Plugin } from 'vite';\n\nimport css from './loader-app/boot-loader.css?raw';\n// The loader-app Solid sources are inlined as raw text (never parsed by\n// dx-compile — app-framework is a React package, so its build can't compile\n// Solid JSX). They are compiled to a self-contained browser IIFE at the\n// consuming app's build time by {@link compileLoaderBundle} below.\nimport bridgeSrc from './loader-app/bridge.ts?raw';\nimport entrySrc from './loader-app/entry.tsx?raw';\nimport loaderSrc from './loader-app/Loader.tsx?raw';\nimport mountSrc from './loader-app/mount.tsx?raw';\nimport storeSrc from './loader-app/store.ts?raw';\nimport typesSrc from './loader-app/types.ts?raw';\n\n/**\n * Options for {@link bootLoaderPlugin}.\n */\nexport type BootLoaderOptions = {\n /**\n * Initial status text rendered by the loader (replaced via\n * `window.__bootLoader.status(...)` once the host starts firing phase callbacks).\n */\n status?: string;\n\n /**\n * Inline SVG markup for an optional brand mark rendered inside the progress\n * ring. The mark renders at full opacity with whatever fills the SVG declares,\n * so pass a colour-palette logo for the strongest visual identity. SVGs that\n * use `fill=\"currentColor\"` still inherit the loader's `prefers-color-scheme`\n * text colour. Leave empty/undefined to render only the ring.\n */\n markSvg?: string;\n\n /**\n * HTML entry filenames to inject the loader into. Defaults to `index.html` only\n * so auxiliary pages (`recovery.html`, `reset.html`, etc.) stay unobstructed.\n */\n include?: string[];\n};\n\nconst VIRTUAL_NS = 'boot-loader-app';\n\n// Relative-import graph of the loader-app, keyed by module name (no extension).\n// `tsx` modules carry JSX (compiled via `babel-preset-solid`); `ts` modules are\n// type-stripped only. `solid-js` imports introduced by the Solid transform\n// resolve from `node_modules` against `resolveDir`.\nconst MODULES: Record<string, { contents: string; tsx: boolean }> = {\n entry: { contents: entrySrc, tsx: true },\n mount: { contents: mountSrc, tsx: true },\n Loader: { contents: loaderSrc, tsx: true },\n bridge: { contents: bridgeSrc, tsx: false },\n store: { contents: storeSrc, tsx: false },\n types: { contents: typesSrc, tsx: false },\n};\n\n// Walk up from the compiled plugin to find a `node_modules` containing\n// `solid-js` (a dependency of this package). Used as esbuild's `resolveDir`.\nconst resolveDir = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Compile the loader-app from its inlined raw sources into a single\n * self-contained IIFE (Solid runtime bundled in) suitable for inlining into\n * `index.html`. Mirrors dx-compile's Solid pipeline: `@babel/preset-typescript`\n * strips types, then `babel-preset-solid` compiles JSX into reactive primitives.\n */\nconst compileLoaderBundle = async (): Promise<string> => {\n const virtualSolid = (): EsbuildPlugin => ({\n name: 'boot-loader-app-virtual',\n setup: (esbuild) => {\n esbuild.onResolve({ filter: /^\\.\\// }, (args) => {\n const name = args.path.replace(/^\\.\\//, '').replace(/\\.(tsx?|jsx?)$/, '');\n return name in MODULES ? { path: name, namespace: VIRTUAL_NS } : undefined;\n });\n\n esbuild.onLoad({ filter: /.*/, namespace: VIRTUAL_NS }, async (args) => {\n const module = MODULES[args.path];\n const result = await babel.transformAsync(module.contents, {\n filename: `${args.path}.${module.tsx ? 'tsx' : 'ts'}`,\n babelrc: false,\n configFile: false,\n // Presets run last-to-first: TS strips first, then Solid sees plain JSX.\n presets: [\n [babelPresetSolid, { generate: 'dom', hydratable: false }],\n [babelPresetTypeScript, { allowDeclareFields: true }],\n ],\n });\n if (!result?.code) {\n throw new Error(`babel-preset-solid returned no code for ${args.path}`);\n }\n return { contents: result.code, loader: 'js', resolveDir };\n });\n },\n });\n\n const result = await build({\n stdin: { contents: \"import './entry';\", loader: 'ts', resolveDir, sourcefile: 'boot-loader-entry.ts' },\n bundle: true,\n format: 'iife',\n platform: 'browser',\n target: 'es2020',\n minify: true,\n write: false,\n legalComments: 'none',\n define: { 'process.env.NODE_ENV': '\"production\"' },\n plugins: [virtualSolid()],\n });\n\n return result.outputFiles[0].text;\n};\n\nlet bundlePromise: Promise<string> | undefined;\nconst getLoaderBundle = (): Promise<string> => (bundlePromise ??= compileLoaderBundle());\n\n/**\n * Vite plugin that injects a Solid \"boot loader\" app into the host app's\n * `index.html`.\n *\n * The full-screen backdrop paints on the very first frame from an inline\n * `<style>` (before any JS bundle is fetched), so the user sees the loading\n * surface immediately on cold load instead of a blank document. A compiled,\n * self-contained Solid IIFE — inlined ahead of the app bundle — then renders\n * the determinate progress ring + status log into that backdrop and exposes the\n * host-facing driver on `window.__bootLoader`.\n *\n * The host app drives the loader (the React relay forwards `useApp`'s startup\n * progress):\n * - `window.__bootLoader.status(payload)` updates the status line per phase.\n * - `window.__bootLoader.progress(fraction)` grows the determinate ring (0–1).\n * - `window.__bootLoader.ready()` plays the dismissal outro, then self-removes.\n * - `window.__bootLoader.dismiss()` removes the loader immediately (fast path).\n *\n * Inject order (all at the start of `<body>`, except the stylesheet):\n * - `<style>` → `<head>` (parses before any bundled stylesheet).\n * - `<div id=\"boot-loader\">` → the static backdrop the CSS styles instantly.\n * - inline `<script>` config (`window.__BOOT_LOADER_CONFIG__`) → before the bundle.\n * - inline `<script>` loader bundle → renders the Solid app into the backdrop.\n *\n * Keeping the loader a sibling of `#root` (rather than a child) means\n * `createRoot(document.getElementById('root')).render(...)` does not fight the\n * loader for ownership; the framework explicitly dismisses after the first\n * React commit for a deterministic handoff.\n *\n * Color tokens are exposed as CSS custom properties (`--boot-loader-bg-light`,\n * etc.) in `boot-loader.css`, so consumers can override them at the document\n * level without re-parameterizing this plugin.\n */\nexport const bootLoaderPlugin = ({ status, markSvg, include = ['index.html'] }: BootLoaderOptions = {}): Plugin => {\n return {\n name: 'app-framework:boot-loader',\n async transformIndexHtml(_html, ctx) {\n const filename = basename(ctx.filename ?? 'index.html');\n if (!include.includes(filename)) {\n return;\n }\n\n const bundle = await getLoaderBundle();\n // Authoritative backdrop id: injected here, passed to the bundle via\n // config (so `entry.tsx` reads it), and mirrored by the CSS selector in\n // `boot-loader.css`. The inner DOM ↔ CSS contract is guarded by the story.\n const rootId = 'boot-loader';\n return [\n {\n tag: 'style',\n injectTo: 'head',\n children: css,\n },\n {\n tag: 'div',\n injectTo: 'body-prepend',\n attrs: {\n id: rootId,\n role: 'status',\n 'aria-live': 'polite',\n 'aria-label': 'Initializing',\n },\n children: '',\n },\n {\n tag: 'script',\n injectTo: 'body-prepend',\n children: `window.__BOOT_LOADER_CONFIG__=${JSON.stringify({ rootId, markSvg, status })};`,\n },\n {\n tag: 'script',\n injectTo: 'body-prepend',\n children: bundle,\n },\n ];\n },\n };\n};\n", "/*\n * Boot loader stylesheet \u2014 injected into the host's `<head>` by `bootLoaderPlugin`\n * so the full-screen backdrop paints before any JS bundle is fetched. The Solid\n * `Loader` renders the ring + status into the `#boot-loader` backdrop; this\n * sheet styles both. Class/id names here form a contract with `Loader.tsx`,\n * guarded by `BootLoader.solid-stories.tsx` (it mounts the real component).\n */\n\nbody {\n margin: 0;\n overflow: hidden;\n}\n\n/*\n * Defaults match `@dxos/ui-theme`'s `--color-base-surface`, which resolves to\n * Tailwind's `neutral-50` / `neutral-950` in light / dark mode respectively\n * (see `packages/ui/ui-theme/src/css/theme/semantic.css`). Hosts can override\n * with the `--boot-loader-bg-*` / `--boot-loader-fg-*` custom properties on\n * `:root` if they need a different palette. Keeping the boot loader's\n * background identical to the app's `body` eliminates the flash on handoff\n * to the rendered React shell.\n */\n#boot-loader {\n --color-composer-100: rgb(5 40 61);\n --color-composer-200: rgb(10 75 105);\n --color-composer-300: rgb(1 122 183);\n --color-composer-400: rgb(6 197 253);\n\n /*\n * Caps the disc / mark at the design pixel sizes on roomy viewports while\n * shrinking proportionally on narrow ones (`vmin` follows the smaller of\n * width / height) so neither the ring nor the mark crops on phones.\n */\n --boot-loader-disc-size: min(384px, 80vmin);\n /*\n * Match the React `Placeholder`'s logo box (`h-[300px] w-[300px]` at the\n * `stage >= 1` keyframe) so the brand mark doesn't visibly jump size when\n * the loader hands off \u2014 the responsive cap keeps the same 300/384 ratio\n * (\u224878%) at any viewport width.\n */\n --boot-loader-mark-size: min(300px, 62.5vmin);\n --boot-loader-status-gap: 32px;\n\n position: fixed;\n inset: 0;\n z-index: 10;\n font-size: 13px;\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n sans-serif;\n /*\n * Dismissal outro \u2014 `mountLoader` toggles `data-dismissing` on this element\n * when the host calls `__bootLoader.ready()`; the loader cross-fades out over\n * the real app shell rendering beneath it, and removes itself once this\n * opacity transition completes (a fallback timer covers reduced-motion).\n */\n transition: opacity 500ms ease-out;\n}\n\n#boot-loader {\n background: var(--boot-loader-bg-light, #fafafa);\n color: var(--boot-loader-fg-light, #0a0a0a);\n --boot-loader-accent: var(--boot-loader-accent-light, var(--color-composer-200));\n}\n\n@media (prefers-color-scheme: dark) {\n #boot-loader {\n background: var(--boot-loader-bg-dark, #0a0a0a);\n color: var(--boot-loader-fg-dark, #f0f0f0);\n --boot-loader-accent: var(--boot-loader-accent-dark, var(--color-composer-300));\n }\n}\n\n#boot-loader[data-dismissing] {\n opacity: 0;\n}\n\n/* Gently shrink the disc + mark as the loader fades, echoing the prior handoff. */\n#boot-loader[data-dismissing] #boot-loader-disc {\n transform: translate(-50%, -50%) scale(0.92);\n transition: transform 500ms ease-out;\n}\n\n/*\n * Stack the ring (the SVG `#boot-loader-ring`) and the brand mark in the same\n * grid cell so the mark sits centered inside the circle.\n */\n#boot-loader-disc {\n position: absolute;\n top: 50%;\n left: 50%;\n display: grid;\n place-items: center;\n width: var(--boot-loader-disc-size);\n height: var(--boot-loader-disc-size);\n transform: translate(-50%, -50%);\n}\n\n#boot-loader-disc > * {\n grid-column: 1;\n grid-row: 1;\n}\n\n/*\n * Default to grayscale so the mark reads as a quiet monochrome silhouette\n * before any host-driven progress lands; the brand palette swaps in once\n * `Loader.tsx` sets `data-host-driven` on the disc (the first\n * `__bootLoader.progress()` call). Hover keeps a parallel reveal affordance\n * for inspection in the storybook. The 1000ms ease lets the grayscale \u2192 color\n * transition play through the activation phase rather than snapping.\n */\n#boot-loader-mark {\n width: var(--boot-loader-mark-size);\n height: var(--boot-loader-mark-size);\n display: flex;\n align-items: center;\n justify-content: center;\n filter: grayscale(100%);\n transition: filter 1000ms ease-out;\n}\n\n/*\n * `grayscale(0%)` (identity) rather than `none` \u2014 `filter: none` changes\n * the filter function list and most engines treat that as a discrete\n * transition (snap, not ease). Keeping `grayscale(...)` on both sides of\n * the rule lets the browser interpolate the percentage smoothly.\n */\n#boot-loader-disc[data-host-driven] #boot-loader-mark,\n#boot-loader-mark:hover {\n filter: grayscale(0%);\n}\n\n#boot-loader-mark svg {\n width: 100%;\n height: 100%;\n /*\n * The host SVG carries its own brand-palette fills, so we don't apply a\n * `color` cascade here. SVGs that intentionally use `fill=\"currentColor\"`\n * still pick up the loader's text colour via `#boot-loader`'s `color`.\n */\n}\n\n/*\n * Circular determinate progress \u2014 a single SVG `<path>` arc that sweeps\n * anticlockwise from 12 o'clock, its angle growing with progress (the `d` is\n * recomputed by the component each tick). There is no static track;\n * `stroke-linecap: round` rounds the trailing edge, and `marker-end` paints the\n * leading-edge dot. Stroke width is in viewBox units so it scales with the disc.\n */\n#boot-loader-ring {\n width: var(--boot-loader-disc-size);\n height: var(--boot-loader-disc-size);\n overflow: visible;\n /*\n * Fade the arc linearly from the head (the marker, fully opaque) back to the\n * tail (12 o'clock, transparent). A conic-gradient mask does this along the\n * curve \u2014 `Loader.tsx` writes the eased progress into `--boot-loader-arc`\n * (0\u2013100), and the arc occupies the conic range `(100 - arc)%`\u2026`100%`, so the\n * head sits at `(100 - arc)%` (opaque) and the tail at `100%` (transparent).\n * NOTE: We start at -1.16deg so that we don't mask the marker.\n */\n --boot-loader-arc: 0;\n mask: conic-gradient(\n from -1.16deg at 50% 50%,\n transparent 0,\n transparent calc((100 - var(--boot-loader-arc)) * 1%),\n #000 calc((100 - var(--boot-loader-arc)) * 1%),\n transparent 100%\n );\n -webkit-mask: conic-gradient(\n from -1.16deg at 50% 50%,\n transparent 0,\n transparent calc((100 - var(--boot-loader-arc)) * 1%),\n #000 calc((100 - var(--boot-loader-arc)) * 1%),\n transparent 100%\n );\n}\n\n/*\n * The leading-edge dot's layer \u2014 same geometry as `#boot-loader-ring` but with no\n * mask, so the dot renders as a full circle (the ring's conic fade mask would\n * otherwise bisect it where it sits on the mask's transparent\u2192opaque edge).\n */\n#boot-loader-ring-head {\n width: var(--boot-loader-disc-size);\n height: var(--boot-loader-disc-size);\n overflow: visible;\n}\n\n.boot-loader-ring-progress {\n fill: none;\n stroke: var(--boot-loader-accent);\n /* viewBox units: ~1.9px on the 384px disc, scaling down on smaller viewports. */\n stroke-width: 0.5;\n opacity: 0.5;\n stroke-linecap: butt;\n overflow: visible;\n /* Dashed line: dash + gap lengths in viewBox units (~2 units \u2248 7.7px @384px). */\n /* stroke-dasharray: 2 1; */\n}\n\n/* The `marker-end` dot at the arc's leading edge. */\n.boot-loader-ring-marker {\n fill: var(--boot-loader-accent);\n stroke: none;\n overflow: visible;\n /* opacity: 0.5; */\n}\n\n#boot-loader-status {\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n /* \n * Sit just below the centered disc \u2014 half the disc plus the configured gap.\n */\n transform: translate(0, calc(var(--boot-loader-disc-size) / 2 + var(--boot-loader-status-gap)));\n /*\n * Slightly de-emphasised vs body text so the brand mark + ring stay the\n * dominant focus, but high enough to remain legible on both light and dark\n * backgrounds without a custom palette.\n */\n opacity: 0.5;\n /*\n * Terminal-style log viewport (3 rows at the default `line-height`) over\n * a vertically-stacked track of every status the driver has emitted. The\n * track is bottom-anchored via `justify-content: flex-end` so the newest\n * line always sits on the last visible row, older lines stack above it,\n * and anything that doesn't fit is clipped at the top by\n * `overflow: hidden`. The driver runs a FLIP-style transform animation\n * per append so each new line slides up from below the bottom edge \u2014\n * independent of any `scroll-behavior` smooth-scroll support, which\n * Playwright/headless Chrome strips even from spec-compliant\n * `scrollTo({ behavior: 'smooth' })` calls.\n */\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n height: 4.5em;\n line-height: 1.5;\n letter-spacing: 0.01em;\n /* \n * Fixed-width digits so the `(i/n)` counter on range-bearing status\n * updates (\"Loading plugins (12/80)\") doesn't jitter as the index\n * ticks through different glyph widths. \n */\n font-variant-numeric: tabular-nums;\n text-align: center;\n overflow: hidden;\n}\n\n#boot-loader-status-fade {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 32px;\n background: linear-gradient(to bottom, var(--boot-loader-bg-light, #fafafa), transparent);\n z-index: 1;\n}\n@media (prefers-color-scheme: dark) {\n #boot-loader-status-fade {\n background: linear-gradient(to bottom, var(--boot-loader-bg-dark, #0a0a0a), transparent);\n }\n}\n\n#boot-loader-rss {\n background: var(--boot-loader-bg-light, #fafafa);\n text-wrap: balance;\n}\n@media (prefers-color-scheme: dark) {\n #boot-loader-rss {\n background: var(--boot-loader-bg-dark, #0a0a0a);\n }\n}\n\n/*\n * Track of every appended `.boot-loader-status-line`.\n */\n#boot-loader-status-track {\n display: flex;\n flex-direction: column;\n /*\n * Resting transform is `translateY(0)` \u2014 the bottom-anchored flex parent\n * already positions the newest line on the last visible row. On each append\n * `Loader.tsx` runs a one-shot FLIP: snap to `translateY(<lineHeight>px)` with\n * no transition (placing the new line just below the viewport), force a\n * reflow, then animate back to 0 so the track rises by one line-height and the\n * new entry slides up into the bottom row.\n */\n transform: translateY(0);\n transition: transform 500ms ease-out;\n}\n\n/* Honour reduced-motion preferences explicitly \u2014 `transition` doesn't auto-respect it. */\n@media (prefers-reduced-motion: reduce) {\n #boot-loader-status-track {\n transition: none;\n }\n}\n\n.boot-loader-status-line {\n flex: 0 0 auto;\n height: 1.5em;\n white-space: nowrap;\n}\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type LoaderStore } from './store';\nimport { type BootLoaderApi } from './types';\n\n/**\n * Wrap a reactive {@link LoaderStore} as the imperative `window.__bootLoader`\n * facade the host app drives. `status` / `progress` write into the store;\n * `ready` plays the graceful dismissal outro; `dismiss` is the immediate-remove\n * backstop for the fast-load path (and a no-op once an outro is already in\n * flight, so a late `dismiss()` from the framework never cuts the animation).\n */\nexport const createBridge = (store: LoaderStore, dismissNow: () => void): BootLoaderApi => ({\n status: (payload) => store.pushStatus(payload),\n progress: (fraction) => store.setProgress(fraction),\n ready: () => store.ready(),\n dismiss: () => {\n if (store.phase() === 'dismissing') {\n return;\n }\n dismissNow();\n },\n});\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { mountLoader } from './mount';\nimport { DEFAULT_ROOT_ID } from './types';\n\n//\n// Production entry \u2014 bundled to a self-contained IIFE by `bootLoaderPlugin` and\n// inlined into `index.html` ahead of the app bundle. Mounts the loader into the\n// static backdrop using the config the plugin baked in just before this script\n// (including the backdrop id, so the id has a single source). The storybook\n// does NOT use this entry; it imports `mountLoader` directly so Vite compiles\n// the Solid source with HMR.\n//\n\nconst config = window.__BOOT_LOADER_CONFIG__ ?? {};\nconst el = document.getElementById(config.rootId ?? DEFAULT_ROOT_ID);\nif (el) {\n mountLoader(el, config);\n}\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Component, For, createEffect, createSignal, onCleanup, onMount } from 'solid-js';\n\nimport { type LoaderStore } from './store';\n\n// Ring geometry in the SVG's `0 0 100 100` viewBox. The radius leaves a couple\n// of units of padding so the stroke, its round cap, and the end marker aren't\n// clipped at the viewBox edge.\nconst RING_RADIUS = 48;\nconst RING_CENTER = 50;\n// Leading-edge marker: a small dot drawn at the arc's head in an unmasked layer.\nconst MARKER_RADIUS = 1; // viewBox units \u2192 ~3.8px on the 384px disc\n\n/**\n * Read an element's *current animated* translateY (px) from its live transform\n * matrix \u2014 the interpolated value mid-transition, not the last-written property.\n * Used by the status FLIP so successive appends chain off the in-flight position\n * instead of yanking the track back to a fixed invert target.\n */\nconst readTranslateY = (element: HTMLElement): number => {\n const computed = getComputedStyle(element).transform;\n if (!computed || computed === 'none') {\n return 0;\n }\n const match = computed.match(/matrix.*\\(([^)]+)\\)/);\n if (!match) {\n return 0;\n }\n const values = match[1].split(',');\n // 2D `matrix(a, b, c, d, tx, ty)` \u2192 ty at index 5; 3D `matrix3d(...)` \u2192 ty at 13.\n if (values.length === 6) {\n return Number.parseFloat(values[5]) || 0;\n }\n if (values.length === 16) {\n return Number.parseFloat(values[13]) || 0;\n }\n return 0;\n};\n\nexport type LoaderProps = {\n /** Reactive source of truth for progress, status lines, and lifecycle phase. */\n store: LoaderStore;\n /** Inline SVG markup for the brand mark rendered inside the ring. */\n markSvg?: string;\n};\n\n/**\n * The boot loader, authored as a single Solid component \u2014 the one source of\n * truth for the loader DOM. `bootLoaderPlugin` bundles this (Solid runtime\n * inlined) into `index.html`; the storybook mounts the very same component, so\n * the two can no longer drift. The DOM structure, ids, and classes mirror\n * `boot-loader.css`.\n *\n * The full-screen backdrop (`#boot-loader`) is injected as static markup so it\n * paints from CSS before this bundle executes; this component renders the disc\n * and status log *into* that backdrop. The dismissal outro (fading `#boot-loader`)\n * and its teardown are owned by {@link mountLoader}, which has the host element.\n */\nexport const Loader: Component<LoaderProps> = (props) => {\n let trackRef: HTMLDivElement | undefined;\n let previousCount = props.store.lines().length;\n\n // FLIP-style slide on each appended line: snap the track down by one\n // line-height (chained off any in-flight translate) with no transition, force\n // a reflow, then animate back to translateY(0) so the new entry rises from\n // below the bottom-anchored viewport. Range ticks (length unchanged) skip it.\n createEffect(() => {\n const count = props.store.lines().length;\n const track = trackRef;\n if (track && count > previousCount) {\n const currentY = readTranslateY(track);\n const lineHeight = track.lastElementChild?.getBoundingClientRect().height ?? 0;\n track.style.transition = 'none';\n track.style.transform = `translateY(${currentY + lineHeight}px)`;\n void track.offsetHeight;\n track.style.transition = '';\n track.style.transform = 'translateY(0)';\n }\n previousCount = count;\n });\n\n // Eased display progress. A `<path>`'s `d` can't be CSS-transitioned, so the\n // arc would snap on every store tick; instead we ease a displayed value toward\n // the store's progress with a requestAnimationFrame loop (~per-frame lerp) and\n // recompute the path each frame. This restores the compositor-smooth growth\n // the old `transition: stroke-dashoffset` gave, while keeping the path +\n // `marker-end` (the marker rides the arc's recomputed end automatically).\n const [shown, setShown] = createSignal(props.store.progress());\n let raf: number | undefined;\n const animate = () => {\n const target = props.store.progress();\n const current = shown();\n // Snap when within a hair to settle; otherwise lerp ~18% of the gap/frame.\n const next = Math.abs(target - current) < 0.05 ? target : current + (target - current) * 0.18;\n if (next !== current) {\n setShown(next);\n }\n raf = requestAnimationFrame(animate);\n };\n\n onMount(() => {\n raf = requestAnimationFrame(animate);\n });\n\n onCleanup(() => {\n if (raf != null) {\n cancelAnimationFrame(raf);\n }\n });\n\n // Determinate ring as an SVG `<path>` arc: an anticlockwise sweep starting at\n // 12 o'clock whose angle grows with the eased `shown()` progress. The sweep is\n // capped just shy of a full turn so the single arc command never degenerates at\n // 100%. The leading-edge dot is its `head` point, rendered separately (below) in\n // an *unmasked* layer \u2014 drawing it via `marker-end` on this path would put it\n // under the ring's conic fade mask, whose hard edge bisects the dot into a\n // half-circle.\n const arc = () => {\n const fraction = Math.min(shown() / 100, 0.9999);\n const sweep = fraction * 2 * Math.PI;\n const start = -Math.PI / 2; // 12 o'clock\n const end = start - sweep; // anticlockwise (decreasing angle)\n const x0 = RING_CENTER + RING_RADIUS * Math.cos(start);\n const y0 = RING_CENTER + RING_RADIUS * Math.sin(start);\n const headX = RING_CENTER + RING_RADIUS * Math.cos(end);\n const headY = RING_CENTER + RING_RADIUS * Math.sin(end);\n const largeArc = sweep > Math.PI ? 1 : 0;\n // sweep-flag 0 = anticlockwise (negative-angle) direction.\n return { d: `M ${x0} ${y0} A ${RING_RADIUS} ${RING_RADIUS} 0 ${largeArc} 0 ${headX} ${headY}`, headX, headY };\n };\n\n // Once host-driven, the brand mark eases grayscale \u2192 colour and stays there.\n const isHostDriven = () => props.store.phase() !== 'creep';\n\n return (\n <>\n <div id='boot-loader-disc' data-host-driven={isHostDriven() ? '' : undefined}>\n <svg\n id='boot-loader-ring'\n viewBox='0 0 100 100'\n aria-hidden='true'\n style={{ '--boot-loader-arc': String(shown()) }}\n >\n {shown() > 0 ? <path class='boot-loader-ring-progress' d={arc().d} /> : null}\n </svg>\n {/* Leading-edge dot in its own unmasked layer (see `arc()`), so the ring's fade mask\n never clips it. Stacked over `#boot-loader-ring` via the disc grid. */}\n {shown() > 0 ? (\n <svg id='boot-loader-ring-head' viewBox='0 0 100 100' aria-hidden='true'>\n <circle class='boot-loader-ring-marker' cx={arc().headX} cy={arc().headY} r={MARKER_RADIUS} />\n </svg>\n ) : null}\n {props.markSvg ? <div id='boot-loader-mark' innerHTML={props.markSvg} /> : null}\n </div>\n <div id='boot-loader-status'>\n <div id='boot-loader-status-fade' />\n <div id='boot-loader-status-track' ref={trackRef}>\n <For each={props.store.lines()}>{(line) => <div class='boot-loader-status-line'>{line.text}</div>}</For>\n </div>\n </div>\n </>\n );\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { createEffect } from 'solid-js';\nimport { render } from 'solid-js/web';\n\nimport { createBridge } from './bridge';\nimport { Loader } from './Loader';\nimport { createLoaderStore } from './store';\nimport { type BootLoaderConfig } from './types';\n\n/** Fallback teardown if the outro's `transitionend` never fires (e.g. no opacity transition). */\nconst OUTRO_FALLBACK_MS = 800;\n\n/**\n * Mount the boot loader into a host element (`#boot-loader`, the static backdrop\n * the plugin injects \u2014 or any container in the storybook) and install the\n * `window.__bootLoader` facade. Renders the disc + status into the host, toggles\n * `data-dismissing` on it for the outro, and removes everything once the outro\n * completes.\n *\n * Returns a disposer that tears the loader down immediately (idempotent).\n */\nexport const mountLoader = (el: HTMLElement, config: BootLoaderConfig = {}): (() => void) => {\n const store = createLoaderStore(config.status);\n\n let removed = false;\n // Forward-declared so `remove` can dispose the Solid render created below.\n let disposeRender: (() => void) | undefined;\n\n const remove = (): void => {\n if (removed) {\n return;\n }\n removed = true;\n el.removeEventListener('transitionend', handleTransitionEnd);\n store.dispose();\n disposeRender?.();\n el.remove();\n if (window.__bootLoader === api) {\n delete window.__bootLoader;\n }\n };\n\n const handleTransitionEnd = (event: TransitionEvent): void => {\n if (event.propertyName === 'opacity' && store.phase() === 'dismissing') {\n remove();\n }\n };\n el.addEventListener('transitionend', handleTransitionEnd);\n\n disposeRender = render(() => {\n // Drive the backdrop's outro from the host element (Solid owns the host's\n // children; the host attribute is toggled imperatively within this owner).\n createEffect(() => {\n const dismissing = store.phase() === 'dismissing';\n el.toggleAttribute('data-dismissing', dismissing);\n if (dismissing) {\n setTimeout(remove, OUTRO_FALLBACK_MS);\n }\n });\n return <Loader store={store} markSvg={config.markSvg} />;\n }, el);\n\n const api = createBridge(store, remove);\n window.__bootLoader = api;\n\n return remove;\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Accessor, createSignal } from 'solid-js';\n\nimport { type StatusPayload } from './types';\n\n//\n// Creep tuning. The ring auto-creeps toward a moving ceiling so a long\n// activation silence never reads as a frozen disc. See the original\n// hand-written driver for the rationale behind each constant.\n//\n\n/** Creep timer cadence, in milliseconds. */\nexport const CREEP_TICK_MS = 100;\n/** State-1 ease rate \u2014 a gentle \"we're alive\" hint before real progress lands. */\nexport const STATE_1_RATE = 0.05;\n/** State-1 asymptote (percent) the creep eases toward before host progress. */\nexport const STATE_1_ASYMPTOTE = 40;\n/** State-2 ease rate \u2014 bridges the gap between sparse host `progress()` calls. */\nexport const STATE_2_RATE = 0.05;\n/** State-2 lead (percent) the ceiling sits ahead of the last host value. */\nexport const STATE_2_BUMP = 15;\n/** Hard ceiling the auto-creep never crosses (host must drive the rest). */\nexport const ABSOLUTE_CEILING = 90;\n\n/** Loader lifecycle phase. */\nexport type Phase = 'creep' | 'host' | 'dismissing';\n\n/** A single rendered status line; `id` keys the `<For>` and survives in-place range ticks. */\nexport type StatusLine = {\n id: number;\n text: string;\n event?: string;\n module?: string;\n};\n\n/**\n * Asymptotic ease \u2014 `next = raw + (ceiling - raw) * rate`, clamped so it never\n * overshoots (or regresses past) the ceiling. Pure; unit-tested.\n */\nexport const easeToward = (raw: number, ceiling: number, rate: number): number =>\n raw >= ceiling - 0.1 ? raw : raw + (ceiling - raw) * rate;\n\n/**\n * Clamp a host-supplied fraction to a percent in [0, 100]. Invalid / negative /\n * non-finite values collapse to 0 rather than poisoning the CSS var. Pure;\n * unit-tested.\n */\nexport const clampPercent = (fraction?: number): number =>\n typeof fraction !== 'number' || !Number.isFinite(fraction) || fraction < 0 ? 0 : Math.min(1, fraction) * 100;\n\n/** Display text for a payload \u2014 appends the `(index/total)` suffix when a range is present. */\nexport const displayText = (payload: StatusPayload): string =>\n payload.range ? `${payload.humanized} (${payload.range.index}/${payload.range.total})` : payload.humanized;\n\n/**\n * Reactive loader store \u2014 owns the progress percent, the status-line log, and\n * the lifecycle phase, plus the auto-creep timer. All DOM-free, so the creep\n * math and status reduction are testable as plain functions; `Loader.tsx` binds\n * the accessors to the DOM and `bridge.ts` wraps the mutators as the imperative\n * `window.__bootLoader` facade.\n */\nexport type LoaderStore = {\n /** Progress as a percent in [0, 100] (the CSS `--boot-loader-bar-progress` value). */\n progress: Accessor<number>;\n /** Appended status lines, newest last. */\n lines: Accessor<StatusLine[]>;\n /** Current lifecycle phase. */\n phase: Accessor<Phase>;\n /** Apply a status update (append, or replace-in-place for range ticks). */\n pushStatus: (payload: StatusPayload) => void;\n /** Enter host-driven progress with `fraction` \u2208 [0, 1]; never regresses. */\n setProgress: (fraction?: number) => void;\n /** Snap to 100%, stop the creep, and enter the dismissing phase. */\n ready: () => void;\n /** Stop the creep timer (call on teardown). */\n dispose: () => void;\n};\n\nexport const createLoaderStore = (initialStatus?: string): LoaderStore => {\n const [progress, setProgressPct] = createSignal(0);\n const [lines, setLines] = createSignal<StatusLine[]>(initialStatus ? [{ id: 0, text: initialStatus }] : []);\n const [phase, setPhase] = createSignal<Phase>('creep');\n\n let creepCeiling = STATE_1_ASYMPTOTE;\n let creepRate = STATE_1_RATE;\n let nextId = initialStatus ? 1 : 0;\n let timer: ReturnType<typeof setInterval> | null = null;\n\n const startCreep = (): void => {\n if (timer == null) {\n timer = setInterval(() => setProgressPct((raw) => easeToward(raw, creepCeiling, creepRate)), CREEP_TICK_MS);\n }\n };\n\n const stopCreep = (): void => {\n if (timer != null) {\n clearInterval(timer);\n timer = null;\n }\n };\n\n const pushStatus = (payload: StatusPayload): void => {\n const text = displayText(payload);\n setLines((current) => {\n const previous = current.at(-1);\n // Dedup back-to-back identical transitions (same text + structured fields).\n if (\n previous &&\n previous.text === text &&\n (previous.event ?? null) === (payload.event ?? null) &&\n (previous.module ?? null) === (payload.module ?? null)\n ) {\n return current;\n }\n // Range tick \u2014 replace the current line in place rather than appending,\n // so a counted phase produces one entry with an updating suffix.\n if (payload.range && previous) {\n return [...current.slice(0, -1), { ...previous, text }];\n }\n return [...current, { id: nextId++, text, event: payload.event, module: payload.module }];\n });\n };\n\n const setProgress = (fraction?: number): void => {\n setPhase('host');\n const pct = clampPercent(fraction);\n // The ring never regresses: hold the current value if the host reports lower.\n setProgressPct((current) => Math.max(current, pct));\n // Switch the creep to its state-2 cadence and lead the host value by a bump.\n creepRate = STATE_2_RATE;\n creepCeiling = Math.min(Math.max(creepCeiling, pct + STATE_2_BUMP), ABSOLUTE_CEILING);\n startCreep();\n };\n\n const ready = (): void => {\n stopCreep();\n setProgressPct(100);\n setPhase('dismissing');\n };\n\n const dispose = (): void => stopCreep();\n\n startCreep();\n\n return { progress, lines, phase, pushStatus, setProgress, ready, dispose };\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\n/**\n * Status payload accepted by `window.__bootLoader.status(...)`. The caller owns\n * formatting \u2014 `humanized` is the exact text rendered \u2014 while `event` / `module`\n * carry the structured activation ids for the boot trace, and `range` drives an\n * in-place `(index/total)` counter for long counted phases.\n */\nexport type StatusPayload = {\n /**\n * Raw activation event key (e.g. `dxos.org/plugin/observability/activate`)\n * when the transition is event-level.\n */\n event?: string;\n\n /**\n * Raw module id (e.g. `org.dxos.plugin.observability.module.ReactSurface`)\n * when the transition is module-level.\n */\n module?: string;\n\n /** Exact text to display (e.g. \"Activating Observability: react-surface\"). */\n humanized: string;\n\n /**\n * Optional `(index/total)` tick. When present the loader replaces the current\n * line in place (\"Loading plugins (12/80)\") instead of appending a new entry \u2014\n * keeps the visible log compact during long counted phases.\n */\n range?: { index: number; total: number };\n};\n\n/**\n * Imperative facade exposed on `window.__bootLoader`, installed by the inlined\n * loader bundle and driven by the host app (the React relay forwards `useApp`'s\n * startup progress through it).\n */\nexport type BootLoaderApi = {\n /** Update the visible status line. */\n status: (payload: StatusPayload) => void;\n /** Enter host-driven progress \u2014 `fraction` \u2208 [0, 1]. */\n progress: (fraction?: number) => void;\n /** Play the dismissal outro, then remove the loader DOM (graceful path). */\n ready: () => void;\n /** Remove the loader DOM immediately (fast-load backstop / terminal). */\n dismiss: () => void;\n};\n\n/**\n * Config baked into `index.html` by `bootLoaderPlugin` ahead of the loader\n * bundle, so the compiled app stays static (compiled once, independent of the\n * host's brand mark / initial status).\n */\nexport type BootLoaderConfig = {\n /**\n * Id of the static backdrop element the plugin injects and the loader mounts\n * into \u2014 the single coupling between `transformIndexHtml` and the app. The\n * plugin owns the authoritative value and passes it here so `entry.tsx` reads\n * it rather than hardcoding (the CSS selector mirrors it \u2014 see `boot-loader.css`).\n */\n rootId?: string;\n /** Inline SVG markup for the brand mark rendered inside the ring. */\n markSvg?: string;\n /** Initial status text rendered before the host fires its first `status(...)`. */\n status?: string;\n};\n\n/** Fallback backdrop id when no config is present (kept in sync with `loader.ts` + the CSS). */\nexport const DEFAULT_ROOT_ID = 'boot-loader';\n\ndeclare global {\n interface Window {\n __bootLoader?: BootLoaderApi;\n __BOOT_LOADER_CONFIG__?: BootLoaderConfig;\n }\n}\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport * as FetchHttpClient from '@effect/platform/FetchHttpClient';\nimport * as HttpClient from '@effect/platform/HttpClient';\nimport * as HttpClientRequest from '@effect/platform/HttpClientRequest';\nimport * as HttpClientResponse from '@effect/platform/HttpClientResponse';\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n\nimport { BaseError } from '@dxos/errors';\nimport { PLUGIN_ENTRY_FILENAME } from '@dxos/protocols';\n\n/**\n * Default port the Vite plugin (`composerPlugin`) binds the dev server to.\n *\n * Shared single source of truth — `composerPlugin` reads it as the default\n * port, and the host's \"Load Dev Plugin\" affordance pre-fills the manifest URL\n * with `http://localhost:${PLUGIN_DEV_SERVER_PORT}/manifest.json`. Lives in\n * app-framework rather than `@dxos/protocols` because the constant is a\n * client-side convention (host loader + Vite plugin) rather than a wire-level\n * protocol.\n */\nexport const PLUGIN_DEV_SERVER_PORT = 3967;\n\n/**\n * Tagged error for manifest fetch / parse failures. Construction sites set\n * `context.manifestUrl` and `context.reason` (one of `'fetch-failed' |\n * 'http-error' | 'parse-failed' | 'invalid'`) so handlers can route on the\n * specific failure mode.\n */\nexport class PluginManifestError extends BaseError.extend('PluginManifestError', 'Plugin manifest is invalid') {}\n\n/**\n * Schema for a third-party plugin manifest.\n *\n * Production manifests are published as a sibling of the plugin's entry module\n * ({@link PLUGIN_ENTRY_FILENAME}) and advertise every file the plugin needs at\n * runtime so the host can eagerly cache them for offline use.\n *\n * Dev manifests (served by `vite dev` via {@link composerPlugin}) set `devEntry`\n * to point at the unbundled source entry. The host's loader treats the presence\n * of `devEntry` as the dev-mode signal: it imports the entry directly from the\n * dev server, skips eager asset caching, and skips static stylesheet injection\n * (Vite handles CSS via runtime `<style>` injection during HMR). `assets` is not\n * required to enumerate every file in dev mode — chunks and styles flow through\n * the dev server on demand.\n */\nexport const Manifest = Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n version: Schema.String,\n assets: Schema.Array(Schema.String),\n devEntry: Schema.String.pipe(Schema.optional),\n});\n\nexport type Manifest = Schema.Schema.Type<typeof Manifest>;\n\n/**\n * Resolved manifest with all asset paths converted to absolute URLs.\n *\n * `dev` reflects whether the source manifest declared a `devEntry`. Loaders branch\n * on this to skip offline caching and stylesheet injection — both are no-ops (or\n * actively wrong) when the plugin is being served by a Vite dev server.\n */\nexport type ResolvedManifest = {\n id: string;\n name: string;\n version: string;\n entryUrl: string;\n assetUrls: readonly string[];\n dev: boolean;\n};\n\n/**\n * Resolves a parsed manifest's relative asset paths against the manifest's URL.\n * In dev mode the entry comes from `devEntry`; otherwise it's the canonical\n * {@link PLUGIN_ENTRY_FILENAME} sitting next to the manifest.\n */\nconst resolve = (manifestUrl: string, manifest: Manifest): ResolvedManifest => {\n const dev = manifest.devEntry !== undefined;\n return {\n id: manifest.id,\n name: manifest.name,\n version: manifest.version,\n entryUrl: new URL(dev ? manifest.devEntry! : PLUGIN_ENTRY_FILENAME, manifestUrl).toString(),\n assetUrls: manifest.assets.map((asset) => new URL(asset, manifestUrl).toString()),\n dev,\n };\n};\n\n/**\n * Synchronous decode + validate + resolve for an in-memory manifest payload. Used\n * by tests and tooling that have the manifest body already loaded; the runtime\n * path goes through {@link fetchManifest}.\n */\nexport const parse = (manifestUrl: string, payload: unknown): ResolvedManifest => {\n const manifest = Schema.decodeUnknownSync(Manifest)(payload);\n if (manifest.devEntry === undefined && !manifest.assets.includes(PLUGIN_ENTRY_FILENAME)) {\n throw new Error(`Manifest at ${manifestUrl} does not list ${PLUGIN_ENTRY_FILENAME} in assets.`);\n }\n return resolve(manifestUrl, manifest);\n};\n\n/**\n * Fetches and parses a manifest from the given URL via Effect's HTTP client and\n * Schema-driven JSON decoding. All failure modes surface as a single tagged\n * {@link PluginManifestError}; callers route on `error.context.reason`.\n */\nexport const fetchManifest = (manifestUrl: string): Effect.Effect<ResolvedManifest, PluginManifestError> =>\n Effect.gen(function* () {\n const response = yield* HttpClientRequest.get(manifestUrl).pipe(\n HttpClient.execute,\n Effect.mapError((cause) => new PluginManifestError({ context: { manifestUrl, reason: 'fetch-failed' }, cause })),\n );\n if (response.status >= 400) {\n return yield* Effect.fail(\n new PluginManifestError({ context: { manifestUrl, reason: 'http-error', status: response.status } }),\n );\n }\n const manifest = yield* HttpClientResponse.schemaBodyJson(Manifest)(response).pipe(\n Effect.mapError((cause) => new PluginManifestError({ context: { manifestUrl, reason: 'parse-failed' }, cause })),\n );\n if (manifest.devEntry === undefined && !manifest.assets.includes(PLUGIN_ENTRY_FILENAME)) {\n return yield* Effect.fail(\n new PluginManifestError({\n context: { manifestUrl, reason: 'invalid' },\n cause: `assets does not include ${PLUGIN_ENTRY_FILENAME}`,\n }),\n );\n }\n return resolve(manifestUrl, manifest);\n }).pipe(Effect.scoped, Effect.provide(FetchHttpClient.layer));\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { PLUGIN_ENTRY_FILENAME } from '@dxos/protocols';\n\nimport { type Plugin } from '../core';\n\n/**\n * Name of the asset written alongside the built module bundle.\n * The DXOS community registry resolves each published plugin by fetching this file\n * from the repo's latest GitHub Release, so authors should not rename it.\n */\nexport const MANIFEST_ASSET_NAME = 'manifest.json';\n\n/**\n * Canonical entry filename (re-exported from `@dxos/protocols`) so vite-plugin\n * consumers don't have to reach into the protocols package directly.\n */\nexport const ENTRY_FILENAME = PLUGIN_ENTRY_FILENAME;\n\n/**\n * Plugin metadata required to emit a manifest at build time.\n *\n * Extends `Plugin.Meta` with a build-time `version` field that is not\n * relevant to the runtime plugin definition itself.\n */\nexport type BuildMeta = Plugin.Meta & { version: string };\n\n/**\n * Serializes a plugin's public metadata + bundle layout into the format consumed\n * by the host loader (see `UrlLoader.make` and `PluginManifest.parse`).\n *\n * The host fetches this manifest, resolves every entry in `assets` against the\n * manifest URL, and persists them via the platform `PluginAssetCache` so the\n * plugin works offline. For production builds the entry module is always\n * {@link ENTRY_FILENAME} and must appear in `assets`. For dev-server manifests\n * pass `devEntry` (a path relative to the manifest URL) — the host then imports\n * the entry directly from the dev server and skips offline caching, since the\n * full asset graph isn't enumerable until build time.\n *\n * Exported from a vite-free module so tests and tooling can validate manifests\n * without paying the cost of loading vite + esbuild.\n */\nexport const serializeManifest = (\n meta: BuildMeta,\n { assets, devEntry }: { assets: readonly string[]; devEntry?: string },\n): string => {\n // The published manifest is keyed by the bare NSID `id`; the `key` DXN is an\n // in-process convenience and is intentionally omitted to keep the registry\n // wire-format stable. `version` is the build-time package version (may be a\n // non-semver dev tag), carried by `BuildMeta` rather than derived from `key`.\n const { key: _key, ...rest } = meta;\n return JSON.stringify(\n {\n ...rest,\n assets,\n ...(devEntry !== undefined ? { devEntry } : {}),\n },\n null,\n 2,\n );\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\n/**\n * Packages shared between the Composer host app and remote plugins.\n *\n * {@link DEFAULT_PACKAGES} is the single source of truth: `importMapPlugin` emits\n * one wrapper chunk per entry so the host serves it at runtime, and `composerPlugin`\n * (via {@link isSharedPackage}) externalizes the same set from plugin bundles.\n * Adding a new `@dxos/*` (or third-party) package that plugins may depend on means\n * adding it here — in one place — so the externalization contract stays in sync\n * with what the host actually provides.\n *\n * Every entry must also be a **direct** dependency of composer-app's `package.json`,\n * including packages that are only re-exported by an umbrella (e.g. via subpath\n * re-exports from another listed package). pnpm doesn't symlink transitive deps\n * into a package's own `node_modules`, so the import-map plugin's `this.resolve`\n * call fails for transitive-only entries and the importmap silently drops them —\n * leaving plugins with bare specifiers the host can't satisfy at install time.\n *\n * Plugin packages (`@dxos/plugin-*`) are intentionally NOT listed: community plugins\n * bundle their own copy of any plugin-subpath import, which is safe because those\n * exports are limited to lightweight types/operation defs.\n */\n\n/**\n * Non-`@dxos/*` packages the Composer host provides to plugins via import map.\n * Spread into {@link DEFAULT_PACKAGES} so the third-party set lives in one place.\n */\nconst THIRD_PARTY_SHARED_PACKAGES = [\n '@effect-atom/atom',\n '@effect-atom/atom-react',\n '@effect/platform',\n 'effect',\n 'lit',\n 'react',\n 'react-dom',\n 'solid-js',\n];\n\nexport const DEFAULT_PACKAGES = [\n // packages/common\n '@dxos/async',\n '@dxos/codec-protobuf',\n '@dxos/context',\n '@dxos/crypto',\n '@dxos/debug',\n '@dxos/display-name',\n '@dxos/effect',\n '@dxos/effect-atom-solid',\n '@dxos/errors',\n '@dxos/feed-store',\n '@dxos/graph',\n '@dxos/hypercore',\n '@dxos/invariant',\n '@dxos/keyboard',\n '@dxos/keys',\n '@dxos/kv-store',\n '@dxos/log',\n '@dxos/merkle-search-tree',\n '@dxos/random',\n '@dxos/random-access-storage',\n '@dxos/timeframe',\n '@dxos/tracing',\n '@dxos/util',\n '@dxos/web-context',\n '@dxos/web-context-react',\n '@dxos/web-context-solid',\n\n // packages/core/echo\n '@dxos/echo',\n '@dxos/echo-client',\n '@dxos/echo-host',\n '@dxos/echo-protocol',\n '@dxos/echo-query',\n '@dxos/echo-react',\n '@dxos/echo-solid',\n '@dxos/feed',\n '@dxos/index-core',\n\n // packages/core/halo\n '@dxos/credentials',\n '@dxos/keyring',\n\n // packages/core/mesh\n '@dxos/edge-client',\n '@dxos/messaging',\n '@dxos/network-manager',\n '@dxos/rpc',\n '@dxos/rpc-tunnel',\n '@dxos/teleport',\n '@dxos/teleport-extension-automerge-replicator',\n '@dxos/teleport-extension-gossip',\n '@dxos/teleport-extension-object-sync',\n '@dxos/teleport-extension-replicator',\n '@dxos/websocket-rpc',\n\n // packages/core\n '@dxos/ai',\n '@dxos/assistant',\n '@dxos/assistant-toolkit',\n '@dxos/compute',\n '@dxos/conductor',\n '@dxos/functions',\n '@dxos/functions-runtime',\n '@dxos/mcp-client',\n '@dxos/operation',\n '@dxos/protocols',\n\n // packages/devtools\n '@dxos/devtools',\n\n // packages/sdk\n '@dxos/app-framework',\n '@dxos/app-graph',\n '@dxos/app-solid',\n '@dxos/app-toolkit',\n '@dxos/client',\n '@dxos/client-protocol',\n '@dxos/client-services',\n '@dxos/config',\n '@dxos/migrations',\n '@dxos/observability',\n '@dxos/react-client',\n '@dxos/react-edge-client',\n '@dxos/schema',\n '@dxos/types',\n\n // packages/ui\n '@dxos/lit-grid',\n '@dxos/lit-ui',\n '@dxos/react-hooks',\n '@dxos/react-ui',\n '@dxos/react-ui-attention',\n '@dxos/react-ui-audio',\n '@dxos/react-ui-board',\n '@dxos/react-ui-calendar',\n '@dxos/react-ui-canvas',\n '@dxos/react-ui-canvas-compute',\n '@dxos/react-ui-canvas-editor',\n '@dxos/react-ui-chat',\n '@dxos/react-ui-components',\n '@dxos/react-ui-dnd',\n '@dxos/react-ui-editor',\n '@dxos/react-ui-experimental',\n '@dxos/react-ui-form',\n '@dxos/react-ui-gameboard',\n '@dxos/react-ui-geo',\n '@dxos/react-ui-graph',\n '@dxos/react-ui-grid',\n '@dxos/react-ui-list',\n '@dxos/react-ui-markdown',\n '@dxos/react-ui-masonry',\n '@dxos/react-ui-menu',\n '@dxos/react-ui-mosaic',\n '@dxos/react-ui-pickers',\n '@dxos/react-ui-list',\n '@dxos/react-ui-stack',\n '@dxos/react-ui-syntax-highlighter',\n '@dxos/react-ui-table',\n '@dxos/react-ui-tabs',\n '@dxos/react-ui-text-tooltip',\n '@dxos/react-ui-thread',\n '@dxos/solid-ui',\n '@dxos/solid-ui-geo',\n '@dxos/ui',\n '@dxos/ui-editor',\n '@dxos/ui-theme',\n '@dxos/ui-types',\n\n // third-party\n ...THIRD_PARTY_SHARED_PACKAGES,\n];\n\n/**\n * True when the given bare specifier (or one of its subpaths) is provided by the\n * Composer host at runtime and must not be re-bundled by a plugin.\n *\n * Matches only packages listed in {@link DEFAULT_PACKAGES} — the same list\n * {@link importMapPlugin} consumes — so externalization cannot claim a package\n * the host isn't actually mapping. Unknown `@dxos/*` packages fall through to\n * normal bundling, which is the correct default for plugin-owned or yet-to-be\n * shared workspace packages.\n */\nexport const isSharedPackage = (id: string): boolean =>\n DEFAULT_PACKAGES.some((pkg) => id === pkg || id.startsWith(`${pkg}/`));\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Plugin as VitePlugin } from 'vite';\n\nimport { PLUGIN_DEV_SERVER_PORT } from '../../core';\nimport { type BuildMeta, ENTRY_FILENAME, MANIFEST_ASSET_NAME, serializeManifest } from '../manifest';\nimport { DEFAULT_PACKAGES, isSharedPackage } from '../packages';\n\nexport { ENTRY_FILENAME, MANIFEST_ASSET_NAME, serializeManifest };\nexport type { BuildMeta };\n\nconst JSX_DEV_RUNTIME = 'react/jsx-dev-runtime';\n\n/**\n * Whether an import should be externalized by the plugin bundle.\n * Uses the shared-package predicate directly so plugins automatically pick up any\n * new `@dxos/*` (non-plugin) package the host provides, without a code change here.\n */\nconst isExternal = (id: string) => id !== JSX_DEV_RUNTIME && isSharedPackage(id);\n\n/**\n * Banner injected at the top of every plugin bundle.\n *\n * Why: rolldown emits ESM `import` for externalized deps, but when a *bundled* module\n * is CJS and contains `require('react')` (or any other external), rolldown keeps the\n * `require(...)` call in the output and relies on a runtime `require` function. The\n * browser doesn't have `require`, so rolldown's fallback shim throws:\n * `Calling `require` for \"react\" in an environment that doesn't expose the `require`\n * function`.\n *\n * The full dependency graphs of non-trivial plugins unavoidably drag in CJS-only\n * helpers (`use-sync-external-store` via xstate / zustand / preact-signals / … ),\n * and waiting for every one of those packages to ship ESM isn't realistic. Instead\n * we install a tiny module-local `require` at the top of the bundle that looks up\n * a handful of well-known host-provided modules by name and returns their already\n * ESM-imported namespaces. Rolldown's own shim honours an existing `require`\n * before falling through to the throw path, so this entirely removes the runtime\n * error without changing how externalization itself works.\n *\n * Keep the list aligned with the externals that CJS code actually reaches for;\n * adding entries here is safe (unused imports get tree-shaken), but the list is\n * deliberately small to keep the banner noise-free.\n */\nconst REQUIRE_SHIM_BANNER = [\n '// --- composer-plugin: CJS require shim ---',\n '// See @dxos/app-framework/vite-plugin/composer-plugin.ts for rationale.',\n \"import * as __composerReact from 'react';\",\n \"import * as __composerReactDom from 'react-dom';\",\n \"import * as __composerReactJsxRuntime from 'react/jsx-runtime';\",\n 'const __composerRequireShim = new Map([',\n \" ['react', __composerReact.default ?? __composerReact],\",\n \" ['react-dom', __composerReactDom.default ?? __composerReactDom],\",\n \" ['react/jsx-runtime', __composerReactJsxRuntime],\",\n ']);',\n \"// Module-local binding: rolldown's CJS fallback does a `typeof require` check\",\n '// and uses whichever `require` is in lexical scope. Declaring this as `const`',\n \"// (instead of `globalThis.require ??=`) keeps each bundle's shim isolated from\",\n '// the host page and from other plugins sharing the window.',\n 'const require = (id) => {',\n ' if (__composerRequireShim.has(id)) return __composerRequireShim.get(id);',\n \" throw new Error('composer-plugin: unsupported CJS require at runtime: ' + id);\",\n '};',\n '// --- end CJS require shim ---',\n].join('\\n');\n\nexport type ComposerPluginOptions = {\n /** Entry point for the plugin bundle. Defaults to `src/plugin.tsx`. */\n entry?: string;\n /** Dev server port. Defaults to {@link PLUGIN_DEV_SERVER_PORT}. */\n port?: number;\n /**\n * Plugin metadata. When provided, a `manifest.json` asset is emitted alongside the bundle\n * listing every emitted file. The host fetches this manifest at install time and persists\n * the declared assets in its offline cache so the plugin works without network. The bundle's\n * entry module is always written as {@link ENTRY_FILENAME} (`index.mjs`).\n */\n meta?: BuildMeta;\n};\n\n/**\n * Vite plugin for **external Composer plugin projects**. Configures the build to produce\n * an ESM bundle that externalizes all framework dependencies, which the Composer host app\n * provides at runtime via import map.\n *\n * Handles:\n * 1. Build config — lib mode entry point, ES format output, rollup externals, code-split chunks.\n * 2. Dev externalization — marks shared deps as external during `vite serve` and strips\n * the `/@id/` prefix that Vite's import analysis adds to external bare specifiers.\n * 3. JSX dev runtime shim — bridges `react/jsx-dev-runtime` (used by React refresh in dev)\n * to `react/jsx-runtime` (which is what the externalized React provides).\n * 4. Manifest emit — when `meta` is supplied, writes `manifest.json` next to the bundled\n * module listing every emitted asset (entry, CSS, chunks, etc.) so the host can eagerly\n * cache them for offline use.\n */\nexport const composerPlugin = (options?: ComposerPluginOptions): VitePlugin[] => {\n const entry = options?.entry ?? 'src/plugin.tsx';\n const port = options?.port ?? PLUGIN_DEV_SERVER_PORT;\n const meta = options?.meta;\n const resolved = new Set<string>();\n let base = '/';\n\n const plugins: VitePlugin[] = [\n // Configure vite for library-mode builds with externalized deps.\n {\n name: 'composer-plugin',\n config: () => ({\n server: {\n port,\n // Allow the Composer host (different origin) to dynamically import plugin modules.\n cors: true,\n },\n preview: { port },\n build: {\n sourcemap: true,\n // Transitively-bundled WASM modules (automerge, tiktoken, …) emit top-level\n // await; `esnext` lets rolldown pass that through without an explicit polyfill.\n target: 'esnext',\n lib: {\n entry,\n formats: ['es'],\n fileName: () => ENTRY_FILENAME,\n },\n rolldownOptions: {\n external: (id: string) => isExternal(id),\n output: {\n chunkFileNames: 'chunks/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n // Install the CJS require shim at the top of plugin.mjs so transitively\n // bundled CJS helpers (that call `require('react')` et al. at runtime) can\n // resolve against the host-provided externals instead of throwing.\n banner: REQUIRE_SHIM_BANNER,\n },\n },\n },\n }),\n },\n\n // Dev-time externalization.\n // Vite's dev server doesn't use rollup externals, so we need to handle it manually.\n // We intercept imports of shared deps at resolve time, mark them external, and then\n // strip the `/@id/` prefix that Vite's import analysis injects for external modules.\n {\n name: 'composer-plugin:externalize',\n enforce: 'pre',\n apply: 'serve',\n // Exclude shared packages from Vite's dependency pre-bundling.\n config: () => ({\n optimizeDeps: {\n exclude: DEFAULT_PACKAGES,\n },\n }),\n // Mark shared deps as external so Vite doesn't try to bundle them.\n resolveId: (id) => {\n if (isExternal(id)) {\n resolved.add(id);\n return { id, external: true };\n }\n },\n // Return a stub for any externalized module that Vite tries to load directly.\n load: (id) => {\n if (resolved.has(id)) {\n return { code: 'export default {};' };\n }\n },\n // After all plugins are resolved, inject a late-stage transform plugin that strips\n // the `/@id/` prefix from externalized bare specifiers in the output.\n // This must run after Vite's internal import analysis which rewrites bare specifiers.\n configResolved: (config) => {\n base = config.base ?? '/';\n (config.plugins as VitePlugin[]).push({\n name: 'composer-plugin:strip-prefix',\n transform: (code: string) => {\n if (resolved.size === 0) {\n return;\n }\n const escaped = [...resolved].map((s) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|');\n const pattern = new RegExp(`${base}@id/(${escaped})`, 'g');\n if (pattern.test(code)) {\n return code.replace(pattern, (_: string, dep: string) => dep);\n }\n },\n });\n },\n },\n\n // JSX dev runtime shim.\n // React refresh (used by @vitejs/plugin-react) imports from `react/jsx-dev-runtime`,\n // but the externalized React only exposes `react/jsx-runtime`. This virtual module\n // bridges the gap by re-exporting jsx-runtime's functions under jsx-dev-runtime's API.\n {\n name: 'composer-plugin:jsx-dev-shim',\n enforce: 'pre',\n apply: 'serve',\n resolveId: (id) => (id === JSX_DEV_RUNTIME ? `\\0${JSX_DEV_RUNTIME}` : undefined),\n load: (id) =>\n id === `\\0${JSX_DEV_RUNTIME}`\n ? [\n 'import { jsx, jsxs, Fragment } from \"react/jsx-runtime\";',\n 'export { Fragment };',\n 'export function jsxDEV(type, props, key, isStaticChildren) {',\n ' return isStaticChildren ? jsxs(type, props, key) : jsx(type, props, key);',\n '}',\n ].join('\\n')\n : undefined,\n },\n\n // React Refresh preamble stub.\n //\n // @vitejs/plugin-react's JSX transform prepends a runtime check to every module:\n // if (!window.$RefreshReg$) throw new Error(\"@vitejs/plugin-react can't detect preamble…\");\n // In a normal single-origin app, vite injects a `<script type=\"module\">` preamble\n // into `index.html` that sets up `$RefreshReg$` / `$RefreshSig$` on `window` before any\n // app code runs. When a community plugin is dev-served at its own origin and then\n // dynamic-imported into the Composer host at a different origin, the host's window\n // never receives that preamble, so every JSX module throws on first import.\n //\n // Inject a no-op refresh shim on the host's window from the plugin's entrypoint: fast-\n // refresh itself doesn't work cross-origin anyway, so silencing the check lets the\n // plugin load and ordinary page reloads take care of picking up edits. Production\n // builds are untouched (`apply: 'serve'`).\n {\n name: 'composer-plugin:react-refresh-shim',\n enforce: 'pre',\n apply: 'serve',\n transform(code, id) {\n // Only patch the plugin entrypoint (an absolute path ending in the configured entry).\n // Matching by suffix keeps us from prepending the shim to every transformed module,\n // which would both bloat the output and defeat vite's caching.\n if (!id.endsWith(entry.replace(/^\\.?\\//, '/'))) {\n return;\n }\n const shim = [\n '// composer-plugin: no-op React Refresh shim so cross-origin plugin modules',\n \"// don't throw the @vitejs/plugin-react preamble check at dynamic-import time.\",\n 'if (typeof window !== \"undefined\") {',\n ' window.$RefreshReg$ = window.$RefreshReg$ || (() => {});',\n ' window.$RefreshSig$ = window.$RefreshSig$ || (() => (type) => type);',\n ' window.__vite_plugin_react_preamble_installed__ = true;',\n '}',\n '',\n ].join('\\n');\n return { code: shim + code, map: null };\n },\n },\n ];\n\n if (meta) {\n // Emit `manifest.json` alongside the built module listing every emitted asset, so the\n // dist directory can be uploaded as-is to a GitHub Release for the DXOS community\n // registry to pick up. The host loader fetches this file at install time and eagerly\n // caches every listed asset for offline use.\n plugins.push({\n name: 'composer-plugin:emit-manifest',\n apply: 'build',\n // `enforce: 'post'` is load-bearing: vite's CSS extraction plugin emits sibling\n // `.css` assets in its own `generateBundle` hook. Without `post`, ours runs first\n // and sees only the JS chunks — the manifest then omits CSS, so the host can't\n // inject `<link>` tags for the plugin's stylesheet at install time.\n enforce: 'post',\n generateBundle(_options, bundle) {\n // Source maps are large and only fetched when devtools opens — exclude them\n // from the manifest so the host doesn't precache megabytes of debug data.\n const assets = Object.keys(bundle)\n .filter((name) => name !== MANIFEST_ASSET_NAME && !name.endsWith('.map'))\n .sort();\n this.emitFile({\n type: 'asset',\n fileName: MANIFEST_ASSET_NAME,\n source: serializeManifest(meta, { assets }),\n });\n },\n });\n\n // Dev-server manifest. `vite dev` can't enumerate transitive chunks/CSS up front\n // (they resolve on demand), so we serve a `devEntry`-flavored manifest at the dev\n // root and let the host loader skip eager caching + static stylesheet injection.\n // The host imports `entry` directly from the dev server, where Vite handles\n // JSX transforms, externalization, and runtime CSS injection.\n plugins.push({\n name: 'composer-plugin:serve-manifest',\n apply: 'serve',\n configureServer(server) {\n const body = serializeManifest(meta, { assets: [], devEntry: entry.replace(/^\\.?\\//, '') });\n server.middlewares.use(`/${MANIFEST_ASSET_NAME}`, (req, res, next) => {\n // Only intercept the bare manifest URL — let any sub-paths fall through.\n if (req.url && req.url !== '/' && req.url !== '') {\n return next();\n }\n // CORS mirrors `server.cors: true` (see plugin config above) so the host\n // app at a different origin can read the manifest. Vite's built-in CORS\n // covers most paths but middlewares mounted before its `cors` middleware\n // need to set the header themselves.\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Content-Type', 'application/json');\n res.setHeader('Cache-Control', 'no-store');\n res.statusCode = 200;\n res.end(body);\n });\n },\n });\n }\n\n return plugins;\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { init as initCjsLexer, parse as parseCjs } from 'cjs-module-lexer';\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { createRequire as nodeCreateRequire } from 'node:module';\nimport path from 'node:path';\nimport { type Plugin } from 'vite';\n\nimport { DEFAULT_PACKAGES } from '../packages';\n\nconst require = nodeCreateRequire(import.meta.url);\n\n//\n// Import map helpers.\n// These utilities support `importMapPlugin` by resolving package entrypoints,\n// detecting module formats (ESM vs CJS), and extracting named exports from CJS bundles.\n//\n\n/** Strips vite query strings (e.g. `?v=123`) from resolved module IDs. */\nconst trimQueryString = (id: string) => id.replace(/\\?.*$/, '');\n\n/**\n * Determines whether a resolved file is an ESM module by checking file extension\n * first (.mjs/.cjs), then walking up to the nearest package.json for `\"type\": \"module\"`.\n */\nconst resolvedIdIsEsmModule = (resolvedId: string): boolean => {\n const file = trimQueryString(resolvedId);\n if (file.endsWith('.mjs') || file.endsWith('.mts')) {\n return true;\n }\n if (file.endsWith('.cjs') || file.endsWith('.cts')) {\n return false;\n }\n\n let directory = path.dirname(file);\n while (directory !== path.dirname(directory)) {\n const packageJsonPath = path.join(directory, 'package.json');\n if (existsSync(packageJsonPath)) {\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as { type?: string };\n return pkg.type === 'module';\n } catch {\n return false;\n }\n }\n directory = path.dirname(directory);\n }\n\n return false;\n};\n\n/**\n * Walks up from a resolved file path to find the package.json whose `\"name\"` matches\n * the given package name. Returns the path to that package.json, or undefined.\n */\nconst findPackageJsonPath = (resolvedId: string, packageName: string): string | undefined => {\n let directory = path.dirname(trimQueryString(resolvedId));\n\n while (directory !== path.dirname(directory)) {\n const packageJsonPath = path.join(directory, 'package.json');\n if (existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as { name?: string };\n if (packageJson.name === packageName) {\n return packageJsonPath;\n }\n } catch {}\n }\n\n directory = path.dirname(directory);\n }\n\n return undefined;\n};\n\n/** Resolves a package name to its package.json path using Node's require.resolve. */\nconst resolvePackageJsonPath = (packageName: string): string | undefined => {\n try {\n return findPackageJsonPath(require.resolve(packageName), packageName);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Resolves a package name to its package.json via vite's own resolver, which handles\n * workspace-linked packages whose `exports` field omits `./package.json` (so\n * `require.resolve` can't find it). Falls back to `require.resolve`.\n */\nconst resolvePackageJsonPathViaContext = async (\n ctx: { resolve: (id: string) => Promise<{ id: string } | null> },\n packageName: string,\n): Promise<string | undefined> => {\n try {\n const resolved = await ctx.resolve(packageName);\n if (resolved) {\n const viaResolved = findPackageJsonPath(resolved.id, packageName);\n if (viaResolved) {\n return viaResolved;\n }\n }\n } catch {\n // fall through\n }\n return resolvePackageJsonPath(packageName);\n};\n\n/**\n * Subpath exports that should be excluded from the import map.\n * These are node-only entrypoints (vite plugins, native addons) that shouldn't be pre-bundled for the browser.\n *\n * TODO(wittjosiah): Replace these hand-maintained lists (plus {@link GLOBALLY_EXCLUDED_SUBPATHS}\n * and {@link BUILD_TOOL_SUBPATH}) with a structural check — e.g. honour an `agent`/`node`-only\n * export condition in package.json, or probe each subpath's resolved file for `node:*` imports\n * at build time — so every new server-only entrypoint doesn't require a code change here.\n */\nconst importMapExcludedSubpaths: Readonly<Record<string, ReadonlySet<string>>> = {\n '@dxos/app-framework': new Set(['vite-plugin']),\n // `@dxos/lit-grid/testing` re-exports a playwright page-object manager and pulls\n // `@playwright/test` (and transitive playwright-core) into the browser bundle.\n '@dxos/lit-grid': new Set(['testing']),\n '@dxos/react-ui-mosaic': new Set(['playwright']),\n '@dxos/react-ui-stack': new Set(['playwright']),\n '@dxos/react-ui-table': new Set(['playwright']),\n '@dxos/ui-theme': new Set(['plugin']),\n // `solid-js/web/storage` is a server-only helper that pulls\n // `node:async_hooks` (AsyncLocalStorage) and has no browser shim. Client\n // code imports `solid-js`, `solid-js/store`, and `solid-js/web` only.\n 'solid-js': new Set(['web/storage']),\n // `effect` publishes `./.index` for bundler internals — maps to `effect/.index`, which Vite\n // often cannot resolve for the import map and is not part of the plugin-facing surface.\n effect: new Set(['.index']),\n};\n\n/**\n * Subpaths common to many packages that should always be excluded.\n * `./playwright` subdirectories house e2e test harnesses that pull in\n * `@playwright/test` (a node-only package that breaks the browser bundle).\n * `./testing` subpaths similarly expose node-only test helpers (e.g.\n * `@dxos/edge-client/testing` pulls `@dxos/node-std/http` which has no\n * browser analogue) and aren't part of the plugin-facing surface.\n */\nconst GLOBALLY_EXCLUDED_SUBPATHS = new Set(['playwright', 'testing']);\n\n/**\n * Regex for subpaths that are always node-only build tooling — vite, esbuild, and\n * rollup plugins. These use `node:*` imports and will blow up the browser bundle if\n * they end up in the import map.\n */\nconst BUILD_TOOL_SUBPATH = /^(vite-plugin|esbuild-plugin|rollup-plugin|plugin)$/;\n\n/**\n * Asset subpaths (CSS, PCSS, images, etc.) that the host already loads via its own\n * bundle — for example `@dxos/react-ui-form` pulls in `@dxos/lit-ui/dx-tag-picker.pcss`\n * on startup, so the stylesheet is already attached to the DOM by the time a remote\n * plugin runs. Community plugins should still be able to _import_ those specifiers\n * (rolldown leaves the `import \"…\"` statements in the output when the package is\n * externalized), so the import map maps them to a no-op empty ES module. The\n * resulting browser fetch is a cheap no-op; the styles are never re-downloaded\n * and never re-injected.\n */\nconst ASSET_SUBPATH = /\\.(css|pcss|scss|sass|less|json|node|wasm|html|svg|png|jpe?g|gif|webp|ico)$/;\nconst isAssetSubpath = (specifier: string) => ASSET_SUBPATH.test(specifier);\n\n/**\n * Walks `baseDir` and returns every file that matches the pattern `${baseDir}/<rest>${extension}`.\n * Used to expand wildcard exports like `./proto/*` → `./dist/src/proto/gen/*.js` into their\n * full set of bare specifiers.\n */\nconst walkDirectoryForExtension = (baseDir: string, extension: string): string[] => {\n if (!existsSync(baseDir)) {\n return [];\n }\n const results: string[] = [];\n const walk = (dir: string) => {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = path.join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n walk(full);\n } else if (entry.endsWith(extension)) {\n results.push(path.relative(baseDir, full).slice(0, -extension.length));\n }\n }\n };\n walk(baseDir);\n return results;\n};\n\n/** Resolves an `exports` value to a single target path for pattern expansion. */\nconst pickPatternTarget = (value: unknown): string | undefined => {\n if (typeof value === 'string') {\n return value;\n }\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const preferred = obj.browser ?? obj.import ?? obj.default ?? obj.module;\n return typeof preferred === 'string' ? preferred : undefined;\n }\n return undefined;\n};\n\n/**\n * Expands a wildcard export like `./proto/*` into concrete subpath specifiers by walking\n * the target directory. Returns `<packageName>/<subpath>` strings.\n */\nconst expandWildcardExport = (\n packageName: string,\n packageJsonDir: string,\n exportKey: string,\n exportValue: unknown,\n): string[] => {\n const target = pickPatternTarget(exportValue);\n if (!target || !target.includes('*')) {\n return [];\n }\n // Split on `*` — at most one supported (node's exports pattern semantics).\n const keyStarIndex = exportKey.indexOf('*');\n const targetStarIndex = target.indexOf('*');\n if (keyStarIndex === -1 || targetStarIndex === -1) {\n return [];\n }\n const keyPrefix = exportKey.slice(2, keyStarIndex); // drop leading './'\n const targetPrefix = target.slice(2, targetStarIndex); // drop leading './'\n const targetSuffix = target.slice(targetStarIndex + 1);\n const baseDir = path.resolve(packageJsonDir, targetPrefix);\n const files = walkDirectoryForExtension(baseDir, targetSuffix || '.js');\n return files.map((relativeNoExt) => `${packageName}/${keyPrefix}${relativeNoExt}`);\n};\n\n/**\n * Reads a package's `exports` field and returns all subpath entrypoints as bare specifiers\n * (e.g. `@dxos/client`, `@dxos/client/echo`, `@dxos/lit-ui/dx-tag-picker.pcss`,\n * `@dxos/protocols/proto/dxos/echo/metadata`). Wildcard patterns are expanded by walking\n * the corresponding output directory. Falls back to just the package name if exports is\n * absent or simple.\n */\nconst getPackageEntrypoints = (packageName: string, packageJsonPath: string): string[] => {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {\n exports?: Record<string, unknown> | string | string[];\n };\n const exportsField = packageJson.exports;\n\n if (!exportsField || typeof exportsField === 'string' || Array.isArray(exportsField)) {\n return [packageName];\n }\n\n const exportKeys = Object.keys(exportsField);\n if (!exportKeys.some((key) => key.startsWith('.'))) {\n return [packageName];\n }\n\n const excluded = importMapExcludedSubpaths[packageName];\n const packageJsonDir = path.dirname(packageJsonPath);\n const modules = exportKeys.flatMap((key) => {\n if (key === '.') {\n return [packageName];\n }\n\n if (!key.startsWith('./') || key === './package.json') {\n return [];\n }\n\n // Skip `.d.ts` subpath exports — these are meant to be imported as raw text\n // (e.g. `@dxos/echo-query/api.d.ts?raw` for in-editor type hints), not as\n // ES modules. Enumerating them here would have vite try to bundle the\n // declaration file's imports (protobufjs, effect, etc.), which breaks.\n if (key.endsWith('.d.ts')) {\n return [];\n }\n\n if (key.includes('*')) {\n // Expand wildcard patterns like `./proto/*` into concrete specifiers.\n return expandWildcardExport(packageName, packageJsonDir, key, (exportsField as Record<string, unknown>)[key]);\n }\n\n const subpath = key.slice(2);\n if (excluded?.has(subpath) || GLOBALLY_EXCLUDED_SUBPATHS.has(subpath) || BUILD_TOOL_SUBPATH.test(subpath)) {\n return [];\n }\n\n return [`${packageName}/${subpath}`];\n });\n\n return modules.length > 0 ? modules : [packageName];\n};\n\n/**\n * Statically analyzes a CJS file to extract named exports using cjs-module-lexer.\n * Follows re-exports (e.g. react's index.js re-exports from cjs/react.development.js)\n * and deduplicates. Filters out `default` and `__esModule` pseudo-exports.\n */\nconst getCjsNamedExports = (filePath: string, seen = new Set<string>()): string[] => {\n const normalized = trimQueryString(filePath);\n if (seen.has(normalized)) {\n return [];\n }\n seen.add(normalized);\n\n try {\n const source = readFileSync(normalized, 'utf8');\n const { exports: directExports, reexports } = parseCjs(source);\n\n const reexportedNames = reexports.flatMap((reexport) => {\n const resolved = path.resolve(path.dirname(normalized), reexport);\n const candidates = [resolved, `${resolved}.js`, `${resolved}.cjs`];\n const found = candidates.find((candidate) => existsSync(candidate));\n return found ? getCjsNamedExports(found, seen) : [];\n });\n\n return [...new Set([...directExports, ...reexportedNames])].filter(\n (name) => name !== 'default' && name !== '__esModule',\n );\n } catch {\n return [];\n }\n};\n\n/**\n * Vite plugin for the **host app** (Composer). Generates a browser import map so that\n * shared packages are loaded once and reused by both the host and any remote plugins.\n *\n * In production, emits a dedicated chunk per specifier via virtual wrapper modules,\n * then injects a `<script type=\"importmap\">` tag into the HTML with the chunk URLs.\n *\n * Virtual wrappers are needed because directly emitting chunks for CJS packages loses\n * their named exports due to Rollup's interop. The wrapper re-exports them explicitly.\n *\n * TODO: Restore dev-mode support. The previous dev path mapped each bare specifier to\n * its absolute `/@fs/` file path during `buildStart`, which forced `this.resolve()` for\n * hundreds of subpath entrypoints and raced with Vite's optimize-deps static scan —\n * producing non-deterministic chunk content (~34 chunks drifting per warm-start) and\n * triggering Vite 8.0.10's `runOptimizer` / `commitProcessing` crashes (`fileHash` /\n * `browserHash` undefined on partial-discovery batches). Plugin is currently gated to\n * `apply: 'build'` to avoid both. A working dev-mode implementation would need to\n * resolve specifiers without participating in the optimize-deps phase — candidates:\n * - defer resolution to `transformIndexHtml` (after the optimizer settles)\n * - read resolved paths from `environment.depsOptimizer.metadata` rather than calling\n * `this.resolve()` ourselves\n * - resolve via `require.resolve` directly, bypassing the Vite plugin pipeline entirely\n */\nexport const importMapPlugin = (options?: { packages?: string[] }): Plugin[] => {\n const packages = options?.packages ?? DEFAULT_PACKAGES;\n const WRAPPER_PREFIX = '\\0import-map:';\n const chunkRefIds: Record<string, string> = {};\n const resolvedIds: Record<string, string> = {};\n let imports: Record<string, string> = {};\n let modules: string[] = [];\n let importMapIsDev = false;\n let base = '/';\n\n return [\n // Phase 1: Resolve all package entrypoints and emit chunks.\n //\n // Build-only. The dev-mode path (recording absolute `/@fs/` paths in\n // `imports[]`) is non-functional today and was actively harmful: calling\n // `this.resolve()` for every shared package's subpath entrypoints during\n // `buildStart` races with Vite's optimize-deps static scan, producing\n // non-deterministic chunk content (~34 drifting chunks per warm-start) and\n // triggering Vite 8.0.10's `runOptimizer` / `commitProcessing` crashes\n // (`fileHash` / `browserHash` undefined on partial-discovery batches) when\n // the resolved set doesn't match the optimizer's metadata. The importmap\n // is only meaningful for production builds where remote plugins consume\n // the emitted wrapper chunks.\n {\n name: 'import-map:get-chunk-ref-ids',\n apply: 'build',\n configResolved(config) {\n base = config.base ?? '/';\n },\n async buildStart() {\n importMapIsDev = this.environment.mode === 'dev';\n await initCjsLexer();\n\n // Expand each package name into its full set of subpath entrypoints\n // (e.g. '@dxos/client' -> ['@dxos/client', '@dxos/client/echo', ...]).\n modules = [\n ...new Set(\n (\n await Promise.all(\n packages.map(async (packageName) => {\n const packageJsonPath = await resolvePackageJsonPathViaContext(this, packageName);\n if (!packageJsonPath) {\n this.warn(`Unable to locate package.json for import map package: ${packageName}`);\n return [packageName];\n }\n\n return getPackageEntrypoints(packageName, packageJsonPath);\n }),\n )\n ).flat(),\n ),\n ];\n\n for (const specifier of modules) {\n if (isAssetSubpath(specifier)) {\n // Host already loaded the real asset; remote plugins need the specifier to\n // resolve to *something* that behaves as an ES module. A data URL is the\n // cheapest option — no chunk to emit (rolldown tree-shakes an empty wrapper\n // even with `preserveSignature: 'strict'`, so the referenced file wouldn't\n // exist at runtime), no extra network request, and the same path in dev and prod.\n imports[specifier] = 'data:text/javascript;charset=utf-8,export%20%7B%7D%3B';\n continue;\n }\n\n const resolved = await this.resolve(specifier);\n if (!resolved) {\n this.warn(`Import map: unable to resolve \"${specifier}\"; omitting from import map.`);\n continue;\n }\n\n if (importMapIsDev) {\n // Dev: map bare specifier to the resolved file path, prefixed with vite's\n // `/@fs/` escape hatch so absolute node_modules paths (including\n // `.vite/deps/*` pre-bundled chunks) round-trip through the dev server\n // instead of being resolved against the document origin as a 404.\n const filePath = trimQueryString(resolved.id);\n imports[specifier] = filePath.startsWith('/') ? `/@fs${filePath}` : filePath;\n } else {\n // Prod: emit a virtual wrapper chunk that re-exports from the real module.\n resolvedIds[specifier] = resolved.id;\n chunkRefIds[specifier] = this.emitFile({\n type: 'chunk',\n id: `${WRAPPER_PREFIX}${specifier}`,\n preserveSignature: 'strict',\n });\n }\n }\n },\n\n // Intercept virtual wrapper IDs so Rollup doesn't try to resolve them as files.\n resolveId(id) {\n if (id.startsWith(WRAPPER_PREFIX)) {\n return id;\n }\n },\n\n // Generate the source for each virtual wrapper module.\n // For CJS packages, explicitly re-export named exports (discovered via static analysis)\n // because Rollup's `export *` interop doesn't preserve them for CJS.\n //\n // Each wrapper also emits a local `__keepalive` export. Without this, Rolldown\n // (Vite 8) tree-shakes wrappers whose `export *` re-exports happen to coincide\n // with another already-emitted chunk's exports — typical for umbrella packages\n // (e.g. `@dxos/compute` re-exports from `@dxos/operation`, so the operation\n // wrapper looks \"redundant\" to Rolldown and gets merged away). A local const\n // export has no upstream source for Rolldown to dedupe against, so the chunk\n // is always preserved and the import-map entry resolves at runtime.\n load(id) {\n if (!id.startsWith(WRAPPER_PREFIX)) {\n return;\n }\n const specifier = id.slice(WRAPPER_PREFIX.length);\n const keepalive = `export const __dxosImportMapKeepalive = ${JSON.stringify(specifier)};`;\n const resolvedId = resolvedIds[specifier];\n if (!resolvedId) {\n return `export * from ${JSON.stringify(specifier)};\\n${keepalive}\\n`;\n }\n\n const filePath = trimQueryString(resolvedId);\n const isCjs = filePath.endsWith('.cjs') || (!filePath.endsWith('.mjs') && !resolvedIdIsEsmModule(filePath));\n\n if (isCjs) {\n const named = getCjsNamedExports(filePath);\n if (named.length > 0) {\n return `export { default, ${named.join(', ')} } from ${JSON.stringify(specifier)};\\n${keepalive}\\n`;\n }\n }\n return `export * from ${JSON.stringify(specifier)};\\n${keepalive}\\n`;\n },\n\n // After bundling, map each specifier to the URL of its emitted chunk. Preserves\n // asset-subpath entries already written to `imports` during `buildStart` (those\n // use an inline data URL rather than an emitted chunk).\n generateBundle() {\n if (importMapIsDev) {\n return;\n }\n\n imports = {\n ...imports,\n ...Object.fromEntries(\n modules\n .filter((specifier) => chunkRefIds[specifier] !== undefined)\n .map((specifier) => [specifier, `${base}${this.getFileName(chunkRefIds[specifier])}`]),\n ),\n };\n },\n },\n\n // Phase 2: Inject the import map into the HTML as a <script type=\"importmap\"> tag.\n {\n name: 'import-map:transform-index-html',\n apply: 'build',\n enforce: 'post',\n transformIndexHtml(html: string) {\n const tags = [\n {\n tag: 'script',\n attrs: {\n type: 'importmap',\n },\n children: JSON.stringify({ imports }, null, 2),\n },\n ];\n\n return {\n html,\n tags,\n };\n },\n },\n ];\n};\n"],
|
|
5
|
-
"mappings": "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G,IAAMC,WAAkBC,cAAO;EACpCC,IAAWC;EACXC,MAAaD;EACbE,SAAgBF;EAChBG,QAAeC,aAAaJ,aAAM;EAClCK,UAAiBL,cAAOM,KAAYC,eAAQ;AAC9C,CAAA;;;ACnDA,SAASC,yBAAAA,8BAA6B;AAS/B,IAAMC,sBAAsB;AAM5B,IAAMC,iBAAiBF;AAyBvB,IAAMG,oBAAoB,CAC/BC,MACA,EAAEC,QAAQC,SAAQ,MAAoD;AAMtE,QAAM,EAAEC,KAAKC,MAAM,GAAGC,KAAAA,IAASL;AAC/B,SAAOM,KAAKC,UACV;IACE,GAAGF;IACHJ;IACA,GAAIC,aAAaM,SAAY;MAAEN;IAAS,IAAI,CAAC;EAC/C,GACA,MACA,CAAA;AAEJ;;;AChCA,IAAMO,8BAA8B;EAClC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGK,IAAMC,mBAAmB;;EAE9B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAGGD;;AAaE,IAAME,kBAAkB,CAACC,OAC9BF,iBAAiBG,KAAK,CAACC,QAAQF,OAAOE,OAAOF,GAAGG,WAAW,GAAGD,GAAAA,GAAM,CAAA;;;AC7KtE,IAAME,kBAAkB;AAOxB,IAAMC,a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",
|
|
6
|
-
"names": ["babel", "babelPresetTypeScript", "babelPresetSolid", "build", "basename", "dirname", "fileURLToPath", "VIRTUAL_NS", "MODULES", "entry", "contents", "entrySrc", "tsx", "mount", "mountSrc", "Loader", "loaderSrc", "bridge", "bridgeSrc", "store", "storeSrc", "types", "typesSrc", "resolveDir", "dirname", "fileURLToPath", "url", "compileLoaderBundle", "virtualSolid", "name", "setup", "esbuild", "onResolve", "filter", "args", "path", "replace", "namespace", "undefined", "onLoad", "module", "result", "transformAsync", "filename", "babelrc", "configFile", "presets", "babelPresetSolid", "generate", "hydratable", "babelPresetTypeScript", "allowDeclareFields", "code", "Error", "loader", "build", "stdin", "sourcefile", "bundle", "format", "platform", "target", "minify", "write", "legalComments", "define", "plugins", "outputFiles", "text", "bundlePromise", "getLoaderBundle", "bootLoaderPlugin", "status", "markSvg", "include", "transformIndexHtml", "_html", "ctx", "basename", "includes", "rootId", "tag", "injectTo", "children", "css", "attrs", "id", "
|
|
3
|
+
"sources": ["../../../src/vite-plugin/boot-loader/loader.ts", "raw-loader:/__w/dxos/dxos/packages/sdk/app-framework/src/vite-plugin/boot-loader/loader-app/boot-loader.css", "raw-loader:/__w/dxos/dxos/packages/sdk/app-framework/src/vite-plugin/boot-loader/loader-app/bridge.ts", "raw-loader:/__w/dxos/dxos/packages/sdk/app-framework/src/vite-plugin/boot-loader/loader-app/entry.tsx", "raw-loader:/__w/dxos/dxos/packages/sdk/app-framework/src/vite-plugin/boot-loader/loader-app/Loader.tsx", "raw-loader:/__w/dxos/dxos/packages/sdk/app-framework/src/vite-plugin/boot-loader/loader-app/mount.tsx", "raw-loader:/__w/dxos/dxos/packages/sdk/app-framework/src/vite-plugin/boot-loader/loader-app/store.ts", "raw-loader:/__w/dxos/dxos/packages/sdk/app-framework/src/vite-plugin/boot-loader/loader-app/types.ts", "../../../src/vite-plugin/composer/index.ts", "../../../src/core/capability.ts", "../../../src/core/plugin.ts", "../../../src/core/plugin-manifest.ts", "../../../src/vite-plugin/load.ts", "../../../src/vite-plugin/manifest.ts", "../../../src/vite-plugin/packages.ts", "../../../src/vite-plugin/import-map/index.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\n// @ts-ignore — @types/babel__core present transitively but not declared here.\nimport * as babel from '@babel/core';\n// @ts-ignore — @babel/preset-typescript ships no .d.ts.\nimport babelPresetTypeScript from '@babel/preset-typescript';\n// @ts-ignore — babel-preset-solid ships no .d.ts.\nimport babelPresetSolid from 'babel-preset-solid';\nimport { type Plugin as EsbuildPlugin, build } from 'esbuild';\nimport { basename, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type Plugin } from 'vite';\n\nimport css from './loader-app/boot-loader.css?raw';\n// The loader-app Solid sources are inlined as raw text (never parsed by\n// dx-compile — app-framework is a React package, so its build can't compile\n// Solid JSX). They are compiled to a self-contained browser IIFE at the\n// consuming app's build time by {@link compileLoaderBundle} below.\nimport bridgeSrc from './loader-app/bridge.ts?raw';\nimport entrySrc from './loader-app/entry.tsx?raw';\nimport loaderSrc from './loader-app/Loader.tsx?raw';\nimport mountSrc from './loader-app/mount.tsx?raw';\nimport storeSrc from './loader-app/store.ts?raw';\nimport typesSrc from './loader-app/types.ts?raw';\n\n/**\n * Options for {@link bootLoaderPlugin}.\n */\nexport type BootLoaderOptions = {\n /**\n * Initial status text rendered by the loader (replaced via\n * `window.__bootLoader.status(...)` once the host starts firing phase callbacks).\n */\n status?: string;\n\n /**\n * Inline SVG markup for an optional brand mark rendered inside the progress\n * ring. The mark renders at full opacity with whatever fills the SVG declares,\n * so pass a colour-palette logo for the strongest visual identity. SVGs that\n * use `fill=\"currentColor\"` still inherit the loader's `prefers-color-scheme`\n * text colour. Leave empty/undefined to render only the ring.\n */\n markSvg?: string;\n\n /**\n * HTML entry filenames to inject the loader into. Defaults to `index.html` only\n * so auxiliary pages (`recovery.html`, `reset.html`, etc.) stay unobstructed.\n */\n include?: string[];\n};\n\nconst VIRTUAL_NS = 'boot-loader-app';\n\n// Relative-import graph of the loader-app, keyed by module name (no extension).\n// `tsx` modules carry JSX (compiled via `babel-preset-solid`); `ts` modules are\n// type-stripped only. `solid-js` imports introduced by the Solid transform\n// resolve from `node_modules` against `resolveDir`.\nconst MODULES: Record<string, { contents: string; tsx: boolean }> = {\n entry: { contents: entrySrc, tsx: true },\n mount: { contents: mountSrc, tsx: true },\n Loader: { contents: loaderSrc, tsx: true },\n bridge: { contents: bridgeSrc, tsx: false },\n store: { contents: storeSrc, tsx: false },\n types: { contents: typesSrc, tsx: false },\n};\n\n// Walk up from the compiled plugin to find a `node_modules` containing\n// `solid-js` (a dependency of this package). Used as esbuild's `resolveDir`.\nconst resolveDir = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Compile the loader-app from its inlined raw sources into a single\n * self-contained IIFE (Solid runtime bundled in) suitable for inlining into\n * `index.html`. Mirrors dx-compile's Solid pipeline: `@babel/preset-typescript`\n * strips types, then `babel-preset-solid` compiles JSX into reactive primitives.\n */\nconst compileLoaderBundle = async (): Promise<string> => {\n const virtualSolid = (): EsbuildPlugin => ({\n name: 'boot-loader-app-virtual',\n setup: (esbuild) => {\n esbuild.onResolve({ filter: /^\\.\\// }, (args) => {\n const name = args.path.replace(/^\\.\\//, '').replace(/\\.(tsx?|jsx?)$/, '');\n return name in MODULES ? { path: name, namespace: VIRTUAL_NS } : undefined;\n });\n\n esbuild.onLoad({ filter: /.*/, namespace: VIRTUAL_NS }, async (args) => {\n const module = MODULES[args.path];\n const result = await babel.transformAsync(module.contents, {\n filename: `${args.path}.${module.tsx ? 'tsx' : 'ts'}`,\n babelrc: false,\n configFile: false,\n // Presets run last-to-first: TS strips first, then Solid sees plain JSX.\n presets: [\n [babelPresetSolid, { generate: 'dom', hydratable: false }],\n [babelPresetTypeScript, { allowDeclareFields: true }],\n ],\n });\n if (!result?.code) {\n throw new Error(`babel-preset-solid returned no code for ${args.path}`);\n }\n return { contents: result.code, loader: 'js', resolveDir };\n });\n },\n });\n\n const result = await build({\n stdin: { contents: \"import './entry';\", loader: 'ts', resolveDir, sourcefile: 'boot-loader-entry.ts' },\n bundle: true,\n format: 'iife',\n platform: 'browser',\n target: 'es2020',\n minify: true,\n write: false,\n legalComments: 'none',\n define: { 'process.env.NODE_ENV': '\"production\"' },\n plugins: [virtualSolid()],\n });\n\n return result.outputFiles[0].text;\n};\n\nlet bundlePromise: Promise<string> | undefined;\nconst getLoaderBundle = (): Promise<string> => (bundlePromise ??= compileLoaderBundle());\n\n/**\n * Vite plugin that injects a Solid \"boot loader\" app into the host app's\n * `index.html`.\n *\n * The full-screen backdrop paints on the very first frame from an inline\n * `<style>` (before any JS bundle is fetched), so the user sees the loading\n * surface immediately on cold load instead of a blank document. A compiled,\n * self-contained Solid IIFE — inlined ahead of the app bundle — then renders\n * the determinate progress ring + status log into that backdrop and exposes the\n * host-facing driver on `window.__bootLoader`.\n *\n * The host app drives the loader (the React relay forwards `useApp`'s startup\n * progress):\n * - `window.__bootLoader.status(payload)` updates the status line per phase.\n * - `window.__bootLoader.progress(fraction)` grows the determinate ring (0–1).\n * - `window.__bootLoader.ready()` plays the dismissal outro, then self-removes.\n * - `window.__bootLoader.dismiss()` removes the loader immediately (fast path).\n *\n * Inject order (all at the start of `<body>`, except the stylesheet):\n * - `<style>` → `<head>` (parses before any bundled stylesheet).\n * - `<div id=\"boot-loader\">` → the static backdrop the CSS styles instantly.\n * - inline `<script>` config (`window.__BOOT_LOADER_CONFIG__`) → before the bundle.\n * - inline `<script>` loader bundle → renders the Solid app into the backdrop.\n *\n * Keeping the loader a sibling of `#root` (rather than a child) means\n * `createRoot(document.getElementById('root')).render(...)` does not fight the\n * loader for ownership; the framework explicitly dismisses after the first\n * React commit for a deterministic handoff.\n *\n * Color tokens are exposed as CSS custom properties (`--boot-loader-bg-light`,\n * etc.) in `boot-loader.css`, so consumers can override them at the document\n * level without re-parameterizing this plugin.\n */\nexport const bootLoaderPlugin = ({ status, markSvg, include = ['index.html'] }: BootLoaderOptions = {}): Plugin => {\n return {\n name: 'app-framework:boot-loader',\n async transformIndexHtml(_html, ctx) {\n const filename = basename(ctx.filename ?? 'index.html');\n if (!include.includes(filename)) {\n return;\n }\n\n const bundle = await getLoaderBundle();\n // Authoritative backdrop id: injected here, passed to the bundle via\n // config (so `entry.tsx` reads it), and mirrored by the CSS selector in\n // `boot-loader.css`. The inner DOM ↔ CSS contract is guarded by the story.\n const rootId = 'boot-loader';\n return [\n {\n tag: 'style',\n injectTo: 'head',\n children: css,\n },\n {\n tag: 'div',\n injectTo: 'body-prepend',\n attrs: {\n 'id': rootId,\n 'role': 'status',\n 'aria-live': 'polite',\n 'aria-label': 'Initializing',\n },\n children: '',\n },\n {\n tag: 'script',\n injectTo: 'body-prepend',\n children: `window.__BOOT_LOADER_CONFIG__=${JSON.stringify({ rootId, markSvg, status })};`,\n },\n {\n tag: 'script',\n injectTo: 'body-prepend',\n children: bundle,\n },\n ];\n },\n };\n};\n", "/*\n * Boot loader stylesheet \u2014 injected into the host's `<head>` by `bootLoaderPlugin`\n * so the full-screen backdrop paints before any JS bundle is fetched. The Solid\n * `Loader` renders the ring + status into the `#boot-loader` backdrop; this\n * sheet styles both. Class/id names here form a contract with `Loader.tsx`,\n * guarded by `BootLoader.solid-stories.tsx` (it mounts the real component).\n */\n\nbody {\n margin: 0;\n overflow: hidden;\n}\n\n/*\n * Defaults match `@dxos/ui-theme`'s `--color-base-surface`, which resolves to\n * Tailwind's `neutral-50` / `neutral-950` in light / dark mode respectively\n * (see `packages/ui/ui-theme/src/css/theme/semantic.css`). Hosts can override\n * with the `--boot-loader-bg-*` / `--boot-loader-fg-*` custom properties on\n * `:root` if they need a different palette. Keeping the boot loader's\n * background identical to the app's `body` eliminates the flash on handoff\n * to the rendered React shell.\n */\n#boot-loader {\n --color-composer-100: rgb(5 40 61);\n --color-composer-200: rgb(10 75 105);\n --color-composer-300: rgb(1 122 183);\n --color-composer-400: rgb(6 197 253);\n\n /*\n * Caps the disc / mark at the design pixel sizes on roomy viewports while\n * shrinking proportionally on narrow ones (`vmin` follows the smaller of\n * width / height) so neither the ring nor the mark crops on phones.\n */\n --boot-loader-disc-size: min(384px, 80vmin);\n /*\n * Match the React `Placeholder`'s logo box (`h-[300px] w-[300px]` at the\n * `stage >= 1` keyframe) so the brand mark doesn't visibly jump size when\n * the loader hands off \u2014 the responsive cap keeps the same 300/384 ratio\n * (\u224878%) at any viewport width.\n */\n --boot-loader-mark-size: min(300px, 62.5vmin);\n --boot-loader-status-gap: 32px;\n\n position: fixed;\n inset: 0;\n z-index: 10;\n font-size: 13px;\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n sans-serif;\n /*\n * Dismissal outro \u2014 `mountLoader` toggles `data-dismissing` on this element\n * when the host calls `__bootLoader.ready()`; the loader cross-fades out over\n * the real app shell rendering beneath it, and removes itself once this\n * opacity transition completes (a fallback timer covers reduced-motion).\n */\n transition: opacity 500ms ease-out;\n}\n\n#boot-loader {\n background: var(--boot-loader-bg-light, #fafafa);\n color: var(--boot-loader-fg-light, #0a0a0a);\n --boot-loader-accent: var(--boot-loader-accent-light, var(--color-composer-200));\n}\n\n@media (prefers-color-scheme: dark) {\n #boot-loader {\n background: var(--boot-loader-bg-dark, #0a0a0a);\n color: var(--boot-loader-fg-dark, #f0f0f0);\n --boot-loader-accent: var(--boot-loader-accent-dark, var(--color-composer-300));\n }\n}\n\n#boot-loader[data-dismissing] {\n opacity: 0;\n}\n\n/* Gently shrink the disc + mark as the loader fades, echoing the prior handoff. */\n#boot-loader[data-dismissing] #boot-loader-disc {\n transform: translate(-50%, -50%) scale(0.92);\n transition: transform 500ms ease-out;\n}\n\n/*\n * Stack the ring (the SVG `#boot-loader-ring`) and the brand mark in the same\n * grid cell so the mark sits centered inside the circle.\n */\n#boot-loader-disc {\n position: absolute;\n top: 50%;\n left: 50%;\n display: grid;\n place-items: center;\n width: var(--boot-loader-disc-size);\n height: var(--boot-loader-disc-size);\n transform: translate(-50%, -50%);\n}\n\n#boot-loader-disc > * {\n grid-column: 1;\n grid-row: 1;\n}\n\n/*\n * Default to grayscale so the mark reads as a quiet monochrome silhouette\n * before any host-driven progress lands; the brand palette swaps in once\n * `Loader.tsx` sets `data-host-driven` on the disc (the first\n * `__bootLoader.progress()` call). Hover keeps a parallel reveal affordance\n * for inspection in the storybook. The 1000ms ease lets the grayscale \u2192 color\n * transition play through the activation phase rather than snapping.\n */\n#boot-loader-mark {\n width: var(--boot-loader-mark-size);\n height: var(--boot-loader-mark-size);\n display: flex;\n align-items: center;\n justify-content: center;\n filter: grayscale(100%);\n transition: filter 1000ms ease-out;\n}\n\n/*\n * `grayscale(0%)` (identity) rather than `none` \u2014 `filter: none` changes\n * the filter function list and most engines treat that as a discrete\n * transition (snap, not ease). Keeping `grayscale(...)` on both sides of\n * the rule lets the browser interpolate the percentage smoothly.\n */\n#boot-loader-disc[data-host-driven] #boot-loader-mark,\n#boot-loader-mark:hover {\n filter: grayscale(0%);\n}\n\n#boot-loader-mark svg {\n width: 100%;\n height: 100%;\n /*\n * The host SVG carries its own brand-palette fills, so we don't apply a\n * `color` cascade here. SVGs that intentionally use `fill=\"currentColor\"`\n * still pick up the loader's text colour via `#boot-loader`'s `color`.\n */\n}\n\n/*\n * Circular determinate progress \u2014 a single SVG `<path>` arc that sweeps\n * anticlockwise from 12 o'clock, its angle growing with progress (the `d` is\n * recomputed by the component each tick). There is no static track;\n * `stroke-linecap: round` rounds the trailing edge, and `marker-end` paints the\n * leading-edge dot. Stroke width is in viewBox units so it scales with the disc.\n */\n#boot-loader-ring {\n width: var(--boot-loader-disc-size);\n height: var(--boot-loader-disc-size);\n overflow: visible;\n /*\n * Fade the arc linearly from the head (the marker, fully opaque) back to the\n * tail (12 o'clock, transparent). A conic-gradient mask does this along the\n * curve \u2014 `Loader.tsx` writes the eased progress into `--boot-loader-arc`\n * (0\u2013100), and the arc occupies the conic range `(100 - arc)%`\u2026`100%`, so the\n * head sits at `(100 - arc)%` (opaque) and the tail at `100%` (transparent).\n * NOTE: We start at -1.16deg so that we don't mask the marker.\n */\n --boot-loader-arc: 0;\n mask: conic-gradient(\n from -1.16deg at 50% 50%,\n transparent 0,\n transparent calc((100 - var(--boot-loader-arc)) * 1%),\n #000 calc((100 - var(--boot-loader-arc)) * 1%),\n transparent 100%\n );\n -webkit-mask: conic-gradient(\n from -1.16deg at 50% 50%,\n transparent 0,\n transparent calc((100 - var(--boot-loader-arc)) * 1%),\n #000 calc((100 - var(--boot-loader-arc)) * 1%),\n transparent 100%\n );\n}\n\n/*\n * The leading-edge dot's layer \u2014 same geometry as `#boot-loader-ring` but with no\n * mask, so the dot renders as a full circle (the ring's conic fade mask would\n * otherwise bisect it where it sits on the mask's transparent\u2192opaque edge).\n */\n#boot-loader-ring-head {\n width: var(--boot-loader-disc-size);\n height: var(--boot-loader-disc-size);\n overflow: visible;\n}\n\n.boot-loader-ring-progress {\n fill: none;\n stroke: var(--boot-loader-accent);\n /* viewBox units: ~1.9px on the 384px disc, scaling down on smaller viewports. */\n stroke-width: 0.5;\n opacity: 0.5;\n stroke-linecap: butt;\n overflow: visible;\n /* Dashed line: dash + gap lengths in viewBox units (~2 units \u2248 7.7px @384px). */\n /* stroke-dasharray: 2 1; */\n}\n\n/* The `marker-end` dot at the arc's leading edge. */\n.boot-loader-ring-marker {\n fill: var(--boot-loader-accent);\n stroke: none;\n overflow: visible;\n /* opacity: 0.5; */\n}\n\n#boot-loader-status {\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n /* \n * Sit just below the centered disc \u2014 half the disc plus the configured gap.\n */\n transform: translate(0, calc(var(--boot-loader-disc-size) / 2 + var(--boot-loader-status-gap)));\n /*\n * Slightly de-emphasised vs body text so the brand mark + ring stay the\n * dominant focus, but high enough to remain legible on both light and dark\n * backgrounds without a custom palette.\n */\n opacity: 0.5;\n /*\n * Terminal-style log viewport (3 rows at the default `line-height`) over\n * a vertically-stacked track of every status the driver has emitted. The\n * track is bottom-anchored via `justify-content: flex-end` so the newest\n * line always sits on the last visible row, older lines stack above it,\n * and anything that doesn't fit is clipped at the top by\n * `overflow: hidden`. The driver runs a FLIP-style transform animation\n * per append so each new line slides up from below the bottom edge \u2014\n * independent of any `scroll-behavior` smooth-scroll support, which\n * Playwright/headless Chrome strips even from spec-compliant\n * `scrollTo({ behavior: 'smooth' })` calls.\n */\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n height: 4.5em;\n line-height: 1.5;\n letter-spacing: 0.01em;\n /* \n * Fixed-width digits so the `(i/n)` counter on range-bearing status\n * updates (\"Loading plugins (12/80)\") doesn't jitter as the index\n * ticks through different glyph widths. \n */\n font-variant-numeric: tabular-nums;\n text-align: center;\n overflow: hidden;\n}\n\n#boot-loader-status-fade {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 32px;\n background: linear-gradient(to bottom, var(--boot-loader-bg-light, #fafafa), transparent);\n z-index: 1;\n}\n@media (prefers-color-scheme: dark) {\n #boot-loader-status-fade {\n background: linear-gradient(to bottom, var(--boot-loader-bg-dark, #0a0a0a), transparent);\n }\n}\n\n#boot-loader-rss {\n background: var(--boot-loader-bg-light, #fafafa);\n text-wrap: balance;\n}\n@media (prefers-color-scheme: dark) {\n #boot-loader-rss {\n background: var(--boot-loader-bg-dark, #0a0a0a);\n }\n}\n\n/*\n * Track of every appended `.boot-loader-status-line`.\n */\n#boot-loader-status-track {\n display: flex;\n flex-direction: column;\n /*\n * Resting transform is `translateY(0)` \u2014 the bottom-anchored flex parent\n * already positions the newest line on the last visible row. On each append\n * `Loader.tsx` runs a one-shot FLIP: snap to `translateY(<lineHeight>px)` with\n * no transition (placing the new line just below the viewport), force a\n * reflow, then animate back to 0 so the track rises by one line-height and the\n * new entry slides up into the bottom row.\n */\n transform: translateY(0);\n transition: transform 500ms ease-out;\n}\n\n/* Honour reduced-motion preferences explicitly \u2014 `transition` doesn't auto-respect it. */\n@media (prefers-reduced-motion: reduce) {\n #boot-loader-status-track {\n transition: none;\n }\n}\n\n.boot-loader-status-line {\n flex: 0 0 auto;\n height: 1.5em;\n white-space: nowrap;\n}\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type LoaderStore } from './store';\nimport { type BootLoaderApi } from './types';\n\n/**\n * Wrap a reactive {@link LoaderStore} as the imperative `window.__bootLoader`\n * facade the host app drives. `status` / `progress` write into the store;\n * `ready` plays the graceful dismissal outro; `dismiss` is the immediate-remove\n * backstop for the fast-load path (and a no-op once an outro is already in\n * flight, so a late `dismiss()` from the framework never cuts the animation).\n */\nexport const createBridge = (store: LoaderStore, dismissNow: () => void): BootLoaderApi => ({\n status: (payload) => store.pushStatus(payload),\n progress: (fraction) => store.setProgress(fraction),\n ready: () => store.ready(),\n dismiss: () => {\n if (store.phase() === 'dismissing') {\n return;\n }\n dismissNow();\n },\n});\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { mountLoader } from './mount';\nimport { DEFAULT_ROOT_ID } from './types';\n\n//\n// Production entry \u2014 bundled to a self-contained IIFE by `bootLoaderPlugin` and\n// inlined into `index.html` ahead of the app bundle. Mounts the loader into the\n// static backdrop using the config the plugin baked in just before this script\n// (including the backdrop id, so the id has a single source). The storybook\n// does NOT use this entry; it imports `mountLoader` directly so Vite compiles\n// the Solid source with HMR.\n//\n\nconst config = window.__BOOT_LOADER_CONFIG__ ?? {};\nconst el = document.getElementById(config.rootId ?? DEFAULT_ROOT_ID);\nif (el) {\n mountLoader(el, config);\n}\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Component, For, createEffect, createSignal, onCleanup, onMount } from 'solid-js';\n\nimport { type LoaderStore } from './store';\n\n// Ring geometry in the SVG's `0 0 100 100` viewBox. The radius leaves a couple\n// of units of padding so the stroke, its round cap, and the end marker aren't\n// clipped at the viewBox edge.\nconst RING_RADIUS = 48;\nconst RING_CENTER = 50;\n// Leading-edge marker: a small dot drawn at the arc's head in an unmasked layer.\nconst MARKER_RADIUS = 1; // viewBox units \u2192 ~3.8px on the 384px disc\n\n/**\n * Read an element's *current animated* translateY (px) from its live transform\n * matrix \u2014 the interpolated value mid-transition, not the last-written property.\n * Used by the status FLIP so successive appends chain off the in-flight position\n * instead of yanking the track back to a fixed invert target.\n */\nconst readTranslateY = (element: HTMLElement): number => {\n const computed = getComputedStyle(element).transform;\n if (!computed || computed === 'none') {\n return 0;\n }\n const match = computed.match(/matrix.*\\(([^)]+)\\)/);\n if (!match) {\n return 0;\n }\n const values = match[1].split(',');\n // 2D `matrix(a, b, c, d, tx, ty)` \u2192 ty at index 5; 3D `matrix3d(...)` \u2192 ty at 13.\n if (values.length === 6) {\n return Number.parseFloat(values[5]) || 0;\n }\n if (values.length === 16) {\n return Number.parseFloat(values[13]) || 0;\n }\n return 0;\n};\n\nexport type LoaderProps = {\n /** Reactive source of truth for progress, status lines, and lifecycle phase. */\n store: LoaderStore;\n /** Inline SVG markup for the brand mark rendered inside the ring. */\n markSvg?: string;\n};\n\n/**\n * The boot loader, authored as a single Solid component \u2014 the one source of\n * truth for the loader DOM. `bootLoaderPlugin` bundles this (Solid runtime\n * inlined) into `index.html`; the storybook mounts the very same component, so\n * the two can no longer drift. The DOM structure, ids, and classes mirror\n * `boot-loader.css`.\n *\n * The full-screen backdrop (`#boot-loader`) is injected as static markup so it\n * paints from CSS before this bundle executes; this component renders the disc\n * and status log *into* that backdrop. The dismissal outro (fading `#boot-loader`)\n * and its teardown are owned by {@link mountLoader}, which has the host element.\n */\nexport const Loader: Component<LoaderProps> = (props) => {\n let trackRef: HTMLDivElement | undefined;\n let previousCount = props.store.lines().length;\n\n // FLIP-style slide on each appended line: snap the track down by one\n // line-height (chained off any in-flight translate) with no transition, force\n // a reflow, then animate back to translateY(0) so the new entry rises from\n // below the bottom-anchored viewport. Range ticks (length unchanged) skip it.\n createEffect(() => {\n const count = props.store.lines().length;\n const track = trackRef;\n if (track && count > previousCount) {\n const currentY = readTranslateY(track);\n const lineHeight = track.lastElementChild?.getBoundingClientRect().height ?? 0;\n track.style.transition = 'none';\n track.style.transform = `translateY(${currentY + lineHeight}px)`;\n void track.offsetHeight;\n track.style.transition = '';\n track.style.transform = 'translateY(0)';\n }\n previousCount = count;\n });\n\n // Eased display progress. A `<path>`'s `d` can't be CSS-transitioned, so the\n // arc would snap on every store tick; instead we ease a displayed value toward\n // the store's progress with a requestAnimationFrame loop (~per-frame lerp) and\n // recompute the path each frame. This restores the compositor-smooth growth\n // the old `transition: stroke-dashoffset` gave, while keeping the path +\n // `marker-end` (the marker rides the arc's recomputed end automatically).\n const [shown, setShown] = createSignal(props.store.progress());\n let raf: number | undefined;\n const animate = () => {\n const target = props.store.progress();\n const current = shown();\n // Snap when within a hair to settle; otherwise lerp ~18% of the gap/frame.\n const next = Math.abs(target - current) < 0.05 ? target : current + (target - current) * 0.18;\n if (next !== current) {\n setShown(next);\n }\n raf = requestAnimationFrame(animate);\n };\n\n onMount(() => {\n raf = requestAnimationFrame(animate);\n });\n\n onCleanup(() => {\n if (raf != null) {\n cancelAnimationFrame(raf);\n }\n });\n\n // Determinate ring as an SVG `<path>` arc: an anticlockwise sweep starting at\n // 12 o'clock whose angle grows with the eased `shown()` progress. The sweep is\n // capped just shy of a full turn so the single arc command never degenerates at\n // 100%. The leading-edge dot is its `head` point, rendered separately (below) in\n // an *unmasked* layer \u2014 drawing it via `marker-end` on this path would put it\n // under the ring's conic fade mask, whose hard edge bisects the dot into a\n // half-circle.\n const arc = () => {\n const fraction = Math.min(shown() / 100, 0.9999);\n const sweep = fraction * 2 * Math.PI;\n const start = -Math.PI / 2; // 12 o'clock\n const end = start - sweep; // anticlockwise (decreasing angle)\n const x0 = RING_CENTER + RING_RADIUS * Math.cos(start);\n const y0 = RING_CENTER + RING_RADIUS * Math.sin(start);\n const headX = RING_CENTER + RING_RADIUS * Math.cos(end);\n const headY = RING_CENTER + RING_RADIUS * Math.sin(end);\n const largeArc = sweep > Math.PI ? 1 : 0;\n // sweep-flag 0 = anticlockwise (negative-angle) direction.\n return { d: `M ${x0} ${y0} A ${RING_RADIUS} ${RING_RADIUS} 0 ${largeArc} 0 ${headX} ${headY}`, headX, headY };\n };\n\n // Once host-driven, the brand mark eases grayscale \u2192 colour and stays there.\n const isHostDriven = () => props.store.phase() !== 'creep';\n\n return (\n <>\n <div id='boot-loader-disc' data-host-driven={isHostDriven() ? '' : undefined}>\n <svg\n id='boot-loader-ring'\n viewBox='0 0 100 100'\n aria-hidden='true'\n style={{ '--boot-loader-arc': String(shown()) }}\n >\n {shown() > 0 ? <path class='boot-loader-ring-progress' d={arc().d} /> : null}\n </svg>\n {/* Leading-edge dot in its own unmasked layer (see `arc()`), so the ring's fade mask\n never clips it. Stacked over `#boot-loader-ring` via the disc grid. */}\n {shown() > 0 ? (\n <svg id='boot-loader-ring-head' viewBox='0 0 100 100' aria-hidden='true'>\n <circle class='boot-loader-ring-marker' cx={arc().headX} cy={arc().headY} r={MARKER_RADIUS} />\n </svg>\n ) : null}\n {props.markSvg ? <div id='boot-loader-mark' innerHTML={props.markSvg} /> : null}\n </div>\n <div id='boot-loader-status'>\n <div id='boot-loader-status-fade' />\n <div id='boot-loader-status-track' ref={trackRef}>\n <For each={props.store.lines()}>{(line) => <div class='boot-loader-status-line'>{line.text}</div>}</For>\n </div>\n </div>\n </>\n );\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { createEffect } from 'solid-js';\nimport { render } from 'solid-js/web';\n\nimport { createBridge } from './bridge';\nimport { Loader } from './Loader';\nimport { createLoaderStore } from './store';\nimport { type BootLoaderConfig } from './types';\n\n/** Fallback teardown if the outro's `transitionend` never fires (e.g. no opacity transition). */\nconst OUTRO_FALLBACK_MS = 800;\n\n/**\n * Mount the boot loader into a host element (`#boot-loader`, the static backdrop\n * the plugin injects \u2014 or any container in the storybook) and install the\n * `window.__bootLoader` facade. Renders the disc + status into the host, toggles\n * `data-dismissing` on it for the outro, and removes everything once the outro\n * completes.\n *\n * Returns a disposer that tears the loader down immediately (idempotent).\n */\nexport const mountLoader = (el: HTMLElement, config: BootLoaderConfig = {}): (() => void) => {\n const store = createLoaderStore(config.status);\n\n let removed = false;\n // Forward-declared so `remove` can dispose the Solid render created below.\n let disposeRender: (() => void) | undefined;\n\n const remove = (): void => {\n if (removed) {\n return;\n }\n removed = true;\n el.removeEventListener('transitionend', handleTransitionEnd);\n store.dispose();\n disposeRender?.();\n el.remove();\n if (window.__bootLoader === api) {\n delete window.__bootLoader;\n }\n };\n\n const handleTransitionEnd = (event: TransitionEvent): void => {\n if (event.propertyName === 'opacity' && store.phase() === 'dismissing') {\n remove();\n }\n };\n el.addEventListener('transitionend', handleTransitionEnd);\n\n disposeRender = render(() => {\n // Drive the backdrop's outro from the host element (Solid owns the host's\n // children; the host attribute is toggled imperatively within this owner).\n createEffect(() => {\n const dismissing = store.phase() === 'dismissing';\n el.toggleAttribute('data-dismissing', dismissing);\n if (dismissing) {\n setTimeout(remove, OUTRO_FALLBACK_MS);\n }\n });\n return <Loader store={store} markSvg={config.markSvg} />;\n }, el);\n\n const api = createBridge(store, remove);\n window.__bootLoader = api;\n\n return remove;\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Accessor, createSignal } from 'solid-js';\n\nimport { type StatusPayload } from './types';\n\n//\n// Creep tuning. The ring auto-creeps toward a moving ceiling so a long\n// activation silence never reads as a frozen disc. See the original\n// hand-written driver for the rationale behind each constant.\n//\n\n/** Creep timer cadence, in milliseconds. */\nexport const CREEP_TICK_MS = 100;\n/** State-1 ease rate \u2014 a gentle \"we're alive\" hint before real progress lands. */\nexport const STATE_1_RATE = 0.05;\n/** State-1 asymptote (percent) the creep eases toward before host progress. */\nexport const STATE_1_ASYMPTOTE = 40;\n/** State-2 ease rate \u2014 bridges the gap between sparse host `progress()` calls. */\nexport const STATE_2_RATE = 0.05;\n/** State-2 lead (percent) the ceiling sits ahead of the last host value. */\nexport const STATE_2_BUMP = 15;\n/** Hard ceiling the auto-creep never crosses (host must drive the rest). */\nexport const ABSOLUTE_CEILING = 90;\n\n/** Loader lifecycle phase. */\nexport type Phase = 'creep' | 'host' | 'dismissing';\n\n/** A single rendered status line; `id` keys the `<For>` and survives in-place range ticks. */\nexport type StatusLine = {\n id: number;\n text: string;\n event?: string;\n module?: string;\n};\n\n/**\n * Asymptotic ease \u2014 `next = raw + (ceiling - raw) * rate`, clamped so it never\n * overshoots (or regresses past) the ceiling. Pure; unit-tested.\n */\nexport const easeToward = (raw: number, ceiling: number, rate: number): number =>\n raw >= ceiling - 0.1 ? raw : raw + (ceiling - raw) * rate;\n\n/**\n * Clamp a host-supplied fraction to a percent in [0, 100]. Invalid / negative /\n * non-finite values collapse to 0 rather than poisoning the CSS var. Pure;\n * unit-tested.\n */\nexport const clampPercent = (fraction?: number): number =>\n typeof fraction !== 'number' || !Number.isFinite(fraction) || fraction < 0 ? 0 : Math.min(1, fraction) * 100;\n\n/** Display text for a payload \u2014 appends the `(index/total)` suffix when a range is present. */\nexport const displayText = (payload: StatusPayload): string =>\n payload.range ? `${payload.humanized} (${payload.range.index}/${payload.range.total})` : payload.humanized;\n\n/**\n * Reactive loader store \u2014 owns the progress percent, the status-line log, and\n * the lifecycle phase, plus the auto-creep timer. All DOM-free, so the creep\n * math and status reduction are testable as plain functions; `Loader.tsx` binds\n * the accessors to the DOM and `bridge.ts` wraps the mutators as the imperative\n * `window.__bootLoader` facade.\n */\nexport type LoaderStore = {\n /** Progress as a percent in [0, 100] (the CSS `--boot-loader-bar-progress` value). */\n progress: Accessor<number>;\n /** Appended status lines, newest last. */\n lines: Accessor<StatusLine[]>;\n /** Current lifecycle phase. */\n phase: Accessor<Phase>;\n /** Apply a status update (append, or replace-in-place for range ticks). */\n pushStatus: (payload: StatusPayload) => void;\n /** Enter host-driven progress with `fraction` \u2208 [0, 1]; never regresses. */\n setProgress: (fraction?: number) => void;\n /** Snap to 100%, stop the creep, and enter the dismissing phase. */\n ready: () => void;\n /** Stop the creep timer (call on teardown). */\n dispose: () => void;\n};\n\nexport const createLoaderStore = (initialStatus?: string): LoaderStore => {\n const [progress, setProgressPct] = createSignal(0);\n const [lines, setLines] = createSignal<StatusLine[]>(initialStatus ? [{ id: 0, text: initialStatus }] : []);\n const [phase, setPhase] = createSignal<Phase>('creep');\n\n let creepCeiling = STATE_1_ASYMPTOTE;\n let creepRate = STATE_1_RATE;\n let nextId = initialStatus ? 1 : 0;\n let timer: ReturnType<typeof setInterval> | null = null;\n\n const startCreep = (): void => {\n if (timer == null) {\n timer = setInterval(() => setProgressPct((raw) => easeToward(raw, creepCeiling, creepRate)), CREEP_TICK_MS);\n }\n };\n\n const stopCreep = (): void => {\n if (timer != null) {\n clearInterval(timer);\n timer = null;\n }\n };\n\n const pushStatus = (payload: StatusPayload): void => {\n const text = displayText(payload);\n setLines((current) => {\n const previous = current.at(-1);\n // Dedup back-to-back identical transitions (same text + structured fields).\n if (\n previous &&\n previous.text === text &&\n (previous.event ?? null) === (payload.event ?? null) &&\n (previous.module ?? null) === (payload.module ?? null)\n ) {\n return current;\n }\n // Range tick \u2014 replace the current line in place rather than appending,\n // so a counted phase produces one entry with an updating suffix.\n if (payload.range && previous) {\n return [...current.slice(0, -1), { ...previous, text }];\n }\n return [...current, { id: nextId++, text, event: payload.event, module: payload.module }];\n });\n };\n\n const setProgress = (fraction?: number): void => {\n setPhase('host');\n const pct = clampPercent(fraction);\n // The ring never regresses: hold the current value if the host reports lower.\n setProgressPct((current) => Math.max(current, pct));\n // Switch the creep to its state-2 cadence and lead the host value by a bump.\n creepRate = STATE_2_RATE;\n creepCeiling = Math.min(Math.max(creepCeiling, pct + STATE_2_BUMP), ABSOLUTE_CEILING);\n startCreep();\n };\n\n const ready = (): void => {\n stopCreep();\n setProgressPct(100);\n setPhase('dismissing');\n };\n\n const dispose = (): void => stopCreep();\n\n startCreep();\n\n return { progress, lines, phase, pushStatus, setProgress, ready, dispose };\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\n/**\n * Status payload accepted by `window.__bootLoader.status(...)`. The caller owns\n * formatting \u2014 `humanized` is the exact text rendered \u2014 while `event` / `module`\n * carry the structured activation ids for the boot trace, and `range` drives an\n * in-place `(index/total)` counter for long counted phases.\n */\nexport type StatusPayload = {\n /**\n * Raw activation event key (e.g. `dxos.org/plugin/observability/activate`)\n * when the transition is event-level.\n */\n event?: string;\n\n /**\n * Raw module id (e.g. `org.dxos.plugin.observability.module.ReactSurface`)\n * when the transition is module-level.\n */\n module?: string;\n\n /** Exact text to display (e.g. \"Activating Observability: react-surface\"). */\n humanized: string;\n\n /**\n * Optional `(index/total)` tick. When present the loader replaces the current\n * line in place (\"Loading plugins (12/80)\") instead of appending a new entry \u2014\n * keeps the visible log compact during long counted phases.\n */\n range?: { index: number; total: number };\n};\n\n/**\n * Imperative facade exposed on `window.__bootLoader`, installed by the inlined\n * loader bundle and driven by the host app (the React relay forwards `useApp`'s\n * startup progress through it).\n */\nexport type BootLoaderApi = {\n /** Update the visible status line. */\n status: (payload: StatusPayload) => void;\n /** Enter host-driven progress \u2014 `fraction` \u2208 [0, 1]. */\n progress: (fraction?: number) => void;\n /** Play the dismissal outro, then remove the loader DOM (graceful path). */\n ready: () => void;\n /** Remove the loader DOM immediately (fast-load backstop / terminal). */\n dismiss: () => void;\n};\n\n/**\n * Config baked into `index.html` by `bootLoaderPlugin` ahead of the loader\n * bundle, so the compiled app stays static (compiled once, independent of the\n * host's brand mark / initial status).\n */\nexport type BootLoaderConfig = {\n /**\n * Id of the static backdrop element the plugin injects and the loader mounts\n * into \u2014 the single coupling between `transformIndexHtml` and the app. The\n * plugin owns the authoritative value and passes it here so `entry.tsx` reads\n * it rather than hardcoding (the CSS selector mirrors it \u2014 see `boot-loader.css`).\n */\n rootId?: string;\n /** Inline SVG markup for the brand mark rendered inside the ring. */\n markSvg?: string;\n /** Initial status text rendered before the host fires its first `status(...)`. */\n status?: string;\n};\n\n/** Fallback backdrop id when no config is present (kept in sync with `loader.ts` + the CSS). */\nexport const DEFAULT_ROOT_ID = 'boot-loader';\n\ndeclare global {\n interface Window {\n __bootLoader?: BootLoaderApi;\n __BOOT_LOADER_CONFIG__?: BootLoaderConfig;\n }\n}\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { type Plugin as VitePlugin } from 'vite';\n\nimport { Plugin, PLUGIN_DEV_SERVER_PORT } from '../../core';\nimport { findDxConfigFile, loadDxConfig } from '../load';\nimport { type BuildMeta, ENTRY_FILENAME, MANIFEST_ASSET_NAME, serializeManifest, toBuildMeta } from '../manifest';\nimport { DEFAULT_PACKAGES, isSharedPackage } from '../packages';\n\nexport { ENTRY_FILENAME, MANIFEST_ASSET_NAME, serializeManifest };\nexport type { BuildMeta };\n\nconst JSX_DEV_RUNTIME = 'react/jsx-dev-runtime';\n\n/** Reads `version` from the project's `package.json`; falls back to `0.0.0`. */\nconst readPackageVersion = (dir: string): string => {\n try {\n return JSON.parse(readFileSync(join(dir, 'package.json'), 'utf-8')).version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n};\n\n/**\n * Snapshot the project's declared `dependencies`, resolving each to its concrete\n * installed version (read from `node_modules/<name>/package.json`) so the manifest\n * records exactly what the plugin was built against — the host derives SDK\n * compatibility from the `@dxos/*` subset. Falls back to the declared spec when a\n * dependency can't be resolved on disk.\n */\nconst readResolvedDependencies = (dir: string): Record<string, string> | undefined => {\n try {\n const declared = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf-8')).dependencies as\n | Record<string, string>\n | undefined;\n if (!declared) {\n return undefined;\n }\n const resolved: Record<string, string> = {};\n for (const name of Object.keys(declared)) {\n try {\n const version = JSON.parse(readFileSync(join(dir, 'node_modules', name, 'package.json'), 'utf-8')).version;\n resolved[name] = typeof version === 'string' ? version : declared[name];\n } catch {\n resolved[name] = declared[name];\n }\n }\n return Object.keys(resolved).length > 0 ? resolved : undefined;\n } catch {\n return undefined;\n }\n};\n\n/**\n * Whether an import should be externalized by the plugin bundle.\n * Uses the shared-package predicate directly so plugins automatically pick up any\n * new `@dxos/*` (non-plugin) package the host provides, without a code change here.\n */\nconst isExternal = (id: string) => id !== JSX_DEV_RUNTIME && isSharedPackage(id);\n\n/**\n * Banner injected at the top of every plugin bundle.\n *\n * Why: rolldown emits ESM `import` for externalized deps, but when a *bundled* module\n * is CJS and contains `require('react')` (or any other external), rolldown keeps the\n * `require(...)` call in the output and relies on a runtime `require` function. The\n * browser doesn't have `require`, so rolldown's fallback shim throws:\n * `Calling `require` for \"react\" in an environment that doesn't expose the `require`\n * function`.\n *\n * The full dependency graphs of non-trivial plugins unavoidably drag in CJS-only\n * helpers (`use-sync-external-store` via xstate / zustand / preact-signals / … ),\n * and waiting for every one of those packages to ship ESM isn't realistic. Instead\n * we install a tiny module-local `require` at the top of the bundle that looks up\n * a handful of well-known host-provided modules by name and returns their already\n * ESM-imported namespaces. Rolldown's own shim honours an existing `require`\n * before falling through to the throw path, so this entirely removes the runtime\n * error without changing how externalization itself works.\n *\n * Keep the list aligned with the externals that CJS code actually reaches for;\n * adding entries here is safe (unused imports get tree-shaken), but the list is\n * deliberately small to keep the banner noise-free.\n */\nconst REQUIRE_SHIM_BANNER = [\n '// --- composer-plugin: CJS require shim ---',\n '// See @dxos/app-framework/vite-plugin/composer-plugin.ts for rationale.',\n \"import * as __composerReact from 'react';\",\n \"import * as __composerReactDom from 'react-dom';\",\n \"import * as __composerReactJsxRuntime from 'react/jsx-runtime';\",\n 'const __composerRequireShim = new Map([',\n \" ['react', __composerReact.default ?? __composerReact],\",\n \" ['react-dom', __composerReactDom.default ?? __composerReactDom],\",\n \" ['react/jsx-runtime', __composerReactJsxRuntime],\",\n ']);',\n \"// Module-local binding: rolldown's CJS fallback does a `typeof require` check\",\n '// and uses whichever `require` is in lexical scope. Declaring this as `const`',\n \"// (instead of `globalThis.require ??=`) keeps each bundle's shim isolated from\",\n '// the host page and from other plugins sharing the window.',\n 'const require = (id) => {',\n ' if (__composerRequireShim.has(id)) return __composerRequireShim.get(id);',\n \" throw new Error('composer-plugin: unsupported CJS require at runtime: ' + id);\",\n '};',\n '// --- end CJS require shim ---',\n].join('\\n');\n\nexport type ComposerPluginOptions = {\n /** Entry point for the plugin bundle. Defaults to `src/plugin.tsx`. */\n entry?: string;\n /** Dev server port. Defaults to {@link PLUGIN_DEV_SERVER_PORT}. */\n port?: number;\n /**\n * Path to the project's `dx.config.ts`. Defaults to auto-discovery in the project root\n * (`dx.config.{ts,mjs,js}`). Used only to derive the manifest metadata.\n */\n config?: string;\n /**\n * Plugin metadata. Optional — when omitted it is derived from the project's `dx.config.ts`\n * (`@dxos/protocols` `Config2.Config`) plus the `package.json` version and resolved dependencies. When\n * present (explicitly or derived), a `manifest.json` asset is emitted alongside the bundle listing\n * every emitted file. The host fetches this manifest at install time and persists the declared\n * assets in its offline cache so the plugin works without network. The bundle's entry module is\n * always written as {@link ENTRY_FILENAME} (`index.mjs`).\n */\n meta?: BuildMeta;\n};\n\n/**\n * Vite plugin for **external Composer plugin projects**. Configures the build to produce\n * an ESM bundle that externalizes all framework dependencies, which the Composer host app\n * provides at runtime via import map.\n *\n * Handles:\n * 1. Build config — lib mode entry point, ES format output, rollup externals, code-split chunks.\n * 2. Dev externalization — marks shared deps as external during `vite serve` and strips\n * the `/@id/` prefix that Vite's import analysis adds to external bare specifiers.\n * 3. JSX dev runtime shim — bridges `react/jsx-dev-runtime` (used by React refresh in dev)\n * to `react/jsx-runtime` (which is what the externalized React provides).\n * 4. Manifest emit — when `meta` is supplied, writes `manifest.json` next to the bundled\n * module listing every emitted asset (entry, CSS, chunks, etc.) so the host can eagerly\n * cache them for offline use.\n */\nexport const composerPlugin = (options?: ComposerPluginOptions): VitePlugin[] => {\n const entry = options?.entry ?? 'src/plugin.tsx';\n const port = options?.port ?? PLUGIN_DEV_SERVER_PORT;\n const projectRoot = process.cwd();\n\n // Plugin metadata source of truth is `dx.config.ts` (`@dxos/protocols` `Config2.Config`). When the caller\n // doesn't pass `meta` explicitly, load + validate the config and derive a `BuildMeta` from it\n // (augmented with the package `version` and a resolved dependency snapshot). Resolved once,\n // lazily, so the synchronous plugin factory stays sync; the manifest hooks await it.\n const metaPromise: Promise<BuildMeta | undefined> = options?.meta\n ? Promise.resolve(options.meta)\n : Promise.resolve(options?.config ?? findDxConfigFile(projectRoot)).then((configFile) =>\n configFile\n ? loadDxConfig(configFile).then((config) =>\n toBuildMeta(\n Plugin.getMetaFromConfig(config),\n readPackageVersion(projectRoot),\n readResolvedDependencies(projectRoot),\n ),\n )\n : undefined,\n );\n const resolved = new Set<string>();\n let base = '/';\n\n const plugins: VitePlugin[] = [\n // Configure vite for library-mode builds with externalized deps.\n {\n name: 'composer-plugin',\n config: () => ({\n server: {\n port,\n // Allow the Composer host (different origin) to dynamically import plugin modules.\n cors: true,\n },\n preview: { port },\n build: {\n sourcemap: true,\n // Transitively-bundled WASM modules (automerge, tiktoken, …) emit top-level\n // await; `esnext` lets rolldown pass that through without an explicit polyfill.\n target: 'esnext',\n lib: {\n entry,\n formats: ['es'],\n fileName: () => ENTRY_FILENAME,\n },\n rolldownOptions: {\n external: (id: string) => isExternal(id),\n output: {\n chunkFileNames: 'chunks/[name]-[hash].js',\n assetFileNames: 'assets/[name]-[hash][extname]',\n // Install the CJS require shim at the top of plugin.mjs so transitively\n // bundled CJS helpers (that call `require('react')` et al. at runtime) can\n // resolve against the host-provided externals instead of throwing.\n banner: REQUIRE_SHIM_BANNER,\n },\n },\n },\n }),\n },\n\n // Dev-time externalization.\n // Vite's dev server doesn't use rollup externals, so we need to handle it manually.\n // We intercept imports of shared deps at resolve time, mark them external, and then\n // strip the `/@id/` prefix that Vite's import analysis injects for external modules.\n {\n name: 'composer-plugin:externalize',\n enforce: 'pre',\n apply: 'serve',\n // Exclude shared packages from Vite's dependency pre-bundling.\n config: () => ({\n optimizeDeps: {\n exclude: DEFAULT_PACKAGES,\n },\n }),\n // Mark shared deps as external so Vite doesn't try to bundle them.\n resolveId: (id) => {\n if (isExternal(id)) {\n resolved.add(id);\n return { id, external: true };\n }\n },\n // Return a stub for any externalized module that Vite tries to load directly.\n load: (id) => {\n if (resolved.has(id)) {\n return { code: 'export default {};' };\n }\n },\n // After all plugins are resolved, inject a late-stage transform plugin that strips\n // the `/@id/` prefix from externalized bare specifiers in the output.\n // This must run after Vite's internal import analysis which rewrites bare specifiers.\n configResolved: (config) => {\n base = config.base ?? '/';\n (config.plugins as VitePlugin[]).push({\n name: 'composer-plugin:strip-prefix',\n transform: (code: string) => {\n if (resolved.size === 0) {\n return;\n }\n const escaped = [...resolved].map((s) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|');\n const pattern = new RegExp(`${base}@id/(${escaped})`, 'g');\n if (pattern.test(code)) {\n return code.replace(pattern, (_: string, dep: string) => dep);\n }\n },\n });\n },\n },\n\n // JSX dev runtime shim.\n // React refresh (used by @vitejs/plugin-react) imports from `react/jsx-dev-runtime`,\n // but the externalized React only exposes `react/jsx-runtime`. This virtual module\n // bridges the gap by re-exporting jsx-runtime's functions under jsx-dev-runtime's API.\n {\n name: 'composer-plugin:jsx-dev-shim',\n enforce: 'pre',\n apply: 'serve',\n resolveId: (id) => (id === JSX_DEV_RUNTIME ? `\\0${JSX_DEV_RUNTIME}` : undefined),\n load: (id) =>\n id === `\\0${JSX_DEV_RUNTIME}`\n ? [\n 'import { jsx, jsxs, Fragment } from \"react/jsx-runtime\";',\n 'export { Fragment };',\n 'export function jsxDEV(type, props, key, isStaticChildren) {',\n ' return isStaticChildren ? jsxs(type, props, key) : jsx(type, props, key);',\n '}',\n ].join('\\n')\n : undefined,\n },\n\n // React Refresh preamble stub.\n //\n // @vitejs/plugin-react's JSX transform prepends a runtime check to every module:\n // if (!window.$RefreshReg$) throw new Error(\"@vitejs/plugin-react can't detect preamble…\");\n // In a normal single-origin app, vite injects a `<script type=\"module\">` preamble\n // into `index.html` that sets up `$RefreshReg$` / `$RefreshSig$` on `window` before any\n // app code runs. When a community plugin is dev-served at its own origin and then\n // dynamic-imported into the Composer host at a different origin, the host's window\n // never receives that preamble, so every JSX module throws on first import.\n //\n // Inject a no-op refresh shim on the host's window from the plugin's entrypoint: fast-\n // refresh itself doesn't work cross-origin anyway, so silencing the check lets the\n // plugin load and ordinary page reloads take care of picking up edits. Production\n // builds are untouched (`apply: 'serve'`).\n {\n name: 'composer-plugin:react-refresh-shim',\n enforce: 'pre',\n apply: 'serve',\n transform(code, id) {\n // Only patch the plugin entrypoint (an absolute path ending in the configured entry).\n // Matching by suffix keeps us from prepending the shim to every transformed module,\n // which would both bloat the output and defeat vite's caching.\n if (!id.endsWith(entry.replace(/^\\.?\\//, '/'))) {\n return;\n }\n const shim = [\n '// composer-plugin: no-op React Refresh shim so cross-origin plugin modules',\n \"// don't throw the @vitejs/plugin-react preamble check at dynamic-import time.\",\n 'if (typeof window !== \"undefined\") {',\n ' window.$RefreshReg$ = window.$RefreshReg$ || (() => {});',\n ' window.$RefreshSig$ = window.$RefreshSig$ || (() => (type) => type);',\n ' window.__vite_plugin_react_preamble_installed__ = true;',\n '}',\n '',\n ].join('\\n');\n return { code: shim + code, map: null };\n },\n },\n ];\n\n // Emit `manifest.json` alongside the built module listing every emitted asset, so the\n // dist directory can be uploaded as-is to a GitHub Release for the DXOS community\n // registry to pick up. The host loader fetches this file at install time and eagerly\n // caches every listed asset for offline use. No-ops when no `dx.config.ts`/`meta` resolves.\n plugins.push({\n name: 'composer-plugin:emit-manifest',\n apply: 'build',\n // `enforce: 'post'` is load-bearing: vite's CSS extraction plugin emits sibling\n // `.css` assets in its own `generateBundle` hook. Without `post`, ours runs first\n // and sees only the JS chunks — the manifest then omits CSS, so the host can't\n // inject `<link>` tags for the plugin's stylesheet at install time.\n enforce: 'post',\n async generateBundle(_options, bundle) {\n const meta = await metaPromise;\n if (!meta) {\n return;\n }\n // Source maps are large and only fetched when devtools opens — exclude them\n // from the manifest so the host doesn't precache megabytes of debug data.\n const assets = Object.keys(bundle)\n .filter((name) => name !== MANIFEST_ASSET_NAME && !name.endsWith('.map'))\n .sort();\n this.emitFile({\n type: 'asset',\n fileName: MANIFEST_ASSET_NAME,\n source: serializeManifest(meta, { assets }),\n });\n },\n });\n\n // Dev-server manifest. `vite dev` can't enumerate transitive chunks/CSS up front\n // (they resolve on demand), so we serve a `devEntry`-flavored manifest at the dev\n // root and let the host loader skip eager caching + static stylesheet injection.\n // The host imports `entry` directly from the dev server, where Vite handles\n // JSX transforms, externalization, and runtime CSS injection.\n plugins.push({\n name: 'composer-plugin:serve-manifest',\n apply: 'serve',\n async configureServer(server) {\n const meta = await metaPromise;\n if (!meta) {\n return;\n }\n const body = serializeManifest(meta, { assets: [], devEntry: entry.replace(/^\\.?\\//, '') });\n server.middlewares.use(`/${MANIFEST_ASSET_NAME}`, (req, res, next) => {\n // Only intercept the bare manifest URL — let any sub-paths fall through.\n if (req.url && req.url !== '/' && req.url !== '') {\n return next();\n }\n // CORS mirrors `server.cors: true` (see plugin config above) so the host\n // app at a different origin can read the manifest. Vite's built-in CORS\n // covers most paths but middlewares mounted before its `cors` middleware\n // need to set the header themselves.\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Content-Type', 'application/json');\n res.setHeader('Cache-Control', 'no-store');\n res.statusCode = 200;\n res.end(body);\n });\n },\n });\n\n return plugins;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Atom } from '@effect-atom/atom-react';\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nimport type { DXN } from '@dxos/keys';\n\nimport type * as CapabilityManager from './capability-manager';\nimport type * as Plugin from './plugin';\n\n//\n// Capability Service Layer\n//\n\n/**\n * Effect Context.Tag for accessing CapabilityManager via the Effect layer system.\n * This allows capability modules to access the capability manager without having it passed as an argument.\n */\nexport class Service extends Context.Tag('@dxos/app-framework/CapabilityManager')<\n Service,\n CapabilityManager.CapabilityManager\n>() {}\n\n/**\n * Get a single capability from the capability manager.\n * @param interfaceDef The interface definition of the capability.\n * @returns The capability implementation.\n * @throws If no capability is found.\n */\n// TODO(wittjosiah): Add custom tagged errors (Data.TaggedError) for app-framework to enable\n// type-safe error handling with Effect. Consider CapabilityNotFoundError, ModuleActivationError, etc.\nexport const get = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T, Error, Service> =>\n Effect.flatMap(Service, (manager) =>\n Effect.try({\n try: () => manager.get(interfaceDef),\n catch: (error) => (error instanceof Error ? error : new Error(String(error))),\n }),\n );\n\n/**\n * Get all capabilities from the capability manager for a given interface.\n * @param interfaceDef The interface definition of the capability.\n * @returns An array of capability implementations.\n */\nexport const getAll = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T[], never, Service> =>\n Effect.map(Service, (manager) => manager.getAll(interfaceDef));\n\n/**\n * Wait for a capability to be available.\n * @param interfaceDef The interface definition of the capability.\n * @returns The capability implementation once available.\n */\nexport const waitFor = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.waitFor(interfaceDef));\n\n/**\n * Get the Atom reference to capabilities for reactive access.\n * @param interfaceDef The interface definition of the capability.\n * @returns An Atom containing the array of capability implementations.\n */\nexport const atom = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<Atom.Atom<T[]>, never, Service> =>\n Effect.map(Service, (manager) => manager.atom(interfaceDef));\n\n/**\n * Get capabilities grouped by the module that contributed them.\n * @param interfaceDef The interface definition of the capability.\n * @returns An Atom containing a record from module ID to capability implementations.\n */\nexport const atomByModule = <T>(\n interfaceDef: InterfaceDef<T>,\n): Effect.Effect<Atom.Atom<Record<string, T[]>>, never, Service> =>\n Effect.map(Service, (manager) => manager.atomByModule(interfaceDef));\n\n/**\n * Constructs a layer that will request its interface implementation from the capability manager.\n */\nexport const asLayer = <T, I>(interfaceDef: InterfaceDef<T>, tag: Context.Tag<I, T>): Layer.Layer<I, never, Service> =>\n Layer.effect(tag, get(interfaceDef).pipe(Effect.orDie));\n\nconst InterfaceDefTypeId: unique symbol = Symbol.for('InterfaceDefTypeId');\n\n/**\n * Symbol used to tag lazy capability functions with their module ID.\n */\nexport const ModuleTag: unique symbol = Symbol.for('@dxos/app-framework/ModuleTag');\n\n/**\n * The interface definition of a capability.\n */\nexport type InterfaceDef<T> = {\n [InterfaceDefTypeId]: T;\n identifier: string;\n};\n\nexport namespace InterfaceDef {\n export type Implementation<I extends InterfaceDef<any>> = I extends InterfaceDef<infer T> ? T : never;\n}\n\n/**\n * Helper to define the interface of a capability.\n * Static NSID strings are validated at compile time via {@link DXN.Name}.\n */\nexport const make: {\n <T, S extends string = string>(\n identifier: [DXN.Name<S>] extends [never] ? `Invalid NSID \"${S}\": final segment must be camelCase (no hyphens)` : S,\n ): InterfaceDef<T>;\n} = <T>(identifier: string): InterfaceDef<T> => {\n return { identifier } as InterfaceDef<T>;\n};\n\n/**\n * A unique string identifier with a Typescript type associated with it.\n * When a capability is contributed to the application an implementation of the interface is provided.\n */\nexport type Capability<T> = {\n /**\n * The interface definition of the capability.\n */\n readonly interface: InterfaceDef<T>;\n\n /**\n * The implementation of the capability.\n */\n readonly implementation: T;\n\n /**\n * Called when the capability is deactivated.\n */\n readonly deactivate?: () => Effect.Effect<void, Error>;\n};\n\nexport type Any = Capability<any>;\n\n/**\n * Union type representing all valid return types for a capability module.\n * Supports single capabilities, arrays, and tuples of different capability types.\n */\nexport type ModuleReturn = void | Any | Any[] | readonly Any[] | [Any, ...Any[]] | readonly [Any, ...Any[]];\n\n/**\n * Helper to define the implementation of a capability.\n * Returns the opaque base type so callers cannot discriminate on capability kind,\n * keeping d.ts emit portable across packages.\n */\nexport const contributes = <I extends InterfaceDef<any>>(\n interfaceDef: I,\n implementation: Capability<InterfaceDef.Implementation<I>>['implementation'],\n deactivate?: Capability<InterfaceDef.Implementation<I>>['deactivate'],\n): Any => {\n return {\n interface: interfaceDef,\n implementation,\n deactivate,\n } satisfies Capability<I>;\n};\n\ntype LoadCapability<Props, Capabilities extends ModuleReturn = ModuleReturn> = () => Promise<{\n default: (props: Props) => Effect.Effect<Capabilities, Error, Service | Plugin.Service | never>;\n}>;\ntype LoadCapabilities<Props, Capabilities extends ModuleReturn = ModuleReturn> = () => Promise<{\n default: (props: Props) => Effect.Effect<Capabilities, Error, Service | Plugin.Service | never>;\n}>;\n\ntype NormalizeReturn<R> = R extends readonly (infer A)[]\n ? A[]\n : R extends (infer A)[]\n ? A[]\n : R extends Any\n ? [R]\n : Any[];\n\nexport type LazyCapability<Props = void, Capabilities extends ModuleReturn = ModuleReturn, E extends Error = Error> = (\n props: Props,\n) => Effect.Effect<NormalizeReturn<Capabilities>, E, Service | Plugin.Service | never>;\n\n/**\n * Helper to define a lazily loaded implementation of a capability.\n * Supports single capabilities, arrays, and tuples of different capability types.\n * @param name The export name (e.g., 'AppGraphBuilder') - used to auto-compute module IDs.\n * @param loader The lazy loader function.\n * @returns A lazy capability function with ModuleTag symbol attached.\n */\nexport const lazy = <T = void, R extends ModuleReturn = ModuleReturn>(\n name: string,\n c: LoadCapability<T, R> | LoadCapabilities<T, R>,\n): LazyCapability<T> => {\n const lazyFn = (props: T) =>\n Effect.gen(function* () {\n const { default: getCapability } = yield* Effect.promise(() => c());\n const result = yield* getCapability(props);\n const normalized = result == null ? [] : Array.isArray(result) ? Array.from(result) : [result];\n return normalized as NormalizeReturn<R>;\n });\n\n // Props (T) are preserved so callers pass correctly-typed options, but the contributed\n // Capabilities type is widened to the opaque base. The concrete capability type often traces to a\n // module-internal source path that TypeScript cannot name in declaration files (TS2883); the base\n // type is portable. The contributed type is checked at Capability.contributes regardless.\n return Object.assign(lazyFn, { [ModuleTag]: name }) as LazyCapability<T>;\n};\n\n/**\n * Gets the module tag (export name) from a lazy capability function.\n * @param capability The lazy capability function.\n * @returns The module tag if present, undefined otherwise.\n */\n// TODO(wittjosiah): Stricter type for capability.\nexport const getModuleTag = (capability: unknown): string | undefined => {\n return capability && typeof capability === 'function' && ModuleTag in capability\n ? String(capability[ModuleTag])\n : undefined;\n};\n\n/**\n * Helper to define a capability module with explicit typing.\n * Wraps the default export function to provide better type inference and make the pattern explicit.\n *\n * This helper provides explicit typing for the module activation function,\n * making it clear that the function should:\n * - Access CapabilityManager via the Effect layer system (Capability.get, Capability.getAll, etc.)\n * - Return a capability, array of capabilities, or tuple of different capability types (sync or async)\n *\n * Supports returning multiple capabilities of different types as a tuple, which will be normalized\n * to an array at runtime for compatibility with the plugin system.\n *\n * @example\n * ```ts\n * // Module without options - single capability\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* () {\n * const client = yield* Capability.get(ClientCapabilities.Client);\n * return contributes(Capabilities.SettingsStore, store);\n * })\n * );\n *\n * // Module with multiple capabilities\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* () {\n * return [\n * contributes(Capabilities.SettingsStore, store),\n * contributes(Capabilities.Translations, translations),\n * ];\n * })\n * );\n *\n * // Module with required options (context accessed via layer)\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* (props: { observability: boolean }) {\n * const invoker = yield* Capability.get(Capabilities.OperationInvoker);\n * return contributes(Capabilities.OperationHandler, ...);\n * })\n * );\n * ```\n */\nexport const makeModule = <\n TProps = void,\n TReturn extends ModuleReturn = ModuleReturn,\n E extends Error = Error,\n R extends Service | Plugin.Service | never = Service,\n>(\n fn: (props: TProps) => Effect.Effect<TReturn, E, R>,\n): ((props: TProps) => Effect.Effect<TReturn, E, R>) => fn;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\nimport * as Pipeable from 'effect/Pipeable';\nimport * as Schema from 'effect/Schema';\n\nimport { BaseError } from '@dxos/errors';\nimport { invariant } from '@dxos/invariant';\nimport { DXN } from '@dxos/keys';\nimport { Config2, PluginProfileSchema, PluginReleaseSchema } from '@dxos/protocols';\n\nimport type * as ActivationEvent from './activation-event';\nimport * as Capability from './capability';\nimport type * as PluginManager from './plugin-manager';\n\n//\n// Plugin Service Layer\n//\n\n/**\n * Effect Context.Tag for accessing PluginManager via the Effect layer system.\n * This allows lifecycle operations to access the plugin manager without having it passed as an argument.\n */\nexport class Service extends Context.Tag('@dxos/app-framework/PluginManager')<Service, PluginManager.PluginManager>() {}\n\n//\n// Lifecycle Functions\n//\n\n/**\n * Activates plugins based on the activation event.\n * Accesses the PluginManager via the Effect layer system.\n * @param event The activation event.\n * @returns Whether the activation was successful.\n */\nexport const activate = (event: ActivationEvent.ActivationEvent): Effect.Effect<boolean, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.activate(event));\n\n/**\n * Re-activates the modules that were activated by the event.\n * Accesses the PluginManager via the Effect layer system.\n * @param event The activation event.\n * @returns Whether the reset was successful.\n */\nexport const reset = (event: ActivationEvent.ActivationEvent): Effect.Effect<boolean, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.reset(event));\n\n/**\n * Shuts down the plugin manager, deactivating all active modules and clearing lifecycle state.\n * Accesses the PluginManager via the Effect layer system.\n */\nexport const shutdown = (): Effect.Effect<boolean, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.shutdown());\n\n/**\n * Computes a module ID from plugin ID and export name.\n */\nconst computeModuleId = (pluginId: string, moduleName: string): string => {\n return `${pluginId}.module.${moduleName}`;\n};\n\n/**\n * Identifier denoting a PluginModule.\n */\nexport const PluginModuleTypeId: unique symbol = Symbol.for('@dxos/app-framework/PluginModule');\nexport type PluginModuleTypeId = typeof PluginModuleTypeId;\n\n/**\n * Type guard to check if a value is a PluginModule.\n */\nexport const isPluginModule = (value: unknown): value is PluginModule => {\n return typeof value === 'object' && value !== null && PluginModuleTypeId in value;\n};\n\n/**\n * A unit of containment of modular functionality that can be provided to an application.\n * Activation of a module is async allowing for code to split and loaded lazily.\n */\nexport interface PluginModule {\n readonly [PluginModuleTypeId]: PluginModuleTypeId;\n /**\n * Unique id of the module.\n */\n id: string;\n\n /**\n * Events for which the module will be activated.\n */\n activatesOn: ActivationEvent.Events;\n\n /**\n * Events that this module fires *before* its own activation runs.\n *\n * When this module is asked to activate (via {@link activatesOn}), the\n * plugin manager first activates every event listed here, ensuring any\n * other modules that contribute to those events have completed before\n * this module's {@link activate} body executes. These events are fired\n * by the framework on this module's behalf — the module does not need\n * to wait for some other code to fire them.\n *\n * The module is marked as needing reset if a module activated by one\n * of these events is later removed.\n *\n * Read as: \"this module fires these events before [its] activation\".\n */\n firesBeforeActivation?: ActivationEvent.ActivationEvent[];\n\n /**\n * Events that this module fires *after* its own activation completes.\n *\n * Once this module's {@link activate} body has finished executing, the\n * plugin manager activates every event listed here, causing any modules\n * listening on those events to run. These events are fired by the\n * framework on this module's behalf as part of this module's lifecycle.\n *\n * Read as: \"this module fires these events after [its] activation\".\n */\n firesAfterActivation?: ActivationEvent.ActivationEvent[];\n\n /**\n * Called when the module is activated.\n * CapabilityManager is accessed via the Effect layer system (Capability.Service).\n * PluginManager is accessed via Plugin.Service.\n * @param props Optional props passed to the module.\n * @returns The capabilities of the module.\n */\n activate: (props?: any) => Effect.Effect<Capability.ModuleReturn, Error, Capability.Service | Service | never>;\n}\n\nexport type PluginModuleOptions = Omit<PluginModule, 'id' | typeof PluginModuleTypeId> & { id?: string };\n\nclass PluginModuleImpl implements PluginModule {\n readonly [PluginModuleTypeId]: PluginModuleTypeId = PluginModuleTypeId;\n readonly id: PluginModule['id'];\n readonly activatesOn: PluginModule['activatesOn'];\n readonly firesBeforeActivation?: PluginModule['firesBeforeActivation'];\n readonly firesAfterActivation?: PluginModule['firesAfterActivation'];\n readonly activate: PluginModule['activate'];\n\n constructor(options: Omit<PluginModule, typeof PluginModuleTypeId>) {\n this.id = options.id;\n this.activatesOn = options.activatesOn;\n this.firesBeforeActivation = options.firesBeforeActivation;\n this.firesAfterActivation = options.firesAfterActivation;\n this.activate = options.activate;\n }\n}\n\n/**\n * Runtime plugin metadata, derived from the `@dxos/protocols` registry schemas (protocols owns the\n * config + registry schemas; the runtime projection lives here).\n *\n * - {@link Profile}: version-independent identity + display + provenance — the wire `PluginProfileSchema`\n * (which carries `key`, the display fields, `dependsOn`, `spec`) plus `author` (resolved at runtime\n * from the publisher's handle/DID for registry plugins, or self-declared for bundled).\n * - {@link Release}: a specific hosted release — the wire `PluginReleaseSchema` (version, moduleUrl, dependencies).\n * - {@link Meta}: a resolved single-release view — `{ profile, release? }`, both nested. `release` is\n * unset for bundled plugins (compiled in) and set for registry plugins.\n */\nexport const Profile = Schema.Struct({\n ...PluginProfileSchema.fields,\n author: Schema.optional(Schema.String),\n});\nexport type Profile = Schema.Schema.Type<typeof Profile>;\n\nexport const Release = PluginReleaseSchema;\nexport type Release = Schema.Schema.Type<typeof Release>;\n\nexport const Meta = Schema.Struct({\n profile: Profile,\n release: Schema.optional(Release),\n});\nexport type Meta = Schema.Schema.Type<typeof Meta>;\n\n/** Options for {@link makeMeta}: the {@link Profile} content fields plus the canonical DXN `key`. */\nexport type MakeMetaOptions = {\n key: DXN.DXN;\n name: string;\n description?: string;\n author?: string;\n homePage?: string;\n source?: string;\n tags?: readonly string[];\n dependsOn?: readonly string[];\n spec?: string;\n icon?: Config2.Icon;\n screenshots?: ReadonlyArray<Config2.Screenshot>;\n};\n\n/** Constructs a bundled-plugin {@link Meta} from a canonical DXN. `profile.key` is the bare NSID derived from `key`. */\nexport const makeMeta = (options: MakeMetaOptions): Meta => {\n const { key, ...rest } = options;\n return { profile: { ...rest, key: DXN.getName(key) } };\n};\n\n/** Returns the plugin's canonical DXN URI, constructed from `meta.profile.key` and `meta.release?.version`. */\nexport const getURI = (meta: Meta): DXN.DXN => DXN.make(meta.profile.key, meta.release?.version);\n\n/**\n * Derives a runtime {@link Meta} from a loaded `dx.config.ts` (the `@dxos/protocols` `Config2.Config`).\n * Maps the flat authoring config to the nested profile; bundled plugins have no `release`.\n */\nexport const getMetaFromConfig = ({ plugin }: Config2.Config): Meta => {\n const { key, ...rest } = plugin;\n return makeMeta({ key: DXN.make(key), ...rest });\n};\n\n/**\n * Identifier denoting a Plugin.\n */\nexport const PluginTypeId: unique symbol = Symbol.for('@dxos/app-framework/Plugin');\nexport type PluginTypeId = typeof PluginTypeId;\n\n/**\n * Type guard to check if a value is a Plugin.\n */\nexport const isPlugin = (value: unknown): value is Plugin => {\n return typeof value === 'object' && value !== null && PluginTypeId in value;\n};\n\n/**\n * A collection of modules that are be enabled/disabled as a unit.\n * Plugins provide things such as components, state, actions, etc. to the application.\n */\n// TODO(burdon): Convert to ECHO schema.\nexport interface Plugin {\n readonly [PluginTypeId]: PluginTypeId;\n readonly meta: Readonly<Meta>;\n readonly modules: ReadonlyArray<PluginModule>;\n}\n\n/**\n * Internal implementation of Plugin.\n * @internal\n */\nclass PluginImpl implements Plugin {\n readonly [PluginTypeId]: PluginTypeId = PluginTypeId;\n\n constructor(\n private readonly _meta: Meta,\n private readonly _modules: PluginModule[],\n ) {}\n\n get meta(): Readonly<Meta> {\n return this._meta;\n }\n\n get modules(): ReadonlyArray<PluginModule> {\n return this._modules;\n }\n}\n\n/**\n * Builder interface for creating plugins incrementally.\n */\nexport interface PluginBuilder<T = void> extends Pipeable.Pipeable {\n readonly meta: Meta;\n readonly modules: ReadonlyArray<PluginModuleOptions | ((options: T) => PluginModuleOptions)>;\n addModule(moduleOptions: PluginModuleOptions | ((options: T) => PluginModuleOptions)): PluginBuilder<T>;\n}\n\n/**\n * Builder implementation for creating plugins incrementally.\n */\nclass PluginBuilderImpl<T = void> implements PluginBuilder<T> {\n readonly meta: Meta;\n private readonly _modules: Array<PluginModuleOptions | ((options: T) => PluginModuleOptions)> = [];\n\n constructor(meta: Meta) {\n this.meta = meta;\n }\n\n get modules(): ReadonlyArray<PluginModuleOptions | ((options: T) => PluginModuleOptions)> {\n return this._modules;\n }\n\n addModule(moduleOptions: PluginModuleOptions | ((options: T) => PluginModuleOptions)): PluginBuilder<T> {\n this._modules.push(moduleOptions);\n return this;\n }\n\n pipe() {\n // eslint-disable-next-line prefer-rest-params\n return Pipeable.pipeArguments(this, arguments);\n }\n}\n\n/**\n * Creates a new PluginBuilder to start building a plugin.\n */\nexport const define = <T = void>(meta: Meta): PluginBuilder<T> => new PluginBuilderImpl<T>(meta);\n\n/**\n * Adds a module to a plugin builder.\n * Supports both pipeline and direct call styles.\n * Modules can be either PluginModuleOptions or functions that receive options.\n */\nexport function addModule<T>(\n moduleOptions: PluginModuleOptions | ((options: T) => PluginModuleOptions),\n): (builder: PluginBuilder<T>) => PluginBuilder<T>;\nexport function addModule<T>(\n builder: PluginBuilder<T>,\n moduleOptions: PluginModuleOptions | ((options: T) => PluginModuleOptions),\n): PluginBuilder<T>;\nexport function addModule<T>(\n moduleOptionsOrBuilder: PluginModuleOptions | ((options: T) => PluginModuleOptions) | PluginBuilder<T>,\n moduleOptions?: PluginModuleOptions | ((options: T) => PluginModuleOptions),\n): ((builder: PluginBuilder<T>) => PluginBuilder<T>) | PluginBuilder<T> {\n // If second arg is provided, it's the direct call style: addModule(builder, moduleOptions)\n if (moduleOptions !== undefined) {\n return (moduleOptionsOrBuilder as PluginBuilder<T>).addModule(moduleOptions);\n }\n // Otherwise it's pipeline style: addModule(moduleOptions) returns a function\n const moduleOpts = moduleOptionsOrBuilder as PluginModuleOptions | ((options: T) => PluginModuleOptions);\n return (builder: PluginBuilder<T>) => builder.addModule(moduleOpts);\n}\n\nexport type PluginFactory<T = void> = ((options: T) => Plugin) & { meta: Meta };\n\n/**\n * Resolves a module from either PluginModuleOptions or a function that returns PluginModuleOptions.\n */\nconst resolveModule = (\n meta: Meta,\n module: PluginModuleOptions | ((options: any) => PluginModuleOptions),\n options?: any,\n): PluginModuleImpl => {\n const moduleOptions = typeof module === 'function' ? module(options) : module;\n const pluginName = meta.profile.key;\n const id = Option.fromNullable(moduleOptions.id).pipe(\n Option.match({\n onNone: () => {\n const exportName = Capability.getModuleTag(moduleOptions.activate);\n invariant(exportName, `Plugin module missing name. Plugin: ${meta.profile.key}`);\n return computeModuleId(pluginName, exportName);\n },\n onSome: (id) => computeModuleId(pluginName, id),\n }),\n );\n return new PluginModuleImpl({ ...moduleOptions, id });\n};\n\n/**\n * Creates a Plugin from a builder.\n * Supports both pipeline and direct call styles.\n * Always returns a factory function (options: T) => Plugin.\n * When T is void, the function takes no arguments: () => Plugin.\n */\nexport function make<T>(builder: PluginBuilder<T>): PluginFactory<T>;\nexport function make<T>(builder: PluginBuilder<T>): PluginFactory<T> {\n const meta = builder.meta;\n // `dependsOn` entries and `key` are both bare NSIDs, so compare directly.\n invariant(\n !meta.profile.dependsOn?.includes(meta.profile.key),\n `Plugin ${meta.profile.key} declares itself as a dependency.`,\n );\n\n const factory = (options: T) => {\n const modules = builder.modules.map((module) => resolveModule(meta, module, options));\n return new PluginImpl(meta, modules);\n };\n\n return Object.assign(factory, { meta });\n}\n\n//\n// Lazy plugin loading\n//\n\n/**\n * Symbol used to tag lazy plugin stubs with their loader closure.\n * Hidden from enumeration so plugin manager iteration / serialization paths\n * don't trip over it.\n */\nconst LazyTag: unique symbol = Symbol.for('@dxos/app-framework/Plugin/Lazy');\n\n/**\n * Async loader for a lazy plugin's real implementation.\n * The default export of the loaded module must be a `PluginFactory<T>` —\n * i.e. the same shape `Plugin.make` produces.\n */\nexport type LazyLoader<T = void> = () => Promise<{ default: PluginFactory<T> }>;\n\n/** Internal: payload carried on a lazy stub. */\ntype LazyPayload = { loader: LazyLoader<any>; options: unknown };\n\n/**\n * Defines a lazy plugin whose body is loaded on first enable.\n *\n * The returned factory produces a stub `Plugin` that exposes `meta`\n * synchronously (so callers can read `Plugin.meta.profile.key` for free) but defers\n * loading the real plugin's modules until the manager calls\n * `Plugin.resolveLazy`. This lets the plugin's main entry point ship as a\n * tiny meta-only chunk — the heavy capabilities, schema, React surfaces,\n * etc. live behind the dynamic `import()` and become a separate Rollup\n * chunk that is only fetched when the plugin is enabled.\n *\n * @example\n * ```ts\n * // plugin-markdown/src/index.ts\n * import { Plugin } from '@dxos/app-framework';\n * import { meta } from './meta';\n *\n * export const MarkdownPlugin = Plugin.lazy(meta, () => import('./MarkdownPlugin'));\n *\n * // plugin-markdown/src/MarkdownPlugin.tsx\n * export const MarkdownPlugin = Plugin.define(meta).pipe(...heavy modules..., Plugin.make);\n * export default MarkdownPlugin;\n * ```\n */\nexport const lazy = <T = void>(meta: Meta, loader: LazyLoader<T>): PluginFactory<T> => {\n const factory = (options: T): Plugin => {\n const stub = new PluginImpl(meta, []);\n Object.defineProperty(stub, LazyTag, {\n value: { loader, options } satisfies LazyPayload,\n enumerable: false,\n });\n return stub;\n };\n return Object.assign(factory, { meta });\n};\n\n/**\n * Type guard for lazy plugin stubs produced by {@link lazy}.\n */\nexport const isLazy = (plugin: Plugin): boolean => LazyTag in plugin;\n\n/**\n * Tagged error for failures during lazy plugin resolution. `context.id` is\n * the lazy plugin's `meta.profile.key`; `context.reason` discriminates the failure\n * mode (`'load-failed' | 'missing-default' | 'invalid-plugin' |\n * 'meta-mismatch'`) so callers can route on it.\n */\nexport class LazyPluginError extends BaseError.extend('LazyPluginError', 'Failed to resolve lazy plugin') {}\n\n/**\n * Tagged error for plugin-level dependency resolution failures.\n *\n * `context.id` is the plugin id the manager was acting on. `context.reason`\n * discriminates the failure mode:\n * - `'missing'` — declared dep is neither registered nor in the catalog.\n * `context.missing` lists offending ids.\n * - `'install-failed'` — dep was found in the catalog but `add()` failed.\n * `cause` carries the original error.\n * - `'cycle'` — closure walk detected a cycle. `context.path` is the cycle path.\n * - `'core-dependent'` — cascade-disable would have to disable a core plugin.\n * `context.coreDependent` is the blocking id.\n */\nexport class PluginDependencyError extends BaseError.extend(\n 'PluginDependencyError',\n 'Plugin dependency resolution failed',\n) {}\n\n/**\n * Resolves a lazy plugin stub to its real plugin.\n * Returns the plugin unchanged if it is not lazy. Failures surface as\n * {@link LazyPluginError} with `context.reason` indicating the failure mode\n * and (for loader failures) `cause` set to the original error.\n */\nexport const resolveLazy = (plugin: Plugin): Effect.Effect<Plugin, LazyPluginError> =>\n Effect.gen(function* () {\n if (!isLazy(plugin)) {\n return plugin;\n }\n const id = plugin.meta.profile.key;\n const { loader, options } = (plugin as unknown as { [LazyTag]: LazyPayload })[LazyTag];\n const mod = yield* Effect.tryPromise({\n try: loader,\n catch: (error) => new LazyPluginError({ context: { id, reason: 'load-failed' }, cause: error }),\n });\n if (!mod || typeof mod.default !== 'function') {\n return yield* Effect.fail(new LazyPluginError({ context: { id, reason: 'missing-default' } }));\n }\n const result = mod.default(options);\n if (!isPlugin(result)) {\n return yield* Effect.fail(new LazyPluginError({ context: { id, reason: 'invalid-plugin' } }));\n }\n if (result.meta.profile.key !== id) {\n return yield* Effect.fail(\n new LazyPluginError({ context: { id, reason: 'meta-mismatch', returnedId: result.meta.profile.key } }),\n );\n }\n return result;\n });\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport * as FetchHttpClient from '@effect/platform/FetchHttpClient';\nimport * as HttpClient from '@effect/platform/HttpClient';\nimport * as HttpClientRequest from '@effect/platform/HttpClientRequest';\nimport * as HttpClientResponse from '@effect/platform/HttpClientResponse';\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n\nimport { BaseError } from '@dxos/errors';\nimport { PLUGIN_ENTRY_FILENAME, PluginManifestSchema } from '@dxos/protocols';\n\n/**\n * Default port the Vite plugin (`composerPlugin`) binds the dev server to.\n *\n * Shared single source of truth — `composerPlugin` reads it as the default\n * port, and the host's \"Load Dev Plugin\" affordance pre-fills the manifest URL\n * with `http://localhost:${PLUGIN_DEV_SERVER_PORT}/manifest.json`. Lives in\n * app-framework rather than `@dxos/protocols` because the constant is a\n * client-side convention (host loader + Vite plugin) rather than a wire-level\n * protocol.\n */\nexport const PLUGIN_DEV_SERVER_PORT = 3967;\n\n/**\n * Tagged error for manifest fetch / parse failures. Construction sites set\n * `context.manifestUrl` and `context.reason` (one of `'fetch-failed' |\n * 'http-error' | 'parse-failed' | 'invalid'`) so handlers can route on the\n * specific failure mode.\n */\nexport class PluginManifestError extends BaseError.extend('PluginManifestError', 'Plugin manifest is invalid') {}\n\n/**\n * Schema for a third-party plugin manifest.\n *\n * Production manifests are published as a sibling of the plugin's entry module\n * ({@link PLUGIN_ENTRY_FILENAME}) and advertise every file the plugin needs at\n * runtime so the host can eagerly cache them for offline use.\n *\n * Dev manifests (served by `vite dev` via {@link composerPlugin}) set `devEntry`\n * to point at the unbundled source entry. The host's loader treats the presence\n * of `devEntry` as the dev-mode signal: it imports the entry directly from the\n * dev server, skips eager asset caching, and skips static stylesheet injection\n * (Vite handles CSS via runtime `<style>` injection during HMR). `assets` is not\n * required to enumerate every file in dev mode — chunks and styles flow through\n * the dev server on demand.\n */\nexport const Manifest = Schema.Struct({\n // Reuse the build manifest field definitions from `@dxos/protocols` (the shape `composerPlugin`\n // emits), minus `assets` which we relax below, plus the dev-only `devEntry`.\n ...PluginManifestSchema.omit('assets').fields,\n /**\n * Relative asset paths. Relaxed vs the build `PluginManifestSchema` (which requires >= 1) because\n * dev-server manifests list no assets — chunks/styles flow through the dev server on demand.\n */\n assets: Schema.Array(Schema.String),\n /** Present only for dev-server manifests; points at the unbundled source entry. */\n devEntry: Schema.optional(Schema.String),\n});\n\nexport type Manifest = Schema.Schema.Type<typeof Manifest>;\n\n/**\n * Resolved manifest with all asset paths converted to absolute URLs.\n *\n * `dev` reflects whether the source manifest declared a `devEntry`. Loaders branch\n * on this to skip offline caching and stylesheet injection — both are no-ops (or\n * actively wrong) when the plugin is being served by a Vite dev server.\n */\nexport type ResolvedManifest = Pick<Manifest, 'key' | 'name' | 'version' | 'dependencies'> & {\n entryUrl: string;\n assetUrls: readonly string[];\n dev: boolean;\n};\n\n/**\n * Resolves a parsed manifest's relative asset paths against the manifest's URL.\n * In dev mode the entry comes from `devEntry`; otherwise it's the canonical\n * {@link PLUGIN_ENTRY_FILENAME} sitting next to the manifest.\n */\nconst resolve = (manifestUrl: string, manifest: Manifest): ResolvedManifest => {\n const dev = manifest.devEntry !== undefined;\n return {\n key: manifest.key,\n name: manifest.name,\n version: manifest.version,\n entryUrl: new URL(dev ? manifest.devEntry! : PLUGIN_ENTRY_FILENAME, manifestUrl).toString(),\n assetUrls: manifest.assets.map((asset) => new URL(asset, manifestUrl).toString()),\n dev,\n ...(manifest.dependencies !== undefined ? { dependencies: manifest.dependencies } : {}),\n };\n};\n\n/**\n * Synchronous decode + validate + resolve for an in-memory manifest payload. Used\n * by tests and tooling that have the manifest body already loaded; the runtime\n * path goes through {@link fetchManifest}.\n */\nexport const parse = (manifestUrl: string, payload: unknown): ResolvedManifest => {\n const manifest = Schema.decodeUnknownSync(Manifest)(payload);\n if (manifest.devEntry === undefined && !manifest.assets.includes(PLUGIN_ENTRY_FILENAME)) {\n throw new Error(`Manifest at ${manifestUrl} does not list ${PLUGIN_ENTRY_FILENAME} in assets.`);\n }\n return resolve(manifestUrl, manifest);\n};\n\n/**\n * Fetches and parses a manifest from the given URL via Effect's HTTP client and\n * Schema-driven JSON decoding. All failure modes surface as a single tagged\n * {@link PluginManifestError}; callers route on `error.context.reason`.\n */\nexport const fetchManifest = (manifestUrl: string): Effect.Effect<ResolvedManifest, PluginManifestError> =>\n Effect.gen(function* () {\n const response = yield* HttpClientRequest.get(manifestUrl).pipe(\n HttpClient.execute,\n Effect.mapError((cause) => new PluginManifestError({ context: { manifestUrl, reason: 'fetch-failed' }, cause })),\n );\n if (response.status >= 400) {\n return yield* Effect.fail(\n new PluginManifestError({ context: { manifestUrl, reason: 'http-error', status: response.status } }),\n );\n }\n const manifest = yield* HttpClientResponse.schemaBodyJson(Manifest)(response).pipe(\n Effect.mapError((cause) => new PluginManifestError({ context: { manifestUrl, reason: 'parse-failed' }, cause })),\n );\n if (manifest.devEntry === undefined && !manifest.assets.includes(PLUGIN_ENTRY_FILENAME)) {\n return yield* Effect.fail(\n new PluginManifestError({\n context: { manifestUrl, reason: 'invalid' },\n cause: `assets does not include ${PLUGIN_ENTRY_FILENAME}`,\n }),\n );\n }\n return resolve(manifestUrl, manifest);\n }).pipe(Effect.scoped, Effect.provide(FetchHttpClient.layer));\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport { build } from 'esbuild';\nimport { randomUUID } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { rm, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { Config2 } from '@dxos/protocols';\n\nconst CONFIG_BASENAMES = ['dx.config.ts', 'dx.config.mjs', 'dx.config.js'];\n\nconst decodeConfig2 = Schema.decodeUnknownSync(Config2.Config);\n\n/**\n * Resolves the first `dx.config.{ts,mjs,js}` found under `dir`, or `undefined` if none exist.\n * Pass the result to {@link loadDxConfig}.\n */\nexport const findDxConfigFile = (dir: string): string | undefined =>\n CONFIG_BASENAMES.map((basename) => join(dir, basename)).find((candidate) => existsSync(candidate));\n\n/**\n * Loads and validates a `dx.config.ts` (or `.mjs`/`.js`) file at the given `filePath`.\n *\n * Transpiles the file with esbuild — leaving its bare imports (`@dxos/protocols`, `@dxos/app-framework`, …)\n * external so they resolve from the project's `node_modules` — imports the result, then decodes the\n * default export against the `Config2` schema (a malformed config throws a `Schema` parse error).\n * Node-only (esbuild + filesystem); used by `composerPlugin` and `dx registry publish`.\n */\nexport const loadDxConfig = async (filePath: string): Promise<Config2.Config> => {\n const result = await build({\n entryPoints: [filePath],\n bundle: true,\n format: 'esm',\n platform: 'node',\n write: false,\n // Leave node_modules (incl. @dxos/*) as runtime imports so the temp module below resolves them\n // from the project's node_modules rather than inlining heavy deps (effect, etc.) on every load.\n packages: 'external',\n logLevel: 'silent',\n });\n\n // Import via a temp file so its externalized bare specifiers resolve against the project's\n // node_modules (a data-URL import cannot resolve bare specifiers).\n const tempPath = join(filePath, '..', `.dx.config.${randomUUID()}.mjs`);\n try {\n await writeFile(tempPath, result.outputFiles[0].text, 'utf-8');\n const module = await import(pathToFileURL(tempPath).href);\n return decodeConfig2(module.default);\n } finally {\n await rm(tempPath, { force: true });\n }\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { PLUGIN_ENTRY_FILENAME } from '@dxos/protocols';\n\nimport { type Plugin } from '../core';\n\n/**\n * Name of the asset written alongside the built module bundle.\n * The DXOS community registry resolves each published plugin by fetching this file\n * from the repo's latest GitHub Release, so authors should not rename it.\n */\nexport const MANIFEST_ASSET_NAME = 'manifest.json';\n\n/**\n * Canonical entry filename (re-exported from `@dxos/protocols`) so vite-plugin\n * consumers don't have to reach into the protocols package directly.\n */\nexport const ENTRY_FILENAME = PLUGIN_ENTRY_FILENAME;\n\n/**\n * Flat plugin metadata emitted into `manifest.json` at build time (the shape validated by\n * `@dxos/protocols` `PluginManifestSchema`).\n *\n * The runtime {@link Plugin.Meta} nests its display/identity fields under `profile`; the build\n * manifest is intentionally flat, so this is the {@link Plugin.Profile} content plus build-time fields:\n * the package `version`, and a `dependencies` snapshot (every declared dependency resolved to its\n * concrete installed version). The host derives SDK compatibility from the subset of `dependencies`\n * it shares with the plugin (the externalized `@dxos/*` packages); the rest are recorded for transparency.\n */\nexport type BuildMeta = Plugin.Profile & { version: string; dependencies?: Record<string, string> };\n\n/**\n * Flattens a runtime {@link Plugin.Meta}'s `profile` and augments it with the build-time fields\n * needed to emit `manifest.json`: the package `version` (from the publishing project's `package.json`)\n * and an optional resolved `dependencies` snapshot. Produces the {@link BuildMeta} that `composerPlugin`\n * serializes.\n */\nexport const toBuildMeta = (meta: Plugin.Meta, version: string, dependencies?: Record<string, string>): BuildMeta => ({\n ...meta.profile,\n version,\n ...(dependencies ? { dependencies } : {}),\n});\n\n/**\n * Serializes a plugin's public metadata + bundle layout into the format consumed\n * by the host loader (see `UrlLoader.make` and `PluginManifest.parse`).\n *\n * The host fetches this manifest, resolves every entry in `assets` against the\n * manifest URL, and persists them via the platform `PluginAssetCache` so the\n * plugin works offline. For production builds the entry module is always\n * {@link ENTRY_FILENAME} and must appear in `assets`. For dev-server manifests\n * pass `devEntry` (a path relative to the manifest URL) — the host then imports\n * the entry directly from the dev server and skips offline caching, since the\n * full asset graph isn't enumerable until build time.\n *\n * Exported from a vite-free module so tests and tooling can validate manifests\n * without paying the cost of loading vite + esbuild.\n */\nexport const serializeManifest = (\n meta: BuildMeta,\n { assets, devEntry }: { assets: readonly string[]; devEntry?: string },\n): string => {\n return JSON.stringify(\n {\n ...meta,\n assets,\n ...(devEntry !== undefined ? { devEntry } : {}),\n },\n null,\n 2,\n );\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\n/**\n * Packages shared between the Composer host app and remote plugins.\n *\n * {@link DEFAULT_PACKAGES} is the single source of truth: `importMapPlugin` emits\n * one wrapper chunk per entry so the host serves it at runtime, and `composerPlugin`\n * (via {@link isSharedPackage}) externalizes the same set from plugin bundles.\n * Adding a new `@dxos/*` (or third-party) package that plugins may depend on means\n * adding it here — in one place — so the externalization contract stays in sync\n * with what the host actually provides.\n *\n * Every entry must also be a **direct** dependency of composer-app's `package.json`,\n * including packages that are only re-exported by an umbrella (e.g. via subpath\n * re-exports from another listed package). pnpm doesn't symlink transitive deps\n * into a package's own `node_modules`, so the import-map plugin's `this.resolve`\n * call fails for transitive-only entries and the importmap silently drops them —\n * leaving plugins with bare specifiers the host can't satisfy at install time.\n *\n * Plugin packages (`@dxos/plugin-*`) are intentionally NOT listed: community plugins\n * bundle their own copy of any plugin-subpath import, which is safe because those\n * exports are limited to lightweight types/operation defs.\n */\n\n/**\n * Non-`@dxos/*` packages the Composer host provides to plugins via import map.\n * Spread into {@link DEFAULT_PACKAGES} so the third-party set lives in one place.\n */\nconst THIRD_PARTY_SHARED_PACKAGES = [\n '@effect-atom/atom',\n '@effect-atom/atom-react',\n '@effect/platform',\n 'effect',\n 'lit',\n 'react',\n 'react-dom',\n 'solid-js',\n];\n\nexport const DEFAULT_PACKAGES = [\n // packages/common\n '@dxos/async',\n '@dxos/codec-protobuf',\n '@dxos/context',\n '@dxos/crypto',\n '@dxos/debug',\n '@dxos/display-name',\n '@dxos/effect',\n '@dxos/effect-atom-solid',\n '@dxos/errors',\n '@dxos/feed-store',\n '@dxos/graph',\n '@dxos/hypercore',\n '@dxos/invariant',\n '@dxos/keyboard',\n '@dxos/keys',\n '@dxos/kv-store',\n '@dxos/log',\n '@dxos/merkle-search-tree',\n '@dxos/random',\n '@dxos/random-access-storage',\n '@dxos/timeframe',\n '@dxos/tracing',\n '@dxos/util',\n '@dxos/web-context',\n '@dxos/web-context-react',\n '@dxos/web-context-solid',\n\n // packages/core/echo\n '@dxos/echo',\n '@dxos/echo-client',\n '@dxos/echo-host',\n '@dxos/echo-protocol',\n '@dxos/echo-query',\n '@dxos/echo-react',\n '@dxos/echo-solid',\n '@dxos/feed',\n '@dxos/index-core',\n\n // packages/core/halo\n '@dxos/credentials',\n '@dxos/keyring',\n\n // packages/core/mesh\n '@dxos/edge-client',\n '@dxos/messaging',\n '@dxos/network-manager',\n '@dxos/rpc',\n '@dxos/rpc-tunnel',\n '@dxos/teleport',\n '@dxos/teleport-extension-automerge-replicator',\n '@dxos/teleport-extension-gossip',\n '@dxos/teleport-extension-object-sync',\n '@dxos/teleport-extension-replicator',\n '@dxos/websocket-rpc',\n\n // packages/core\n '@dxos/ai',\n '@dxos/assistant',\n '@dxos/assistant-toolkit',\n '@dxos/compute',\n '@dxos/conductor',\n '@dxos/functions',\n '@dxos/functions-runtime',\n '@dxos/mcp-client',\n '@dxos/operation',\n '@dxos/protocols',\n\n // packages/devtools\n '@dxos/devtools',\n\n // packages/sdk\n '@dxos/app-framework',\n '@dxos/app-graph',\n '@dxos/app-solid',\n '@dxos/app-toolkit',\n '@dxos/client',\n '@dxos/client-protocol',\n '@dxos/client-services',\n '@dxos/config',\n '@dxos/migrations',\n '@dxos/observability',\n '@dxos/react-client',\n '@dxos/react-edge-client',\n '@dxos/schema',\n '@dxos/types',\n\n // packages/ui\n '@dxos/lit-grid',\n '@dxos/lit-ui',\n '@dxos/react-hooks',\n '@dxos/react-ui',\n '@dxos/react-ui-attention',\n '@dxos/react-ui-audio',\n '@dxos/react-ui-board',\n '@dxos/react-ui-calendar',\n '@dxos/react-ui-canvas',\n '@dxos/react-ui-canvas-compute',\n '@dxos/react-ui-canvas-editor',\n '@dxos/react-ui-chat',\n '@dxos/react-ui-components',\n '@dxos/react-ui-dnd',\n '@dxos/react-ui-editor',\n '@dxos/react-ui-experimental',\n '@dxos/react-ui-form',\n '@dxos/react-ui-gameboard',\n '@dxos/react-ui-geo',\n '@dxos/react-ui-graph',\n '@dxos/react-ui-grid',\n '@dxos/react-ui-list',\n '@dxos/react-ui-markdown',\n '@dxos/react-ui-masonry',\n '@dxos/react-ui-menu',\n '@dxos/react-ui-mosaic',\n '@dxos/react-ui-pickers',\n '@dxos/react-ui-list',\n '@dxos/react-ui-syntax-highlighter',\n '@dxos/react-ui-table',\n '@dxos/react-ui-tabs',\n '@dxos/react-ui-thread',\n '@dxos/solid-ui',\n '@dxos/solid-ui-geo',\n '@dxos/ui',\n '@dxos/ui-editor',\n '@dxos/ui-theme',\n '@dxos/ui-types',\n\n // third-party\n ...THIRD_PARTY_SHARED_PACKAGES,\n];\n\n/**\n * True when the given bare specifier (or one of its subpaths) is provided by the\n * Composer host at runtime and must not be re-bundled by a plugin.\n *\n * Matches only packages listed in {@link DEFAULT_PACKAGES} — the same list\n * {@link importMapPlugin} consumes — so externalization cannot claim a package\n * the host isn't actually mapping. Unknown `@dxos/*` packages fall through to\n * normal bundling, which is the correct default for plugin-owned or yet-to-be\n * shared workspace packages.\n */\nexport const isSharedPackage = (id: string): boolean =>\n DEFAULT_PACKAGES.some((pkg) => id === pkg || id.startsWith(`${pkg}/`));\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { init as initCjsLexer, parse as parseCjs } from 'cjs-module-lexer';\nimport { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';\nimport { createRequire as nodeCreateRequire } from 'node:module';\nimport path from 'node:path';\nimport { type Plugin } from 'vite';\n\nimport { DEFAULT_PACKAGES } from '../packages';\n\nconst require = nodeCreateRequire(import.meta.url);\n\n//\n// Import map helpers.\n// These utilities support `importMapPlugin` by resolving package entrypoints,\n// detecting module formats (ESM vs CJS), and extracting named exports from CJS bundles.\n//\n\n/** Strips vite query strings (e.g. `?v=123`) from resolved module IDs. */\nconst trimQueryString = (id: string) => id.replace(/\\?.*$/, '');\n\n/**\n * Determines whether a resolved file is an ESM module by checking file extension\n * first (.mjs/.cjs), then walking up to the nearest package.json for `\"type\": \"module\"`.\n */\nconst resolvedIdIsEsmModule = (resolvedId: string): boolean => {\n const file = trimQueryString(resolvedId);\n if (file.endsWith('.mjs') || file.endsWith('.mts')) {\n return true;\n }\n if (file.endsWith('.cjs') || file.endsWith('.cts')) {\n return false;\n }\n\n let directory = path.dirname(file);\n while (directory !== path.dirname(directory)) {\n const packageJsonPath = path.join(directory, 'package.json');\n if (existsSync(packageJsonPath)) {\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as { type?: string };\n return pkg.type === 'module';\n } catch {\n return false;\n }\n }\n directory = path.dirname(directory);\n }\n\n return false;\n};\n\n/**\n * Walks up from a resolved file path to find the package.json whose `\"name\"` matches\n * the given package name. Returns the path to that package.json, or undefined.\n */\nconst findPackageJsonPath = (resolvedId: string, packageName: string): string | undefined => {\n let directory = path.dirname(trimQueryString(resolvedId));\n\n while (directory !== path.dirname(directory)) {\n const packageJsonPath = path.join(directory, 'package.json');\n if (existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as { name?: string };\n if (packageJson.name === packageName) {\n return packageJsonPath;\n }\n } catch {}\n }\n\n directory = path.dirname(directory);\n }\n\n return undefined;\n};\n\n/** Resolves a package name to its package.json path using Node's require.resolve. */\nconst resolvePackageJsonPath = (packageName: string): string | undefined => {\n try {\n return findPackageJsonPath(require.resolve(packageName), packageName);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Resolves a package name to its package.json via vite's own resolver, which handles\n * workspace-linked packages whose `exports` field omits `./package.json` (so\n * `require.resolve` can't find it). Falls back to `require.resolve`.\n */\nconst resolvePackageJsonPathViaContext = async (\n ctx: { resolve: (id: string) => Promise<{ id: string } | null> },\n packageName: string,\n): Promise<string | undefined> => {\n try {\n const resolved = await ctx.resolve(packageName);\n if (resolved) {\n const viaResolved = findPackageJsonPath(resolved.id, packageName);\n if (viaResolved) {\n return viaResolved;\n }\n }\n } catch {\n // fall through\n }\n return resolvePackageJsonPath(packageName);\n};\n\n/**\n * Subpath exports that should be excluded from the import map.\n * These are node-only entrypoints (vite plugins, native addons) that shouldn't be pre-bundled for the browser.\n *\n * TODO(wittjosiah): Replace these hand-maintained lists (plus {@link GLOBALLY_EXCLUDED_SUBPATHS}\n * and {@link BUILD_TOOL_SUBPATH}) with a structural check — e.g. honour an `agent`/`node`-only\n * export condition in package.json, or probe each subpath's resolved file for `node:*` imports\n * at build time — so every new server-only entrypoint doesn't require a code change here.\n */\nconst importMapExcludedSubpaths: Readonly<Record<string, ReadonlySet<string>>> = {\n '@dxos/app-framework': new Set(['vite-plugin']),\n // `@dxos/lit-grid/testing` re-exports a playwright page-object manager and pulls\n // `@playwright/test` (and transitive playwright-core) into the browser bundle.\n '@dxos/lit-grid': new Set(['testing']),\n '@dxos/react-ui-mosaic': new Set(['playwright']),\n '@dxos/react-ui-table': new Set(['playwright']),\n '@dxos/ui-theme': new Set(['plugin']),\n // `solid-js/web/storage` is a server-only helper that pulls\n // `node:async_hooks` (AsyncLocalStorage) and has no browser shim. Client\n // code imports `solid-js`, `solid-js/store`, and `solid-js/web` only.\n 'solid-js': new Set(['web/storage']),\n // `effect` publishes `./.index` for bundler internals — maps to `effect/.index`, which Vite\n // often cannot resolve for the import map and is not part of the plugin-facing surface.\n 'effect': new Set(['.index']),\n};\n\n/**\n * Subpaths common to many packages that should always be excluded.\n * `./playwright` subdirectories house e2e test harnesses that pull in\n * `@playwright/test` (a node-only package that breaks the browser bundle).\n * `./testing` subpaths similarly expose node-only test helpers (e.g.\n * `@dxos/edge-client/testing` pulls `@dxos/node-std/http` which has no\n * browser analogue) and aren't part of the plugin-facing surface.\n */\nconst GLOBALLY_EXCLUDED_SUBPATHS = new Set(['playwright', 'testing']);\n\n/**\n * Regex for subpaths that are always node-only build tooling — vite, esbuild, and\n * rollup plugins. These use `node:*` imports and will blow up the browser bundle if\n * they end up in the import map.\n */\nconst BUILD_TOOL_SUBPATH = /^(vite-plugin|esbuild-plugin|rollup-plugin|plugin)$/;\n\n/**\n * Asset subpaths (CSS, PCSS, images, etc.) that the host already loads via its own\n * bundle — for example `@dxos/react-ui-form` pulls in `@dxos/lit-ui/dx-tag-picker.pcss`\n * on startup, so the stylesheet is already attached to the DOM by the time a remote\n * plugin runs. Community plugins should still be able to _import_ those specifiers\n * (rolldown leaves the `import \"…\"` statements in the output when the package is\n * externalized), so the import map maps them to a no-op empty ES module. The\n * resulting browser fetch is a cheap no-op; the styles are never re-downloaded\n * and never re-injected.\n */\nconst ASSET_SUBPATH = /\\.(css|pcss|scss|sass|less|json|node|wasm|html|svg|png|jpe?g|gif|webp|ico)$/;\nconst isAssetSubpath = (specifier: string) => ASSET_SUBPATH.test(specifier);\n\n/**\n * Walks `baseDir` and returns every file that matches the pattern `${baseDir}/<rest>${extension}`.\n * Used to expand wildcard exports like `./proto/*` → `./dist/src/proto/gen/*.js` into their\n * full set of bare specifiers.\n */\nconst walkDirectoryForExtension = (baseDir: string, extension: string): string[] => {\n if (!existsSync(baseDir)) {\n return [];\n }\n const results: string[] = [];\n const walk = (dir: string) => {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = path.join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n walk(full);\n } else if (entry.endsWith(extension)) {\n results.push(path.relative(baseDir, full).slice(0, -extension.length));\n }\n }\n };\n walk(baseDir);\n return results;\n};\n\n/** Resolves an `exports` value to a single target path for pattern expansion. */\nconst pickPatternTarget = (value: unknown): string | undefined => {\n if (typeof value === 'string') {\n return value;\n }\n if (value && typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const preferred = obj.browser ?? obj.import ?? obj.default ?? obj.module;\n return typeof preferred === 'string' ? preferred : undefined;\n }\n return undefined;\n};\n\n/**\n * Expands a wildcard export like `./proto/*` into concrete subpath specifiers by walking\n * the target directory. Returns `<packageName>/<subpath>` strings.\n */\nconst expandWildcardExport = (\n packageName: string,\n packageJsonDir: string,\n exportKey: string,\n exportValue: unknown,\n): string[] => {\n const target = pickPatternTarget(exportValue);\n if (!target || !target.includes('*')) {\n return [];\n }\n // Split on `*` — at most one supported (node's exports pattern semantics).\n const keyStarIndex = exportKey.indexOf('*');\n const targetStarIndex = target.indexOf('*');\n if (keyStarIndex === -1 || targetStarIndex === -1) {\n return [];\n }\n const keyPrefix = exportKey.slice(2, keyStarIndex); // drop leading './'\n const targetPrefix = target.slice(2, targetStarIndex); // drop leading './'\n const targetSuffix = target.slice(targetStarIndex + 1);\n const baseDir = path.resolve(packageJsonDir, targetPrefix);\n const files = walkDirectoryForExtension(baseDir, targetSuffix || '.js');\n return files.map((relativeNoExt) => `${packageName}/${keyPrefix}${relativeNoExt}`);\n};\n\n/**\n * Reads a package's `exports` field and returns all subpath entrypoints as bare specifiers\n * (e.g. `@dxos/client`, `@dxos/client/echo`, `@dxos/lit-ui/dx-tag-picker.pcss`,\n * `@dxos/protocols/proto/dxos/echo/metadata`). Wildcard patterns are expanded by walking\n * the corresponding output directory. Falls back to just the package name if exports is\n * absent or simple.\n */\nconst getPackageEntrypoints = (packageName: string, packageJsonPath: string): string[] => {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {\n exports?: Record<string, unknown> | string | string[];\n };\n const exportsField = packageJson.exports;\n\n if (!exportsField || typeof exportsField === 'string' || Array.isArray(exportsField)) {\n return [packageName];\n }\n\n const exportKeys = Object.keys(exportsField);\n if (!exportKeys.some((key) => key.startsWith('.'))) {\n return [packageName];\n }\n\n const excluded = importMapExcludedSubpaths[packageName];\n const packageJsonDir = path.dirname(packageJsonPath);\n const modules = exportKeys.flatMap((key) => {\n if (key === '.') {\n return [packageName];\n }\n\n if (!key.startsWith('./') || key === './package.json') {\n return [];\n }\n\n // Skip `.d.ts` subpath exports — these are meant to be imported as raw text\n // (e.g. `@dxos/echo-query/api.d.ts?raw` for in-editor type hints), not as\n // ES modules. Enumerating them here would have vite try to bundle the\n // declaration file's imports (protobufjs, effect, etc.), which breaks.\n if (key.endsWith('.d.ts')) {\n return [];\n }\n\n if (key.includes('*')) {\n // Expand wildcard patterns like `./proto/*` into concrete specifiers.\n return expandWildcardExport(packageName, packageJsonDir, key, (exportsField as Record<string, unknown>)[key]);\n }\n\n const subpath = key.slice(2);\n if (excluded?.has(subpath) || GLOBALLY_EXCLUDED_SUBPATHS.has(subpath) || BUILD_TOOL_SUBPATH.test(subpath)) {\n return [];\n }\n\n return [`${packageName}/${subpath}`];\n });\n\n return modules.length > 0 ? modules : [packageName];\n};\n\n/**\n * Statically analyzes a CJS file to extract named exports using cjs-module-lexer.\n * Follows re-exports (e.g. react's index.js re-exports from cjs/react.development.js)\n * and deduplicates. Filters out `default` and `__esModule` pseudo-exports.\n */\nconst getCjsNamedExports = (filePath: string, seen = new Set<string>()): string[] => {\n const normalized = trimQueryString(filePath);\n if (seen.has(normalized)) {\n return [];\n }\n seen.add(normalized);\n\n try {\n const source = readFileSync(normalized, 'utf8');\n const { exports: directExports, reexports } = parseCjs(source);\n\n const reexportedNames = reexports.flatMap((reexport) => {\n const resolved = path.resolve(path.dirname(normalized), reexport);\n const candidates = [resolved, `${resolved}.js`, `${resolved}.cjs`];\n const found = candidates.find((candidate) => existsSync(candidate));\n return found ? getCjsNamedExports(found, seen) : [];\n });\n\n return [...new Set([...directExports, ...reexportedNames])].filter(\n (name) => name !== 'default' && name !== '__esModule',\n );\n } catch {\n return [];\n }\n};\n\n/**\n * Vite plugin for the **host app** (Composer). Generates a browser import map so that\n * shared packages are loaded once and reused by both the host and any remote plugins.\n *\n * In production, emits a dedicated chunk per specifier via virtual wrapper modules,\n * then injects a `<script type=\"importmap\">` tag into the HTML with the chunk URLs.\n *\n * Virtual wrappers are needed because directly emitting chunks for CJS packages loses\n * their named exports due to Rollup's interop. The wrapper re-exports them explicitly.\n *\n * TODO: Restore dev-mode support. The previous dev path mapped each bare specifier to\n * its absolute `/@fs/` file path during `buildStart`, which forced `this.resolve()` for\n * hundreds of subpath entrypoints and raced with Vite's optimize-deps static scan —\n * producing non-deterministic chunk content (~34 chunks drifting per warm-start) and\n * triggering Vite 8.0.10's `runOptimizer` / `commitProcessing` crashes (`fileHash` /\n * `browserHash` undefined on partial-discovery batches). Plugin is currently gated to\n * `apply: 'build'` to avoid both. A working dev-mode implementation would need to\n * resolve specifiers without participating in the optimize-deps phase — candidates:\n * - defer resolution to `transformIndexHtml` (after the optimizer settles)\n * - read resolved paths from `environment.depsOptimizer.metadata` rather than calling\n * `this.resolve()` ourselves\n * - resolve via `require.resolve` directly, bypassing the Vite plugin pipeline entirely\n */\nexport const importMapPlugin = (options?: { packages?: string[] }): Plugin[] => {\n const packages = options?.packages ?? DEFAULT_PACKAGES;\n const WRAPPER_PREFIX = '\\0import-map:';\n const chunkRefIds: Record<string, string> = {};\n const resolvedIds: Record<string, string> = {};\n let imports: Record<string, string> = {};\n let modules: string[] = [];\n let importMapIsDev = false;\n let base = '/';\n let root = process.cwd();\n\n return [\n // Phase 1: Resolve all package entrypoints and emit chunks.\n //\n // Build-only. The dev-mode path (recording absolute `/@fs/` paths in\n // `imports[]`) is non-functional today and was actively harmful: calling\n // `this.resolve()` for every shared package's subpath entrypoints during\n // `buildStart` races with Vite's optimize-deps static scan, producing\n // non-deterministic chunk content (~34 drifting chunks per warm-start) and\n // triggering Vite 8.0.10's `runOptimizer` / `commitProcessing` crashes\n // (`fileHash` / `browserHash` undefined on partial-discovery batches) when\n // the resolved set doesn't match the optimizer's metadata. The importmap\n // is only meaningful for production builds where remote plugins consume\n // the emitted wrapper chunks.\n {\n name: 'import-map:get-chunk-ref-ids',\n apply: 'build',\n configResolved(config) {\n base = config.base ?? '/';\n root = config.root;\n },\n async buildStart() {\n importMapIsDev = this.environment.mode === 'dev';\n await initCjsLexer();\n\n // Expand each package name into its full set of subpath entrypoints\n // (e.g. '@dxos/client' -> ['@dxos/client', '@dxos/client/echo', ...]).\n modules = [\n ...new Set(\n (\n await Promise.all(\n packages.map(async (packageName) => {\n const packageJsonPath = await resolvePackageJsonPathViaContext(this, packageName);\n if (!packageJsonPath) {\n this.warn(`Unable to locate package.json for import map package: ${packageName}`);\n return [packageName];\n }\n\n return getPackageEntrypoints(packageName, packageJsonPath);\n }),\n )\n ).flat(),\n ),\n ];\n\n for (const specifier of modules) {\n if (isAssetSubpath(specifier)) {\n // Host already loaded the real asset; remote plugins need the specifier to\n // resolve to *something* that behaves as an ES module. A data URL is the\n // cheapest option — no chunk to emit (rolldown tree-shakes an empty wrapper\n // even with `preserveSignature: 'strict'`, so the referenced file wouldn't\n // exist at runtime), no extra network request, and the same path in dev and prod.\n imports[specifier] = 'data:text/javascript;charset=utf-8,export%20%7B%7D%3B';\n continue;\n }\n\n // Resolve with a host-rooted importer (not a bare importer-less resolve). The host's\n // `importSource` plugin — which routes `@dxos/*` to the `source` (TypeScript) export\n // instead of the published `dist/` — bails out when `importer` is undefined, so an\n // importer-less `this.resolve(specifier)` falls through to the `default`/dist export.\n // That made wrapper chunks evaluate `dist/` while the host app evaluated `src/`,\n // duplicating module-local identity (the private `ProxyHandlerSlot` class, `Ref`\n // brand symbols, React contexts) and breaking `instanceof` across the host↔plugin\n // boundary. Passing a host-rooted importer makes `importSource` resolve these\n // wrappers to the exact same source module the host app uses.\n const resolved = await this.resolve(specifier, path.join(root, 'index.html'));\n if (!resolved) {\n this.warn(`Import map: unable to resolve \"${specifier}\"; omitting from import map.`);\n continue;\n }\n\n if (importMapIsDev) {\n // Dev: map bare specifier to the resolved file path, prefixed with vite's\n // `/@fs/` escape hatch so absolute node_modules paths (including\n // `.vite/deps/*` pre-bundled chunks) round-trip through the dev server\n // instead of being resolved against the document origin as a 404.\n const filePath = trimQueryString(resolved.id);\n imports[specifier] = filePath.startsWith('/') ? `/@fs${filePath}` : filePath;\n } else {\n // Prod: emit a virtual wrapper chunk that re-exports from the real module.\n resolvedIds[specifier] = resolved.id;\n chunkRefIds[specifier] = this.emitFile({\n type: 'chunk',\n id: `${WRAPPER_PREFIX}${specifier}`,\n preserveSignature: 'strict',\n });\n }\n }\n },\n\n // Intercept virtual wrapper IDs so Rollup doesn't try to resolve them as files.\n resolveId(id) {\n if (id.startsWith(WRAPPER_PREFIX)) {\n return id;\n }\n },\n\n // Generate the source for each virtual wrapper module.\n // For CJS packages, explicitly re-export named exports (discovered via static analysis)\n // because Rollup's `export *` interop doesn't preserve them for CJS.\n //\n // Each wrapper also emits a local `__keepalive` export. Without this, Rolldown\n // (Vite 8) tree-shakes wrappers whose `export *` re-exports happen to coincide\n // with another already-emitted chunk's exports — typical for umbrella packages\n // (e.g. `@dxos/compute` re-exports from `@dxos/operation`, so the operation\n // wrapper looks \"redundant\" to Rolldown and gets merged away). A local const\n // export has no upstream source for Rolldown to dedupe against, so the chunk\n // is always preserved and the import-map entry resolves at runtime.\n load(id) {\n if (!id.startsWith(WRAPPER_PREFIX)) {\n return;\n }\n const specifier = id.slice(WRAPPER_PREFIX.length);\n const keepalive = `export const __dxosImportMapKeepalive = ${JSON.stringify(specifier)};`;\n const resolvedId = resolvedIds[specifier];\n if (!resolvedId) {\n return `export * from ${JSON.stringify(specifier)};\\n${keepalive}\\n`;\n }\n\n // Re-export from the resolved absolute path, not the bare specifier. A bare re-export\n // would let Rolldown resolve `@dxos/echo` a second way (the host app reaches it via the\n // `source` export, this virtual module via the published `dist/`), evaluating the same\n // source twice and duplicating module-local identity — the private `ProxyHandlerSlot`\n // class, `Ref` brand symbols, React contexts — which breaks `instanceof` and context\n // lookups across the host↔remote-plugin boundary. The resolved id (see the importer\n // passed to `this.resolve` above) already points at the host's module.\n const filePath = trimQueryString(resolvedId);\n const isCjs = filePath.endsWith('.cjs') || (!filePath.endsWith('.mjs') && !resolvedIdIsEsmModule(filePath));\n if (isCjs) {\n const named = getCjsNamedExports(filePath);\n if (named.length > 0) {\n return `export { default, ${named.join(', ')} } from ${JSON.stringify(filePath)};\\n${keepalive}\\n`;\n }\n }\n return `export * from ${JSON.stringify(filePath)};\\n${keepalive}\\n`;\n },\n\n // After bundling, map each specifier to the URL of its emitted chunk. Preserves\n // asset-subpath entries already written to `imports` during `buildStart` (those\n // use an inline data URL rather than an emitted chunk).\n generateBundle() {\n if (importMapIsDev) {\n return;\n }\n\n imports = {\n ...imports,\n ...Object.fromEntries(\n modules\n .filter((specifier) => chunkRefIds[specifier] !== undefined)\n .map((specifier) => [specifier, `${base}${this.getFileName(chunkRefIds[specifier])}`]),\n ),\n };\n },\n },\n\n // Phase 2: Inject the import map into the HTML as a <script type=\"importmap\"> tag.\n {\n name: 'import-map:transform-index-html',\n apply: 'build',\n enforce: 'post',\n transformIndexHtml(html: string) {\n const tags = [\n {\n tag: 'script',\n attrs: {\n type: 'importmap',\n },\n children: JSON.stringify({ imports }, null, 2),\n },\n ];\n\n return {\n html,\n tags,\n };\n },\n },\n ];\n};\n"],
|
|
5
|
+
"mappings": "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O,IAAME,oBAAoB,CAC/BJ,MACA,EAAEK,QAAQC,SAAQ,MAAoD;AAEtE,SAAOC,KAAKC,UACV;IACE,GAAGR;IACHK;IACA,GAAIC,aAAaG,SAAY;MAAEH;IAAS,IAAI,CAAC;EAC/C,GACA,MACA,CAAA;AAEJ;;;AC3CA,IAAMI,8BAA8B;EAClC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGK,IAAMC,mBAAmB;;EAE9B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAGGD;;AAaE,IAAME,kBAAkB,CAACC,OAC9BF,iBAAiBG,KAAK,CAACC,QAAQF,OAAOE,OAAOF,GAAGG,WAAW,GAAGD,GAAAA,GAAM,CAAA;;;ANxKtE,IAAME,kBAAkB;AAGxB,IAAMC,qBAAqB,CAACC,QAAAA;AAC1B,MAAI;AACF,WAAOC,KAAKC,MAAMC,aAAaC,MAAKJ,KAAK,cAAA,GAAiB,OAAA,CAAA,EAAUK,WAAW;EACjF,QAAQ;AACN,WAAO;EACT;AACF;AASA,IAAMC,2BAA2B,CAACN,QAAAA;AAChC,MAAI;AACF,UAAMO,WAAWN,KAAKC,MAAMC,aAAaC,MAAKJ,KAAK,cAAA,GAAiB,OAAA,CAAA,EAAUQ;AAG9E,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",
|
|
6
|
+
"names": ["babel", "babelPresetTypeScript", "babelPresetSolid", "build", "basename", "dirname", "fileURLToPath", "VIRTUAL_NS", "MODULES", "entry", "contents", "entrySrc", "tsx", "mount", "mountSrc", "Loader", "loaderSrc", "bridge", "bridgeSrc", "store", "storeSrc", "types", "typesSrc", "resolveDir", "dirname", "fileURLToPath", "url", "compileLoaderBundle", "virtualSolid", "name", "setup", "esbuild", "onResolve", "filter", "args", "path", "replace", "namespace", "undefined", "onLoad", "module", "result", "transformAsync", "filename", "babelrc", "configFile", "presets", "babelPresetSolid", "generate", "hydratable", "babelPresetTypeScript", "allowDeclareFields", "code", "Error", "loader", "build", "stdin", "sourcefile", "bundle", "format", "platform", "target", "minify", "write", "legalComments", "define", "plugins", "outputFiles", "text", "bundlePromise", "getLoaderBundle", "bootLoaderPlugin", "status", "markSvg", "include", "transformIndexHtml", "_html", "ctx", "basename", "includes", "rootId", "tag", "injectTo", "children", "css", "attrs", "JSON", "stringify", "readFileSync", "join", "Context", "Effect", "Layer", "Service", "Tag", "ModuleTag", "Symbol", "for", "getModuleTag", "capability", "ModuleTag", "String", "undefined", "Service", "Context", "Effect", "Option", "Pipeable", "Schema", "BaseError", "invariant", "DXN", "PluginProfileSchema", "PluginReleaseSchema", "Service", "PluginModuleImpl", "id", "activatesOn", "firesBeforeActivation", "firesAfterActivation", "activate", "author", "Schema", "Release", "PluginReleaseSchema", "profile", "Profile", "release", "optional", "DXN", "makeMeta", "key", "make", "rest", "_meta", "_modules", "meta", "modules", "addModule", "moduleOptions", "pipe", "undefined", "pluginName", "fromNullable", "Option", "onNone", "exportName", "Capability", "getModuleTag", "invariant", "onSome", "computeModuleId", "builder", "module", "resolveModule", "options", "PluginImpl", "Object", "assign", "factory", "stub", "defineProperty", "value", "loader", "enumerable", "plugin", "mod", "Effect", "tryPromise", "try", "catch", "error", "LazyPluginError", "reason", "cause", "context", "result", "fail", "returnedId", "FetchHttpClient", "HttpClient", "HttpClientRequest", "HttpClientResponse", "Effect", "Schema", "BaseError", "PLUGIN_ENTRY_FILENAME", "PluginManifestSchema", "PLUGIN_DEV_SERVER_PORT", "PluginManifestError", "extend", "Manifest", "Struct", "omit", "fields", "assets", "Array", "String", "devEntry", "optional", "Schema", "build", "randomUUID", "existsSync", "rm", "writeFile", "join", "pathToFileURL", "Config2", "CONFIG_BASENAMES", "decodeConfig2", "decodeUnknownSync", "Config", "findDxConfigFile", "dir", "map", "basename", "find", "candidate", "loadDxConfig", "filePath", "result", "entryPoints", "bundle", "format", "platform", "write", "packages", "logLevel", "tempPath", "outputFiles", "text", "module", "href", "default", "force", "PLUGIN_ENTRY_FILENAME", "MANIFEST_ASSET_NAME", "ENTRY_FILENAME", "toBuildMeta", "meta", "version", "dependencies", "profile", "serializeManifest", "assets", "devEntry", "JSON", "stringify", "undefined", "THIRD_PARTY_SHARED_PACKAGES", "DEFAULT_PACKAGES", "isSharedPackage", "id", "some", "pkg", "startsWith", "JSX_DEV_RUNTIME", "readPackageVersion", "dir", "JSON", "parse", "readFileSync", "join", "version", "readResolvedDependencies", "declared", "dependencies", "undefined", "resolved", "name", "Object", "keys", "length", "isExternal", "id", "isSharedPackage", "REQUIRE_SHIM_BANNER", "composerPlugin", "options", "entry", "port", "PLUGIN_DEV_SERVER_PORT", "projectRoot", "process", "cwd", "metaPromise", "meta", "Promise", "resolve", "config", "findDxConfigFile", "then", "configFile", "loadDxConfig", "toBuildMeta", "Plugin", "getMetaFromConfig", "Set", "base", "plugins", "server", "cors", "preview", "build", "sourcemap", "target", "lib", "formats", "fileName", "ENTRY_FILENAME", "rolldownOptions", "external", "output", "chunkFileNames", "assetFileNames", "banner", "enforce", "apply", "optimizeDeps", "exclude", "DEFAULT_PACKAGES", "resolveId", "add", "load", "has", "code", "configResolved", "push", "transform", "size", "escaped", "map", "s", "replace", "pattern", "RegExp", "test", "_", "dep", "endsWith", "shim", "generateBundle", "_options", "bundle", "assets", "filter", "MANIFEST_ASSET_NAME", "sort", "emitFile", "type", "source", "serializeManifest", "configureServer", "body", "devEntry", "middlewares", "use", "req", "res", "next", "url", "setHeader", "statusCode", "end", "init", "initCjsLexer", "parse", "parseCjs", "existsSync", "readdirSync", "readFileSync", "statSync", "createRequire", "nodeCreateRequire", "path", "require", "nodeCreateRequire", "url", "trimQueryString", "id", "replace", "resolvedIdIsEsmModule", "resolvedId", "file", "endsWith", "directory", "path", "dirname", "packageJsonPath", "join", "existsSync", "pkg", "JSON", "parse", "readFileSync", "type", "findPackageJsonPath", "packageName", "packageJson", "name", "undefined", "resolvePackageJsonPath", "resolve", "resolvePackageJsonPathViaContext", "ctx", "resolved", "viaResolved", "importMapExcludedSubpaths", "Set", "GLOBALLY_EXCLUDED_SUBPATHS", "BUILD_TOOL_SUBPATH", "ASSET_SUBPATH", "isAssetSubpath", "specifier", "test", "walkDirectoryForExtension", "baseDir", "extension", "results", "walk", "dir", "entries", "readdirSync", "entry", "full", "stat", "statSync", "isDirectory", "push", "relative", "slice", "length", "pickPatternTarget", "value", "obj", "preferred", "browser", "import", "default", "module", "expandWildcardExport", "packageJsonDir", "exportKey", "exportValue", "target", "includes", "keyStarIndex", "indexOf", "targetStarIndex", "keyPrefix", "targetPrefix", "targetSuffix", "files", "map", "relativeNoExt", "getPackageEntrypoints", "exportsField", "exports", "Array", "isArray", "exportKeys", "Object", "keys", "some", "key", "startsWith", "excluded", "modules", "flatMap", "subpath", "has", "getCjsNamedExports", "filePath", "seen", "normalized", "add", "source", "directExports", "reexports", "parseCjs", "reexportedNames", "reexport", "candidates", "found", "find", "candidate", "filter", "importMapPlugin", "options", "packages", "DEFAULT_PACKAGES", "WRAPPER_PREFIX", "chunkRefIds", "resolvedIds", "imports", "importMapIsDev", "base", "root", "process", "cwd", "apply", "configResolved", "config", "buildStart", "environment", "mode", "initCjsLexer", "Promise", "all", "warn", "flat", "emitFile", "preserveSignature", "resolveId", "load", "keepalive", "stringify", "isCjs", "named", "generateBundle", "fromEntries", "getFileName", "enforce", "transformIndexHtml", "html", "tags", "tag", "attrs", "children"]
|
|
7
7
|
}
|