@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 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/core/edge-registry-plugin-provider.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Context } from '@dxos/context';\nimport { type EdgeHttpClient } from '@dxos/edge-client';\nimport { type PluginEntry } from '@dxos/protocols';\n\nimport * as Registry from './registry';\n\n/**\n * Maps a wire-format `PluginEntry` (from `@dxos/protocols`) to a\n * `Registry.Plugin` (the app-framework domain type).\n *\n * This is the only translation seam between the two independently-defined type\n * hierarchies — fields are mapped explicitly, with no shared type between them.\n */\nconst toRegistryPlugin = (entry: PluginEntry): Registry.Plugin => ({\n id: entry.meta.id,\n name: entry.meta.name,\n description: entry.meta.description,\n homePage: entry.meta.homePage,\n source: entry.meta.source,\n screenshots: entry.meta.screenshots ? [...entry.meta.screenshots] : undefined,\n tags: entry.meta.tags ? [...entry.meta.tags] : undefined,\n icon: entry.meta.icon,\n iconHue: entry.meta.iconHue,\n moduleUrl: entry.moduleUrl,\n repo: entry.repo,\n version: entry.releaseTag,\n});\n\n/**\n * Implements `Registry.PluginProvider` against the Edge `/registry` HTTP endpoints.\n *\n * Lives in app-framework (rather than the more obvious home of `@dxos/edge-client`)\n * because edge-client doesn't depend on app-framework; siting the implementation\n * here keeps the dependency arrow `app-framework → edge-client` and avoids a\n * cycle. The class needs only the public `EdgeHttpClient` type, so a one-way\n * type-import is enough.\n *\n * `listVersions` is currently a stub: it returns the single latest version derived\n * from the cached plugin list, so the host's version picker has something to render.\n * The wire contract for the real endpoint already exists — see\n * `GetPluginVersionsResponseBodySchema` in `@dxos/protocols/edge/registry` and\n * {@link EdgeHttpClient.getRegistryPluginVersions} — so once Edge ships\n * `GET /registry/plugins/:repo/versions`, swap this stub for a call to\n * `this._client.getRegistryPluginVersions(...)` and map each entry through a\n * `toRegistryPluginVersion` helper (mirror of {@link toRegistryPlugin}).\n */\nexport class EdgeRegistryPluginProvider implements Registry.PluginProvider {\n // Cached on first load so getPlugin/listVersions can resolve without re-fetching.\n #cachedPlugins: readonly Registry.Plugin[] = [];\n\n constructor(private readonly _client: EdgeHttpClient) {}\n\n listPlugins(): Effect.Effect<readonly Registry.Plugin[], Error> {\n return Effect.tryPromise({\n try: () => this._client.getRegistryPlugins(Context.default()),\n catch: (error) => (error instanceof Error ? error : new Error(String(error))),\n }).pipe(\n Effect.map((body) => {\n const plugins = body.plugins.filter((entry) => entry.health === 'ok').map(toRegistryPlugin);\n this.#cachedPlugins = plugins;\n return plugins;\n }),\n );\n }\n\n listVersions(repo: string): Effect.Effect<readonly Registry.PluginVersion[], Error> {\n // Stub: return only the currently-known version until Edge implements the versions endpoint.\n const plugin = this.#cachedPlugins.find((candidate) => candidate.repo === repo);\n if (!plugin) {\n return Effect.fail(new Error(`Plugin not found in catalog: ${repo}`));\n }\n const version: Registry.PluginVersion = { tag: plugin.version, moduleUrl: plugin.moduleUrl };\n return Effect.succeed([version]);\n }\n\n getPlugin(repo: string, version?: string): Effect.Effect<Registry.Plugin, Error> {\n const plugin = this.#cachedPlugins.find((p) => p.repo === repo);\n if (!plugin) {\n return Effect.fail(new Error(`Plugin not found in catalog: ${repo}`));\n }\n if (version && version !== plugin.version) {\n return Effect.fail(new Error(`Version ${version} not available for ${repo}; only ${plugin.version} is cached`));\n }\n return Effect.succeed(plugin);\n }\n}\n"],
|
|
5
|
-
"mappings": ";AAIA,YAAYA,YAAY;AAExB,SAASC,eAAe;AAMxB,IAAA,eAAA;IASEC,mBAAqB,CAAA,WAAA;EACrBC,IAAAA,MAAAA,KAAaC;EACbC,MAAAA,MAAUD,KAAME;EAChBC,aAAQH,MAAWG,KAAAA;EACnBC,UAAAA,MAAaJ,KAAME;UAAuBF,MAAME,KAAKE;eAAeC,MAAAA,KAAAA,cAAAA;IACpEC,GAAMN,MAAME,KAAKI;;QAA8BD,MAAAA,KAAAA,OAAAA;IAC/CE,GAAMP,MAAME,KAAKK;EACjBC,IAAAA;EACAC,MAAAA,MAAWT,KAAMS;EACjBC,SAAMV,MAAMU,KAAI;EAChBC,WAASX,MAAMY;EACjB,MAAA,MAAA;EAEA,SAAA,MAAA;;AAmBE,IAAA,6BAAA,MAAA;EACA;;mBAE6BC,CAAAA;EAA0B,YAAA,SAAA;AAEvDC,SAAAA,UAAgE;;gBAEvD;WACGC,kBAAWA;MAClBC,KACDpB,MAAAA,KAAU,QAAEqB,mBAAAA,QAAAA,QAAAA,QAAAA,EAAAA,YAAAA,YAAAA,GAAAA,cAAAA,GAAAA,GAAAA,CAAAA,CAAAA;MACV,OAAMC,CAAAA,UAAUD,iBAAaE,QAAQnB,QAAUA,IAAMoB,MAAM,OAAK,KAAS,CAACC;YACrE,WAAA,CAAA,SAAiBH;AACtB,YAAA,UAAOA,KAAAA,QAAAA,OAAAA,CAAAA,UAAAA,MAAAA,WAAAA,IAAAA,EAAAA,IAAAA,gBAAAA;AACT,WAAA,iBAAA;AAEJ,aAAA;IAEAI,CAAAA,CAAAA;;eAEQC,MAAS;UAEb,SAAO3B,KAAO4B,eAAgB,KAAA,CAAA,cAAA,UAA6B,SAAQ,IAAA;AACrE,QAAA,CAAA,QAAA;AACA,aAAwC,YAAA,IAAA,MAAA,gCAAA,IAAA,EAAA,CAAA;;UAAuBf,UAAWc;MAAiB,KAAA,OAAA;MAC3F,WAAcE,OAAQ;;WAAS,eAAA;MACjC;IAEAC,CAAAA;;YAEOH,MAAAA,SAAQ;UACX,SAAO3B,KAAO4B,eAAgB,KAAA,CAAA,MAAA,EAAA,SAAA,IAAA;AAChC,QAAA,CAAA,QAAA;AACIb,aAAWA,YAAAA,IAAYY,MAAAA,gCAAgB,IAAA,EAAA,CAAA;;AAE3C,QAAA,WAAA,YAAA,OAAA,SAAA;AACA,aAAcE,YAAQF,IAAAA,MAAAA,WAAAA,OAAAA,sBAAAA,IAAAA,UAAAA,OAAAA,OAAAA,YAAAA,CAAAA;IACxB;AACF,WAAA,eAAA,MAAA;;;",
|
|
6
|
-
"names": ["Effect", "Context", "name", "description", "entry", "homePage", "meta", "source", "screenshots", "undefined", "tags", "icon", "iconHue", "moduleUrl", "repo", "version", "releaseTag", "_client", "listPlugins", "error", "pipe", "body", "plugins", "filter", "health", "toRegistryPlugin", "listVersions", "plugin", "fail", "succeed", "getPlugin"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/helpers.ts", "../../../src/ui/hooks/useSurface.ts", "../../../src/ui/components/PluginManager/PluginManagerProvider.ts", "../../../src/ui/components/Surface/context.ts", "../../../src/ui/components/Surface/SurfaceComponent.tsx", "../../../src/ui/components/Surface/SurfaceInfo.tsx", "../../../src/ui/components/Surface/SurfaceProfilerContext.tsx", "../../../src/ui/components/Surface/types.ts", "../../../src/ui/components/Surface/index.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\ntype DependencyNode = {\n id: string;\n dependsOn?: string[];\n};\n\n/**\n * Topologically sorts a list of nodes based on their dependencies.\n */\n// TODO(wittjosiah): Factor out?\nexport const topologicalSort = <T extends DependencyNode>(nodes: T[]): T[] => {\n const getDependencies = (nodeId: string, seen = new Set<string>(), path = new Set<string>()): string[] => {\n if (path.has(nodeId)) {\n throw new Error(`Circular dependency detected involving ${nodeId}`);\n }\n if (seen.has(nodeId)) {\n return [];\n }\n\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) {\n throw new Error(`Node ${nodeId} not found but is listed as a dependency`);\n }\n\n const newPath = new Set([...path, nodeId]);\n const newSeen = new Set([...seen, nodeId]);\n\n const dependsOn = node.dependsOn ?? [];\n return [...dependsOn.flatMap((depId) => getDependencies(depId, newSeen, newPath)), nodeId];\n };\n\n // Get all unique dependencies.\n const allDependencies = nodes\n .map((node) => node.id)\n .flatMap((id) => getDependencies(id))\n .filter((id, index, self) => self.indexOf(id) === index);\n\n // Map back to original nodes\n return allDependencies\n .map((id) => nodes.find((node) => node.id === id))\n .filter((node): node is T => node !== undefined);\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useContext } from 'react';\n\nimport { raise } from '@dxos/debug';\n\nimport { Surface } from '../components';\n\nexport const useSurface = (): Surface.Context => {\n return useContext(Surface.Context) ?? raise(new Error('Missing SurfaceContext'));\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { createContext, useContext } from 'react';\n\nimport { raise } from '@dxos/debug';\n\nimport { type PluginManager } from '../../../core';\n\nconst PluginManagerContext = createContext<PluginManager.PluginManager | undefined>(undefined);\n\n/**\n * Get the plugin manager.\n */\nexport const usePluginManager = (): PluginManager.PluginManager =>\n useContext(PluginManagerContext) ?? raise(new Error('Missing PluginManagerContext'));\n\n/**\n * Context provider for a plugin manager.\n */\nexport const PluginManagerProvider = PluginManagerContext.Provider;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Context, createContext } from 'react';\n\nimport { type Props } from './types';\n\nexport type SurfaceContext = Pick<Props, 'id' | 'role' | 'data'>;\n\n// TODO(burdon): Use @radix-ui/react-context\nexport const SurfaceContext: Context<SurfaceContext | undefined> = createContext<SurfaceContext | undefined>(undefined);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useAtomValue } from '@effect-atom/atom-react';\nimport React, {\n Fragment,\n type NamedExoticComponent,\n Profiler,\n type RefAttributes,\n Suspense,\n forwardRef,\n memo,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { log } from '@dxos/log';\nimport { ErrorBoundary } from '@dxos/react-error-boundary';\nimport { useDefaultValue } from '@dxos/react-hooks';\nimport { byPosition } from '@dxos/util';\n\nimport { Capabilities } from '../../../common';\nimport { type CapabilityManager } from '../../../core';\nimport { usePluginManager } from '../PluginManager/PluginManagerProvider';\nimport { SurfaceContext } from './context';\nimport { SurfaceInfo } from './SurfaceInfo';\nimport { useSurfaceProfilerCallback } from './SurfaceProfilerContext';\nimport {\n type Definition,\n type Props,\n type RoleToken,\n type TokenData,\n type TypedProps,\n type WebComponentDefinition,\n} from './types';\n\nconst DEBUG = import.meta.env.VITE_DEBUG;\n\nconst DEFAULT_PLACEHOLDER = <Fragment />;\n\n/**\n * Wrapper component for rendering Web Component surfaces.\n * Handles creation, prop setting, and cleanup of Web Components.\n */\nconst WebComponentWrapper = memo(\n forwardRef<HTMLElement, Omit<Props, 'role'> & { role: string; definition: WebComponentDefinition }>(\n ({ id, role, data, limit, definition, ...rest }, forwardedRef) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const elementRef = useRef<HTMLElement | null>(null);\n const propsRef = useRef({ id, role, data, limit, ...rest });\n\n // Update props ref on every render\n propsRef.current = { id, role, data, limit, ...rest };\n\n // Create element only once\n useEffect(() => {\n if (!containerRef.current || elementRef.current) {\n return;\n }\n\n // Create the Web Component\n const element = document.createElement(definition.tagName);\n elementRef.current = element;\n\n // Set initial properties on the Web Component\n Object.assign(element, propsRef.current);\n\n // Append to container\n containerRef.current.appendChild(element);\n\n // Setup ref forwarding if provided\n if (typeof forwardedRef === 'function') {\n forwardedRef(element);\n } else if (forwardedRef) {\n forwardedRef.current = element;\n }\n\n // Cleanup on unmount to prevent memory leaks\n return () => {\n if (elementRef.current && containerRef.current?.contains(elementRef.current)) {\n containerRef.current.removeChild(elementRef.current);\n }\n if (typeof forwardedRef === 'function') {\n forwardedRef(null);\n } else if (forwardedRef) {\n forwardedRef.current = null;\n }\n elementRef.current = null;\n };\n }, [definition.tagName, forwardedRef]);\n\n // Update props on existing element without recreating it\n // This runs on every render to ensure all props (including those in `rest`) are kept up to date\n useEffect(() => {\n const element = elementRef.current;\n if (!element) {\n return;\n }\n\n // Update properties on the existing Web Component\n Object.assign(element, propsRef.current);\n });\n\n return <div ref={containerRef} />;\n },\n ),\n);\n\nWebComponentWrapper.displayName = 'WebComponentWrapper';\n\n/**\n * Wrapper component that provides context for a surface.\n */\n// TODO(burdon): Allow DebugPlugin to provide different fallback using react-ui ErrorFallback.\nconst SurfaceContextProvider = memo(\n forwardRef<HTMLElement, Omit<Props, 'role'> & { role: string; definition: Definition }>(\n ({ id, role, data, limit, fallback = ErrorFallback, definition, ...rest }, forwardedRef) => {\n const contextValue = useMemo(() => ({ id, role, data }), [id, role, data]);\n const onProfilerRender = useSurfaceProfilerCallback();\n const profilerId = `surface/${id}/${role}`;\n\n // Handle Web Component surfaces\n if (definition.kind === 'web-component') {\n return (\n <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>\n <SurfaceContext.Provider value={contextValue}>\n <WebComponentWrapper\n id={id}\n role={role}\n data={data}\n limit={limit}\n definition={definition}\n ref={forwardedRef}\n {...rest}\n />\n </SurfaceContext.Provider>\n </ErrorBoundary>\n );\n }\n\n // Handle React component surfaces\n const Component = definition.component;\n\n // TODO(burdon): Remove from production build?\n const debug = DEBUG || '__DX_DEBUG__' in window;\n if (debug) {\n return (\n <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>\n <div className='contents' data-id={id} data-role={role}>\n <SurfaceContext.Provider value={contextValue}>\n <SurfaceInfo ref={forwardedRef}>\n {onProfilerRender && !profilerId.includes('org.dxos.plugin.debug') ? (\n <Profiler id={profilerId} onRender={onProfilerRender}>\n <Component id={id} role={role} data={data} limit={limit} {...rest} />\n </Profiler>\n ) : (\n <Component id={id} role={role} data={data} limit={limit} {...rest} />\n )}\n </SurfaceInfo>\n </SurfaceContext.Provider>\n </div>\n </ErrorBoundary>\n );\n }\n\n return (\n <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>\n <div className='contents' data-id={id} data-role={role}>\n <SurfaceContext.Provider value={contextValue}>\n <Component id={id} role={role} data={data} limit={limit} {...rest} ref={forwardedRef} />\n </SurfaceContext.Provider>\n </div>\n </ErrorBoundary>\n );\n },\n ),\n);\n\nSurfaceContextProvider.displayName = 'SurfaceContextProvider';\n\n/**\n * A surface is a named region of the screen that can be populated by plugins.\n */\n// TODO(burdon): Remove `ref` since relying on this would be error prone.\nexport const SurfaceComponent = memo(\n forwardRef<HTMLElement, Props & { type?: RoleToken<any> }>(\n ({ id: _id, role, type, data: dataProp, limit, placeholder = DEFAULT_PLACEHOLDER, ...rest }, forwardedRef) => {\n const data = useDefaultValue(dataProp, () => ({}));\n // TODO(wittjosiah): This will make all surfaces depend on a single signal.\n // This isn't ideal because it means that any change to the data will cause all surfaces to re-render.\n // This effectively means that plugin modules which contribute surfaces need to all be activated at startup.\n // This should be fine for now because it's how it worked prior to capabilities api anyway.\n // In the future, it would be nice to be able to bucket the surface contributions by role.\n const surfaces = useSurfaces();\n\n const effectiveRole = role ?? type?.role;\n if (effectiveRole == null) {\n if (DEBUG) {\n log.warn('Surface has neither `role` nor `type` prop', { id: _id });\n }\n return null;\n }\n\n // NOTE: Memoizing the candidates makes the surface not re-render based on reactivity within data.\n const definitions = findCandidates(surfaces, { role: effectiveRole, data });\n const candidates = limit ? definitions.slice(0, limit) : definitions;\n if (DEBUG && candidates.length === 0) {\n log.warn('no candidates for surface', { role: effectiveRole, data });\n return null;\n }\n\n return (\n <Suspense fallback={placeholder}>\n {candidates.map((definition) => (\n <SurfaceContextProvider\n key={definition.id}\n id={definition.id}\n role={effectiveRole}\n data={data}\n limit={limit}\n definition={definition}\n ref={forwardedRef}\n {...rest}\n />\n ))}\n </Suspense>\n );\n },\n ),\n) as (<TToken extends RoleToken<any>>(props: TypedProps<TToken> & RefAttributes<HTMLElement>) => React.ReactNode) &\n NamedExoticComponent<Props & RefAttributes<HTMLElement>>;\n\nSurfaceComponent.displayName = 'Surface';\n\n// TODO(burdon): Make user facing, with telemetry.\nconst ErrorFallback = ({ error }: Props) => {\n const { message } = error instanceof Error ? error : { message: String(error) };\n return (\n <div role='alert' data-testid='error-boundary-fallback'>\n <h1 className='flex gap-2 text-sm mt-2 text-info-text'>{message}</h1>\n </div>\n );\n};\n\nconst findCandidates = (surfaces: Definition[], { role, data }: { role: string; data: Props['data'] }) => {\n return Object.values(surfaces)\n .filter((definition) =>\n Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,\n )\n .filter(({ filter }) => (filter ? filter(data ?? {}, role) : true))\n .toSorted(byPosition);\n};\n\n/**\n * @internal\n */\nexport const useSurfaces = () => {\n const manager = usePluginManager();\n const surfacesByModule = useAtomValue(manager.capabilities.atomByModule(Capabilities.ReactSurface));\n return useMemo(() => {\n const result: Definition[] = [];\n for (const [moduleId, surfaces] of Object.entries(surfacesByModule)) {\n for (const def of surfaces.flat()) {\n result.push(def);\n }\n }\n return result;\n }, [surfacesByModule]);\n};\n\n/**\n * @returns `true` if there is a contributed surface which matches the specified role & data, `false` otherwise.\n *\n * Two overloads:\n * - Typed: pass a `type` role token and `data` is constrained to the token's\n * declared contract (e.g. `AppSurface.Section` requires `attendableId`).\n * - Legacy: pass a string `role` and `data` is untyped.\n */\nexport function isSurfaceAvailable<TToken extends RoleToken<any>>(\n capabilityManager: CapabilityManager.CapabilityManager,\n args: { type: TToken; data?: TokenData<TToken>; role?: never },\n): boolean;\nexport function isSurfaceAvailable(\n capabilityManager: CapabilityManager.CapabilityManager,\n args: Pick<Props, 'role' | 'data'> & { type?: undefined },\n): boolean;\nexport function isSurfaceAvailable(\n capabilityManager: CapabilityManager.CapabilityManager,\n { role, type, data }: { role?: string; type?: RoleToken<any>; data?: unknown },\n): boolean {\n const effectiveRole = role ?? type?.role;\n if (effectiveRole == null) {\n return false;\n }\n const surfaces = capabilityManager.getAll(Capabilities.ReactSurface);\n const candidates = findCandidates(surfaces.flat(), {\n role: effectiveRole,\n data: data as Props['data'],\n });\n return candidates.length > 0;\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, {\n type ReactElement,\n type Ref,\n cloneElement,\n forwardRef,\n useCallback,\n useLayoutEffect,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { addEventListener, combine } from '@dxos/async';\nimport { useMergeRefs } from '@dxos/react-hooks';\n\nimport { useSurface } from '../../hooks';\n\nexport type SurfaceInfoProps = {\n children: ReactElement<{ ref?: Ref<HTMLElement> }>;\n};\n\n/**\n * Debug wrapper for surfaces.\n */\nexport const SurfaceInfo = forwardRef<HTMLElement, SurfaceInfoProps>(({ children }, forwardedRef) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n const [expand, setExpand] = useState(false);\n const info = useSurface();\n\n const [root, setRoot] = useState<HTMLElement | null>(null);\n const measureRef = useCallback((node: HTMLElement | null) => setRoot(node), []);\n const mergedRef = useMergeRefs([measureRef, forwardedRef]);\n const childWithRef = cloneElement(children, { ref: mergedRef });\n\n useLayoutEffect(() => {\n if (!root) {\n setRect(null);\n return;\n }\n\n const measure = () => {\n setRect(root.getBoundingClientRect());\n };\n\n const observer = new ResizeObserver(measure);\n observer.observe(root);\n measure();\n\n return combine(\n addEventListener(window, 'scroll', measure, true),\n addEventListener(window, 'resize', measure),\n () => {\n observer.disconnect();\n },\n );\n }, [root]);\n\n const padding = 0;\n return (\n <>\n {childWithRef}\n {rect &&\n createPortal(\n <div\n className='z-[100] fixed flex flex-col-reverse scrollbar-none overflow-auto pointer-events-none'\n style={{\n top: rect.top + padding,\n left: rect.left + padding,\n width: rect.width - padding * 2,\n height: rect.height - padding * 2,\n }}\n >\n {expand ? (\n <div\n className='absolute inset-0 bg-deck-surface border border-green-500 cursor-pointer pointer-events-auto overflow-auto'\n onPointerDown={(ev) => ev.stopPropagation()}\n onClick={(ev) => {\n ev.stopPropagation();\n setExpand(false);\n }}\n >\n <pre className='p-2 text-xs text-description font-mono'>{JSON.stringify({ info }, null, 2)}</pre>\n </div>\n ) : (\n <span\n className='absolute right-1 bottom-0 flex items-center p-1 text-green-500 opacity-80 hover:opacity-100 text-xl cursor-pointer pointer-events-auto'\n title={info.id}\n onPointerDown={(ev) => ev.stopPropagation()}\n onClick={(ev) => {\n ev.stopPropagation();\n setExpand(true);\n }}\n >\n ⓘ\n </span>\n )}\n </div>,\n // TODO(burdon): Create well-known element to gather all debug portals.\n document.body,\n )}\n </>\n );\n});\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport React, {\n type Context,\n type PropsWithChildren,\n type ProfilerOnRenderCallback,\n createContext,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nconst MAX_ENTRIES = 500;\n\n/**\n * Single profiler record captured from React Profiler onRender callback.\n */\nexport type SurfaceProfilerEntry = {\n id: string;\n phase: 'mount' | 'update' | 'nested-update';\n actualDuration: number;\n baseDuration: number;\n startTime: number;\n commitTime: number;\n timestamp: number;\n};\n\n/**\n * Aggregated stats for a single profiled surface.\n */\nexport type SurfaceProfilerStats = {\n id: string;\n mountCount: number;\n updateCount: number;\n totalRenders: number;\n avgActualDuration: number;\n maxActualDuration: number;\n avgBaseDuration: number;\n lastActualDuration: number;\n lastCommitTime: number;\n};\n\n/**\n * Store that collects profiler entries and notifies subscribers.\n */\nclass SurfaceProfilerStore {\n private _entries: SurfaceProfilerEntry[] = [];\n private _listeners = new Set<() => void>();\n private _snapshot: readonly SurfaceProfilerEntry[] = [];\n private _pendingNotify = false;\n\n /** Records an entry and schedules a deferred notification to avoid re-render loops. */\n record(entry: SurfaceProfilerEntry) {\n this._entries.push(entry);\n if (this._entries.length > MAX_ENTRIES) {\n this._entries = this._entries.slice(-MAX_ENTRIES);\n }\n this._snapshot = [...this._entries];\n this._scheduleNotify();\n }\n\n clear() {\n this._entries = [];\n this._snapshot = [];\n this._notifySync();\n }\n\n subscribe = (listener: () => void) => {\n this._listeners.add(listener);\n return () => {\n this._listeners.delete(listener);\n };\n };\n\n getSnapshot = (): readonly SurfaceProfilerEntry[] => {\n return this._snapshot;\n };\n\n /**\n * Defers notification to the next animation frame to break the\n * Profiler onRender → record → notify → re-render → onRender loop.\n */\n private _scheduleNotify() {\n if (!this._pendingNotify) {\n this._pendingNotify = true;\n requestAnimationFrame(() => {\n this._pendingNotify = false;\n this._notifySync();\n });\n }\n }\n\n private _notifySync() {\n for (const listener of this._listeners) {\n listener();\n }\n }\n}\n\ntype SurfaceProfilerContextValue = {\n store: SurfaceProfilerStore;\n};\n\nconst SurfaceProfilerContext: Context<SurfaceProfilerContextValue | undefined> = createContext<\n SurfaceProfilerContextValue | undefined\n>(undefined);\n\n/**\n * Provider that collects React Profiler data from Surface components.\n */\nexport const SurfaceProfilerProvider = ({ children }: PropsWithChildren) => {\n const storeRef = useRef<SurfaceProfilerStore>(null);\n if (!storeRef.current) {\n storeRef.current = new SurfaceProfilerStore();\n }\n return (\n <SurfaceProfilerContext.Provider value={{ store: storeRef.current }}>{children}</SurfaceProfilerContext.Provider>\n );\n};\n\n/**\n * Returns a stable onRender callback for use with React Profiler.\n */\nexport const useSurfaceProfilerCallback = (): ProfilerOnRenderCallback | undefined => {\n const store = useContext(SurfaceProfilerContext)?.store;\n return useMemo<ProfilerOnRenderCallback | undefined>(() => {\n if (!store) {\n return undefined;\n }\n return (id, phase, actualDuration, baseDuration, startTime, commitTime) => {\n store.record({\n id,\n phase,\n actualDuration,\n baseDuration,\n startTime,\n commitTime,\n timestamp: Date.now(),\n });\n };\n }, [store]);\n};\n\n/**\n * Returns all profiler entries reactively.\n */\nexport const useSurfaceProfilerEntries = (): readonly SurfaceProfilerEntry[] => {\n const context = useContext(SurfaceProfilerContext);\n return useSyncExternalStore(context?.store.subscribe ?? noop, context?.store.getSnapshot ?? emptySnapshot);\n};\n\n/**\n * Returns aggregated stats grouped by surface id.\n */\nexport const useSurfaceProfilerStats = (): SurfaceProfilerStats[] => {\n const entries = useSurfaceProfilerEntries();\n const statsMap = new Map<string, SurfaceProfilerStats>();\n\n for (const entry of entries) {\n let stats = statsMap.get(entry.id);\n if (!stats) {\n stats = {\n id: entry.id,\n mountCount: 0,\n updateCount: 0,\n totalRenders: 0,\n avgActualDuration: 0,\n maxActualDuration: 0,\n avgBaseDuration: 0,\n lastActualDuration: 0,\n lastCommitTime: 0,\n };\n statsMap.set(entry.id, stats);\n }\n\n if (entry.phase === 'mount') {\n stats.mountCount++;\n } else {\n stats.updateCount++;\n }\n stats.totalRenders++;\n stats.avgActualDuration =\n (stats.avgActualDuration * (stats.totalRenders - 1) + entry.actualDuration) / stats.totalRenders;\n stats.avgBaseDuration =\n (stats.avgBaseDuration * (stats.totalRenders - 1) + entry.baseDuration) / stats.totalRenders;\n stats.maxActualDuration = Math.max(stats.maxActualDuration, entry.actualDuration);\n stats.lastActualDuration = entry.actualDuration;\n stats.lastCommitTime = entry.commitTime;\n }\n\n return [...statsMap.values()].sort((a, b) => b.maxActualDuration - a.maxActualDuration);\n};\n\n/**\n * Clears all collected profiler entries.\n */\nexport const useSurfaceProfilerClear = (): (() => void) | undefined => {\n const store = useContext(SurfaceProfilerContext)?.store;\n return useMemo(() => (store ? () => store.clear() : undefined), [store]);\n};\n\nconst noop = () => () => {};\nconst EMPTY_SNAPSHOT: readonly SurfaceProfilerEntry[] = [];\nconst emptySnapshot = () => EMPTY_SNAPSHOT;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport type { FC, PropsWithChildren, ReactNode, RefCallback } from 'react';\n\nimport type { MakeOptional, Position } from '@dxos/util';\n\n/**\n * A typed role token. Carries a role string for runtime dispatch plus a phantom\n * data type so consumers using `type={SomeToken}` and providers using\n * `AppSurface.object(SomeToken, ...)` share a single type-level contract.\n *\n * Mint via {@link makeType}.\n */\nexport type RoleToken<TData> = {\n readonly role: string;\n /** Covariant phantom; never accessed at runtime. */\n readonly _phantom?: TData;\n};\n\n/**\n * One entry in a {@link SurfaceFilter} — a role plus the guard that validates\n * the data shape when the Surface dispatcher is matching that role.\n */\nexport type SurfaceBinding = {\n readonly role: string;\n readonly guard: (data: unknown) => boolean;\n};\n\n/**\n * Typed filter binding for {@link create}. Combines one or more `(role, guard)`\n * pairs so a provider can register against multiple roles while keeping the\n * role and its data shape in a single expression.\n */\nexport type SurfaceFilter<TData> = {\n readonly bindings: ReadonlyArray<SurfaceBinding>;\n /** Covariant phantom; never accessed at runtime. */\n readonly _phantom?: TData;\n};\n\n/**\n * Narrow data type carried by a role token.\n */\nexport type TokenData<T> = T extends RoleToken<infer D> ? D : never;\n\n/**\n * Runtime guard for {@link SurfaceFilter}. Distinguishes new-style filter\n * bindings from legacy predicate filters.\n */\nexport const isSurfaceFilter = (value: unknown): value is SurfaceFilter<any> =>\n typeof value === 'object' && value !== null && Array.isArray((value as { bindings?: unknown }).bindings);\n\n/**\n * Mints a typed role token. Identity is structural; all tokens with the same\n * `role` string are interchangeable at runtime.\n */\nexport const makeType = <TData>(role: string): RoleToken<TData> => ({ role });\n\n/**\n * Props that are passed to the Surface component.\n *\n * The role can be provided either as a string via `role` or as a typed\n * {@link RoleToken} via `type`. The typed form narrows `data` to the token's\n * declared shape.\n */\nexport type Props<T extends Record<string, any> = Record<string, unknown>> = {\n /**\n * If specified, the Surface will be wrapped in an error boundary.\n * The fallback component will be rendered if an error occurs.\n */\n fallback?: FC<{ error: Error; data?: any }>;\n\n /**\n * If specified, the Surface will be wrapped in a suspense boundary.\n * The placeholder component will be rendered while the surface component is loading.\n */\n placeholder?: ReactNode;\n} & MakeOptional<CoreProps<T>, 'id' | 'data' | 'role'> & {\n /**\n * Explicitly disallow `type` on the untyped Props overload — if the caller\n * provides `type={AppSurface.X}`, TypeScript must route to the typed\n * overload (where `data` is narrowed by the token). Without this, the\n * catch-all index signature below would accept any `type` value and mask\n * the typed overload entirely.\n */\n type?: undefined;\n } /**\n * Additional props to pass to the component.\n * These props are not used by Surface itself but may be used by components which resolve the surface.\n * Exclude known prop names to prevent overriding well-defined props.\n */ & {\n [K in keyof Record<string, any>]: K extends keyof CoreProps<T> | 'fallback' | 'placeholder' | 'type' ? never : any;\n };\n\n/**\n * Typed Surface consumer props — carries the role/data-shape contract via a\n * {@link RoleToken}. Available as a typed overload of the Surface component so\n * ad-hoc `type` fields on arbitrary spread props don't conflict with the\n * untyped consumer form.\n */\nexport type TypedProps<TToken extends RoleToken<any>> = {\n fallback?: FC<{ error: Error; data?: any }>;\n placeholder?: ReactNode;\n id?: string;\n type: TToken;\n data?: TokenData<TToken>;\n limit?: number | undefined;\n} & {\n /**\n * Additional pass-through props. Known prop names are excluded so the\n * catch-all doesn't widen `data` / `type` / etc. to `any` at the intersection.\n */\n [K in keyof Record<string, any>]: K extends 'fallback' | 'placeholder' | 'id' | 'type' | 'data' | 'limit'\n ? never\n : any;\n};\n\n/**\n * NOTE: If `[key: string]: unknown` is included in shared types, when re-used other fields become unknown as well.\n */\nexport type CoreProps<T extends Record<string, any> = Record<string, unknown>> = PropsWithChildren<{\n /**\n * ID for debugging.\n */\n id: string;\n\n /**\n * Role defines how the data should be rendered. For new code, prefer the\n * typed overload of the Surface component which takes a {@link RoleToken}\n * via the `type` prop instead — it enforces a role/data contract at compile\n * time.\n */\n role: string;\n\n /**\n * The data to be rendered by the surface.\n * NOTE: This must be a stable value.\n */\n data: T;\n\n /**\n * If more than one component is resolved, the limit determines how many are rendered.\n */\n limit?: number | undefined;\n}>;\n\n// TODO(burdon): Remove ref since relying on this would be error prone.\nexport type ComponentProps<T extends Record<string, any> = Record<string, any>> = CoreProps<T> & {\n ref?: RefCallback<HTMLElement>;\n} & Record<string, any>;\n\n/**\n * React component used to render a surface once is has matched.\n */\nexport type ComponentFunction<T extends Record<string, any> = Record<string, any>> = (\n props: ComponentProps<T>,\n) => ReactNode;\n\n/**\n * Definition of when a React component surface should be rendered.\n *\n * The optional `filter` receives the consumer-supplied `role` as its second\n * argument so a single definition can encode role-specific guards (used by the\n * {@link SurfaceFilter}-based `create` overload).\n */\nexport type ReactDefinition<T extends Record<string, any> = any> = Readonly<{\n kind: 'react';\n id: string;\n role: string | string[];\n position?: Position;\n component: ComponentFunction<T>;\n filter?: (data: Record<string, unknown>, role?: string) => data is T;\n}>;\n\n/**\n * Definition of when a Web Component surface should be rendered.\n */\nexport type WebComponentDefinition<T extends Record<string, any> = any> = Readonly<{\n kind: 'web-component';\n id: string;\n role: string | string[];\n position?: Position;\n /**\n * The tag name of the Web Component to render.\n * The Web Component will receive the same props as React surfaces via properties/attributes.\n */\n tagName: string;\n filter?: (data: Record<string, unknown>, role?: string) => data is T;\n}>;\n\n/**\n * Definition of when a surface (React or Web Component) should be rendered.\n */\nexport type Definition<T extends Record<string, any> = any> = ReactDefinition<T> | WebComponentDefinition<T>;\n\n/**\n * Typed React surface definition — role is derived from the filter's bindings.\n */\nexport type TypedReactDefinition<T extends Record<string, any> = any> = Readonly<{\n id: string;\n filter: SurfaceFilter<T>;\n component: ComponentFunction<T>;\n position?: Position;\n}>;\n\n/**\n * Typed Web Component surface definition.\n */\nexport type TypedWebComponentDefinition<T extends Record<string, any> = any> = Readonly<{\n id: string;\n filter: SurfaceFilter<T>;\n tagName: string;\n position?: Position;\n}>;\n\nconst expandBindings = <T extends Record<string, any>>(\n filter: SurfaceFilter<T>,\n): { role: string | string[]; guard: (data: Record<string, unknown>, role?: string) => data is T } => {\n const bindings = filter.bindings;\n const roles = Array.from(new Set(bindings.map((binding) => binding.role)));\n const guard = (data: Record<string, unknown>, role?: string): data is T => {\n if (role != null) {\n // Multiple bindings may share a role (e.g. via `oneOf` of same-role filters);\n // the role matches if ANY of them passes.\n return bindings.some((entry) => entry.role === role && entry.guard(data));\n }\n return bindings.some((entry) => entry.guard(data));\n };\n return { role: roles.length === 1 ? roles[0] : roles, guard };\n};\n\n/**\n * Validates that a surface or extension local ID follows NSID conventions:\n * each dot-separated segment must be alphanumeric, and the final segment must\n * be camelCase (no hyphens). This mirrors the rule enforced when the id is\n * appended to a plugin's NSID to form a full DXN path.\n *\n * @example Valid: 'about', 'integrationArticle', 'article.journal'\n * @example Invalid: 'integration-article', 'plugin-spec'\n */\nconst validateLocalId = (id: string): void => {\n const segments = id.split('.');\n const finalSegment = segments[segments.length - 1];\n if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(finalSegment)) {\n throw new Error(\n `Invalid surface id: \"${id}\". The final segment \"${finalSegment}\" must be camelCase (letters and digits only, starting with a letter — no hyphens or underscores).`,\n );\n }\n};\n\n/**\n * Creates a React surface definition.\n */\nexport function create<T extends Record<string, any> = any>(definition: TypedReactDefinition<T>): ReactDefinition<T>;\nexport function create<T extends Record<string, any> = any>(\n definition: Omit<ReactDefinition<T>, 'kind'>,\n): ReactDefinition<T>;\nexport function create<T extends Record<string, any> = any>(\n definition: TypedReactDefinition<T> | Omit<ReactDefinition<T>, 'kind'>,\n): ReactDefinition<T> {\n validateLocalId(definition.id);\n if (isSurfaceFilter(definition.filter)) {\n const { id, filter, component, position } = definition as TypedReactDefinition<T>;\n const { role, guard } = expandBindings(filter);\n return { kind: 'react', id, role, position, component, filter: guard };\n }\n return { ...(definition as Omit<ReactDefinition<T>, 'kind'>), kind: 'react' };\n}\n\n/**\n * Creates a Web Component surface definition.\n */\nexport function createWeb<T extends Record<string, any> = any>(\n definition: TypedWebComponentDefinition<T>,\n): WebComponentDefinition<T>;\nexport function createWeb<T extends Record<string, any> = any>(\n definition: Omit<WebComponentDefinition<T>, 'kind'>,\n): WebComponentDefinition<T>;\nexport function createWeb<T extends Record<string, any> = any>(\n definition: TypedWebComponentDefinition<T> | Omit<WebComponentDefinition<T>, 'kind'>,\n): WebComponentDefinition<T> {\n validateLocalId(definition.id);\n if (isSurfaceFilter(definition.filter)) {\n const { id, filter, tagName, position } = definition as TypedWebComponentDefinition<T>;\n const { role, guard } = expandBindings(filter);\n return { kind: 'web-component', id, role, position, tagName, filter: guard };\n }\n return { ...(definition as Omit<WebComponentDefinition<T>, 'kind'>), kind: 'web-component' };\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\n// TODO(wittjosiah): Cleanup to avoid re-naming.\nimport { SurfaceContext } from './context';\nimport { SurfaceComponent, isSurfaceAvailable } from './SurfaceComponent';\nimport {\n SurfaceProfilerProvider,\n useSurfaceProfilerCallback,\n useSurfaceProfilerClear,\n useSurfaceProfilerEntries,\n useSurfaceProfilerStats,\n} from './SurfaceProfilerContext';\nimport {\n type Definition as SurfaceDefinition,\n type RoleToken as SurfaceRoleToken,\n type SurfaceBinding as SurfaceBindingType,\n type SurfaceFilter as SurfaceFilterType,\n type TokenData as SurfaceTokenData,\n type TypedProps as SurfaceTypedProps,\n create as createSurface,\n createWeb as createWebSurface,\n isSurfaceFilter as isSurfaceFilterFn,\n makeType as makeTypeFn,\n} from './types';\n\nexport namespace Surface {\n export type Definition = SurfaceDefinition;\n export const create = createSurface;\n export const createWeb = createWebSurface;\n\n export type Context = SurfaceContext;\n export const Context = SurfaceContext;\n\n export const Surface = SurfaceComponent;\n export const isAvailable = isSurfaceAvailable;\n\n export type RoleToken<TData> = SurfaceRoleToken<TData>;\n export type Binding = SurfaceBindingType;\n export type Filter<TData> = SurfaceFilterType<TData>;\n export type TokenData<T> = SurfaceTokenData<T>;\n export type TypedProps<TToken extends SurfaceRoleToken<any>> = SurfaceTypedProps<TToken>;\n export const makeType = makeTypeFn;\n export const isFilter = isSurfaceFilterFn;\n\n export const ProfilerProvider = SurfaceProfilerProvider;\n export const useProfilerCallback = useSurfaceProfilerCallback;\n export const useProfilerEntries = useSurfaceProfilerEntries;\n export const useProfilerStats = useSurfaceProfilerStats;\n export const useProfilerClear = useSurfaceProfilerClear;\n}\n\nexport type { SurfaceProfilerEntry, SurfaceProfilerStats } from './SurfaceProfilerContext';\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["topologicalSort", "nodes", "getDependencies", "nodeId", "seen", "Set", "path", "has", "Error", "node", "find", "n", "id", "newPath", "newSeen", "dependsOn", "flatMap", "depId", "allDependencies", "map", "filter", "index", "self", "indexOf", "undefined", "useContext", "raise", "createContext", "useContext", "raise", "PluginManagerContext", "undefined", "usePluginManager", "Error", "PluginManagerProvider", "Provider", "createContext", "SurfaceContext", "undefined", "useAtomValue", "React", "Fragment", "Profiler", "Suspense", "forwardRef", "memo", "useEffect", "useMemo", "useRef", "log", "ErrorBoundary", "useDefaultValue", "byPosition", "React", "cloneElement", "forwardRef", "useCallback", "useLayoutEffect", "useState", "createPortal", "addEventListener", "combine", "useMergeRefs", "SurfaceInfo", "forwardRef", "children", "forwardedRef", "rect", "setRect", "useState", "expand", "setExpand", "info", "useSurface", "root", "setRoot", "measureRef", "useCallback", "node", "mergedRef", "useMergeRefs", "childWithRef", "cloneElement", "ref", "useLayoutEffect", "measure", "getBoundingClientRect", "observer", "ResizeObserver", "observe", "combine", "addEventListener", "window", "disconnect", "padding", "createPortal", "div", "className", "style", "top", "left", "width", "height", "onPointerDown", "ev", "stopPropagation", "onClick", "pre", "JSON", "stringify", "span", "title", "id", "document", "body", "React", "createContext", "useContext", "useMemo", "useRef", "useSyncExternalStore", "MAX_ENTRIES", "SurfaceProfilerStore", "_entries", "_listeners", "Set", "_snapshot", "_pendingNotify", "record", "entry", "push", "length", "slice", "_scheduleNotify", "clear", "_notifySync", "subscribe", "listener", "add", "delete", "getSnapshot", "requestAnimationFrame", "SurfaceProfilerContext", "undefined", "SurfaceProfilerProvider", "children", "storeRef", "current", "Provider", "value", "store", "useSurfaceProfilerCallback", "id", "phase", "actualDuration", "baseDuration", "startTime", "commitTime", "timestamp", "Date", "now", "useSurfaceProfilerEntries", "context", "noop", "emptySnapshot", "useSurfaceProfilerStats", "entries", "statsMap", "Map", "stats", "get", "mountCount", "updateCount", "totalRenders", "avgActualDuration", "maxActualDuration", "avgBaseDuration", "lastActualDuration", "lastCommitTime", "set", "Math", "max", "values", "sort", "a", "b", "useSurfaceProfilerClear", "EMPTY_SNAPSHOT", "elementRef", "forwardRef", "propsRef", "useRef", "id", "role", "data", "limit", "useEffect", "Object", "assign", "element", "containerRef", "current", "appendChild", "forwardedRef", "definition", "div", "WebComponentWrapper", "React", "FallbackComponent", "value", "contextValue", "ref", "debug", "DEBUG", "name", "className", "data-role", "SurfaceInfo", "onProfilerRender", "includes", "profilerId", "Component", "SurfaceContextProvider", "effectiveRole", "log", "SurfaceComponent", "ErrorFallback", "String", "error", "message", "findCandidates", "surfacesByModule", "useAtomValue", "useMemo", "moduleId", "def", "result", "surfaces", "isSurfaceFilter", "value", "Array", "isArray", "bindings", "makeType", "role", "expandBindings", "filter", "roles", "from", "Set", "map", "binding", "guard", "data", "some", "entry", "length", "validateLocalId", "id", "segments", "split", "finalSegment", "test", "Error", "create", "definition", "component", "position", "kind", "createWeb", "tagName", "Surface", "create", "createSurface", "createWeb", "createWebSurface", "Context", "SurfaceContext", "SurfaceComponent", "isAvailable", "isSurfaceAvailable", "makeType", "makeTypeFn", "isFilter", "isSurfaceFilterFn", "ProfilerProvider", "SurfaceProfilerProvider", "useProfilerCallback", "useSurfaceProfilerCallback", "useProfilerEntries", "useSurfaceProfilerEntries", "useProfilerStats", "useSurfaceProfilerStats", "useProfilerClear", "useSurfaceProfilerClear", "useSurface", "useContext", "Surface", "Context", "raise", "Error"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/core/capability.ts"],
|
|
4
|
-
"sourcesContent": ["//\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 * 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 */\nexport const make = <T>(identifier: string) => {\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 */\n// TODO(dmaretskyi): Make the return type non-generic so capabilities are non-discernable.\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): Capability<I> => {\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, R> => {\n const lazyFn: LazyCapability<T, R> = (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 return Object.assign(lazyFn, { [ModuleTag]: name });\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"],
|
|
5
|
-
"mappings": ";;;;;AAAA;;;;;;;;;;;;;;;;AAKA,YAAYA,aAAa;AACzB,YAAYC,YAAY;AACxB,YAAYC,WAAW;AAahB,IAAMC,UAAN,cAA8BC,YAAI,uCAAA,EAAA,EAAA;AAGpC;AAUE,IAAMC,MAAM,CAAIC,iBACdC,eAAQJ,SAAS,CAACK,YAChBC,WAAI;EACTA,KAAK,MAAMD,QAAQH,IAAIC,YAAAA;EACvBI,OAAO,CAACC,UAAWA,iBAAiBC,QAAQD,QAAQ,IAAIC,MAAMC,OAAOF,KAAAA,CAAAA;AACvE,CAAA,CAAA;AAQG,IAAMG,SAAS,CAAIR,iBACjBS,WAAIZ,SAAS,CAACK,YAAYA,QAAQM,OAAOR,YAAAA,CAAAA;AAO3C,IAAMU,UAAU,CAAIV,iBAClBC,eAAQJ,SAAS,CAACK,YAAYA,QAAQQ,QAAQV,YAAAA,CAAAA;AAOhD,IAAMW,OAAO,CAAIX,iBACfS,WAAIZ,SAAS,CAACK,YAAYA,QAAQS,KAAKX,YAAAA,CAAAA;AAOzC,IAAMY,eAAe,CAC1BZ,iBAEOS,WAAIZ,SAAS,CAACK,YAAYA,QAAQU,aAAaZ,YAAAA,CAAAA;AAKjD,IAAMa,UAAU,CAAOb,cAA+Bc,QACrDC,aAAOD,KAAKf,IAAIC,YAAAA,EAAcgB,KAAYC,YAAK,CAAA;AAOhD,IAAMC,YAA2BC,uBAAOC,IAAI,+BAAA;AAiB5C,IAAMC,OAAO,CAAIC,eAAAA;AACtB,SAAO;IAAEA;EAAW;AACtB;AAmCO,IAAMC,cAAc,CACzBC,cACAC,gBACAC,eAAAA;AAEA,SAAO;IACLC,WAAWH;IACXC;IACAC;EACF;AACF;AA4BO,IAAME,OAAO,CAClBC,MACAC,MAAAA;AAEA,QAAMC,SAA+B,CAACC,UAC7BC,WAAI,aAAA;AACT,UAAM,EAAEC,SAASC,cAAa,IAAK,OAAcC,eAAQ,MAAMN,EAAAA,CAAAA;AAC/D,UAAMO,SAAS,OAAOF,cAAcH,KAAAA;AACpC,UAAMM,aAAaD,UAAU,OAAO,CAAA,IAAKE,MAAMC,QAAQH,MAAAA,IAAUE,MAAME,KAAKJ,MAAAA,IAAU;MAACA;;AACvF,WAAOC;EACT,CAAA;AAEF,SAAOI,OAAOC,OAAOZ,QAAQ;IAAE,CAACb,SAAAA,GAAYW;EAAK,CAAA;AACnD;AAQO,IAAMe,eAAe,CAACC,eAAAA;AAC3B,SAAOA,cAAc,OAAOA,eAAe,cAAc3B,aAAa2B,aAClEC,OAAOD,WAAW3B,SAAAA,CAAU,IAC5B6B;AACN;AA2CO,IAAMC,aAAa,CAMxBC,OACsDA;",
|
|
6
|
-
"names": ["Context", "Effect", "Layer", "Service", "Tag", "get", "interfaceDef", "flatMap", "manager", "try", "catch", "error", "Error", "String", "getAll", "map", "waitFor", "atom", "atomByModule", "asLayer", "tag", "effect", "pipe", "orDie", "ModuleTag", "Symbol", "for", "make", "identifier", "contributes", "interfaceDef", "implementation", "deactivate", "interface", "lazy", "name", "c", "lazyFn", "props", "gen", "default", "getCapability", "promise", "result", "normalized", "Array", "isArray", "from", "Object", "assign", "getModuleTag", "capability", "String", "undefined", "makeModule", "fn"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/core/url-loader.ts", "../../../src/core/plugin-asset-cache.ts", "../../../src/core/plugin-manifest.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\n\nimport { BaseError } from '@dxos/errors';\nimport { log } from '@dxos/log';\n\nimport * as Plugin from './plugin';\nimport * as PluginAssetCache from './plugin-asset-cache';\nimport * as PluginManifest from './plugin-manifest';\n\nconst DEFAULT_KEY = 'org.dxos.composer.remote-plugins';\n\n/**\n * Tagged error for any failure during remote plugin loading. Construction sites\n * set `context.locator` and `context.reason` (one of `'invalid-locator' |\n * 'manifest-error' | 'cache-error' | 'import-failed' | 'meta-missing' |\n * 'meta-mismatch' | 'duplicate-id'`) so handlers can route on the failure mode.\n */\nexport class RemotePluginLoadError extends BaseError.extend('RemotePluginLoadError', 'Failed to load remote plugin') {}\n\n/**\n * Abstraction over key-value storage (defaults to localStorage).\n */\nexport type Storage = {\n get(key: string): string | null;\n set(key: string, value: string): void;\n};\n\n/**\n * Options for configuring the URL loader.\n */\nexport type Options = {\n storage?: Storage;\n key?: string;\n /**\n * Per-platform offline asset cache. Defaults to a no-op cache (no offline support).\n */\n cache?: PluginAssetCache.Cache;\n};\n\n/**\n * Options for the preload entry point. Adds an optional progress hook so hosts\n * can drive a boot-loader counter (`Loading plugins (3/12)…`) as remote plugin\n * manifests resolve. Resolution order is *not* deterministic — each entry races\n * its own network fetch — so callers should treat `loaded` as a count, not an\n * index. Failures are still swallowed; `loaded` advances on both success and\n * recoverable failure so the counter always reaches `total`.\n */\nexport type PreloadOptions = Options & {\n onPluginLoaded?: (loaded: number, total: number) => void;\n};\n\n/**\n * Persisted record of a remote plugin that has been loaded previously.\n *\n * `url` is the URL of the plugin manifest (`plugin.json`), not the entry module.\n */\nexport type RemotePluginEntry = {\n id: string;\n url: string;\n /** Installed version string, e.g. `v1.0.0`. Populated after install from a community catalog entry. */\n version?: string;\n};\n\nconst defaultStorage = (): Storage => ({\n get: (key) => localStorage.getItem(key),\n set: (key, value) => localStorage.setItem(key, value),\n});\n\nconst getPersistedRemotePlugins = (storage: Storage, key: string): RemotePluginEntry[] => {\n try {\n const parsed: unknown = JSON.parse(storage.get(key) ?? '[]');\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter(\n (entry): entry is RemotePluginEntry =>\n typeof entry === 'object' && entry !== null && typeof entry.id === 'string' && typeof entry.url === 'string',\n );\n } catch {\n return [];\n }\n};\n\nconst persistRemotePlugin = (storage: Storage, key: string, entry: RemotePluginEntry): void => {\n try {\n const entries = getPersistedRemotePlugins(storage, key).filter((existing) => existing.id !== entry.id);\n entries.push(entry);\n storage.set(key, JSON.stringify(entries));\n } catch (error) {\n log.warn('failed to persist remote plugin entry', { entry, error });\n }\n};\n\nconst removePersistedRemotePlugin = (storage: Storage, key: string, pluginId: string): void => {\n try {\n const entries = getPersistedRemotePlugins(storage, key).filter((existing) => existing.id !== pluginId);\n storage.set(key, JSON.stringify(entries));\n } catch (error) {\n log.warn('failed to remove remote plugin entry', { pluginId, error });\n }\n};\n\nconst isUrl = (locator: string): boolean => {\n try {\n const url = new URL(locator);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n};\n\n/**\n * Returns true when the URL's hostname is the local host (localhost, 127.0.0.1, or ::1).\n */\nexport const isLocalUrl = (locator: string): boolean => {\n try {\n const hostname = new URL(locator).hostname.toLowerCase();\n // WHATWG URL returns '::1' without brackets in Node; some browsers return '[::1]'.\n return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '[::1]';\n } catch {\n return false;\n }\n};\n\n/**\n * Returns the list of remote plugin entries previously persisted by {@link make}.\n * Useful for UI code that needs to know which loaded plugins were installed from a URL\n * (e.g. to surface a tag on remote or localhost-hosted plugins).\n */\nexport const getRemoteEntries = (options: Options = {}): readonly RemotePluginEntry[] => {\n const storage = options.storage ?? defaultStorage();\n const key = options.key ?? DEFAULT_KEY;\n return getPersistedRemotePlugins(storage, key);\n};\n\n/**\n * Updates the persisted installed version for an already-stored remote plugin entry.\n * Does nothing if the plugin has not been persisted yet.\n */\nexport const setInstalledVersion = (id: string, version: string, options: Options = {}): void => {\n const storage = options.storage ?? defaultStorage();\n const key = options.key ?? DEFAULT_KEY;\n const entries = getPersistedRemotePlugins(storage, key);\n const index = entries.findIndex((entry) => entry.id === id);\n if (index === -1) {\n return;\n }\n entries[index] = { ...entries[index], version };\n try {\n storage.set(key, JSON.stringify(entries));\n } catch (error) {\n log.warn('failed to update installed version for remote plugin', { id, version, error });\n }\n};\n\n/**\n * Returns the installed version string for the given plugin id, or `undefined` if\n * the plugin was installed without version tracking (legacy install) or is not found.\n */\nexport const getInstalledVersion = (id: string, options: Options = {}): string | undefined => {\n const storage = options.storage ?? defaultStorage();\n const key = options.key ?? DEFAULT_KEY;\n return getPersistedRemotePlugins(storage, key).find((entry) => entry.id === id)?.version;\n};\n\nconst normalizePluginExport = (mod: Record<string, unknown>): Plugin.Plugin => {\n const exported = mod.default;\n if (Plugin.isPlugin(exported)) {\n return exported;\n }\n if (typeof exported === 'function') {\n const result = (exported as () => unknown)();\n if (Plugin.isPlugin(result)) {\n return result;\n }\n }\n throw new Error('Remote module default export is not a Plugin or a zero-arg plugin factory.');\n};\n\n/**\n * Loads stylesheets declared in the manifest by appending `<link rel=\"stylesheet\">` elements to the host document.\n * Each link is tagged with `data-dxos-plugin-id` so `uninstall` can clean them up.\n */\nconst loadStylesheets = (\n manifest: PluginManifest.ResolvedManifest,\n cache: PluginAssetCache.Cache,\n): Effect.Effect<void, PluginAssetCache.PluginAssetCacheError> =>\n Effect.gen(function* () {\n if (typeof document === 'undefined') {\n return;\n }\n const cssUrls = manifest.assetUrls.filter((url) => url.endsWith('.css'));\n for (const url of cssUrls) {\n const resolved = yield* cache.resolve(manifest.id, url);\n if (document.querySelector(`link[data-dxos-plugin-id=\"${manifest.id}\"][href=\"${resolved}\"]`)) {\n continue;\n }\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = resolved;\n link.dataset.dxosPluginId = manifest.id;\n document.head.appendChild(link);\n }\n });\n\nconst loadFromManifest = (\n manifestUrl: string,\n cache: PluginAssetCache.Cache,\n): Effect.Effect<{ plugin: Plugin.Plugin; manifest: PluginManifest.ResolvedManifest }, RemotePluginLoadError> =>\n Effect.gen(function* () {\n log.info('loading remote plugin', { manifestUrl });\n const manifest = yield* PluginManifest.fetchManifest(manifestUrl).pipe(\n Effect.mapError(\n (cause) => new RemotePluginLoadError({ context: { locator: manifestUrl, reason: 'manifest-error' }, cause }),\n ),\n );\n const wrapCacheError = Effect.mapError(\n (cause: PluginAssetCache.PluginAssetCacheError) =>\n new RemotePluginLoadError({ context: { locator: manifestUrl, reason: 'cache-error' }, cause }),\n );\n // Dev-mode manifests (served by `vite dev` via composerPlugin) skip the offline\n // cache: chunks resolve on demand through the dev server, the asset list isn't\n // enumerable up-front, and CSS arrives via runtime <style> injection rather than\n // static <link> tags.\n if (!manifest.dev) {\n // Cache the manifest URL alongside its declared assets. Without it, `preload` on a\n // subsequent reload would fetch the manifest from the network — and fail when the\n // plugin's host is offline, dropping the plugin from the runtime.\n const cachedUrls =\n manifest.assetUrls.indexOf(manifestUrl) === -1 ? [manifestUrl, ...manifest.assetUrls] : manifest.assetUrls;\n yield* cache.cache(manifest.id, cachedUrls).pipe(wrapCacheError);\n }\n const entryUrl = manifest.dev\n ? manifest.entryUrl\n : yield* cache.resolve(manifest.id, manifest.entryUrl).pipe(wrapCacheError);\n const mod = yield* Effect.tryPromise({\n try: () => import(/* @vite-ignore */ entryUrl),\n catch: (cause) =>\n new RemotePluginLoadError({ context: { locator: manifestUrl, reason: 'import-failed' }, cause }),\n });\n const plugin = normalizePluginExport(mod);\n if (!plugin.meta.id || !plugin.meta.name) {\n return yield* Effect.fail(\n new RemotePluginLoadError({ context: { locator: manifestUrl, reason: 'meta-missing' } }),\n );\n }\n if (plugin.meta.id !== manifest.id) {\n return yield* Effect.fail(\n new RemotePluginLoadError({\n context: {\n locator: manifestUrl,\n reason: 'meta-mismatch',\n metaId: plugin.meta.id,\n manifestId: manifest.id,\n },\n }),\n );\n }\n // Append stylesheets only after the entry imports cleanly and meta validation\n // passes. If we did this earlier and the import or meta checks failed, the\n // `<link>` tags would leak into the host DOM with no plugin to own their\n // teardown — `uninstall` only runs for plugins the manager actually accepted.\n // In dev mode, Vite injects styles at runtime via the module graph, so static\n // <link> tags would duplicate (or 404, since CSS chunks aren't pre-built).\n if (!manifest.dev) {\n yield* loadStylesheets(manifest, cache).pipe(wrapCacheError);\n }\n return { plugin, manifest };\n });\n\n/**\n * Preloads previously persisted remote plugins from storage. Per-entry failures\n * are logged and swallowed — the returned effect always succeeds with whichever\n * plugins loaded cleanly, so a single bad entry can't block the host's startup.\n */\nexport const preload = (options: PreloadOptions = {}): Effect.Effect<Plugin.Plugin[], never> =>\n Effect.gen(function* () {\n const storage = options.storage ?? defaultStorage();\n const key = options.key ?? DEFAULT_KEY;\n const cache = options.cache ?? PluginAssetCache.noop();\n const onPluginLoaded = options.onPluginLoaded;\n\n const entries = getPersistedRemotePlugins(storage, key);\n if (entries.length === 0) {\n return [];\n }\n log.info('preloading remote plugins', { count: entries.length });\n const total = entries.length;\n let loaded = 0;\n const results = yield* Effect.all(\n entries.map((entry) =>\n loadFromManifest(entry.url, cache).pipe(\n Effect.tapError((error) => Effect.sync(() => log.warn('failed to preload remote plugin', { entry, error }))),\n Effect.option,\n // Tick the progress hook on both success and recoverable failure so\n // the counter monotonically reaches `total`. The host-supplied\n // callback is best-effort: any synchronous throw flows through\n // `Effect.try` and gets logged + ignored so a buggy hook can't\n // derail the preload.\n Effect.tap(() =>\n Effect.sync(() => {\n loaded += 1;\n }).pipe(\n Effect.andThen(Effect.try(() => onPluginLoaded?.(loaded, total))),\n Effect.tapError((error) => Effect.sync(() => log.warn('onPluginLoaded threw', { loaded, total, error }))),\n Effect.ignore,\n ),\n ),\n ),\n ),\n { concurrency: 'unbounded' },\n );\n return results.flatMap((result) =>\n Option.match(result, {\n onNone: () => [],\n onSome: ({ plugin }) => [plugin],\n }),\n );\n });\n\n/**\n * Creates a plugin loader that resolves built-in plugins by ID or loads remote plugins from URLs.\n *\n * Remote URLs must point at a plugin manifest (`plugin.json`). The loader fetches the manifest,\n * eagerly persists every declared asset via the configured `PluginAssetCache`, then dynamic-imports\n * the entry module.\n */\nexport const make = (builtinPlugins: Plugin.Plugin[], options: Options = {}) => {\n const storage = options.storage ?? defaultStorage();\n const key = options.key ?? DEFAULT_KEY;\n const cache = options.cache ?? PluginAssetCache.noop();\n\n return (locator: string): Effect.Effect<{ plugin: Plugin.Plugin; dev?: boolean }, RemotePluginLoadError> =>\n Effect.gen(function* () {\n const builtin = builtinPlugins.find((plugin) => plugin.meta.id === locator);\n if (builtin) {\n return { plugin: builtin };\n }\n if (!isUrl(locator)) {\n return yield* Effect.fail(new RemotePluginLoadError({ context: { locator, reason: 'invalid-locator' } }));\n }\n const { plugin, manifest } = yield* loadFromManifest(locator, cache);\n // Production manifests can't collide with a builtin id — that would make\n // the registered plugin permanently inaccessible. Dev manifests are\n // allowed to collide because the manager shadow primitive handles the\n // overlap (dev plugin takes the id slot for the session, original is\n // restored on uninstall or page reload).\n if (!manifest.dev) {\n const duplicate = builtinPlugins.find((existing) => existing.meta.id === plugin.meta.id);\n if (duplicate) {\n return yield* Effect.fail(\n new RemotePluginLoadError({ context: { locator, reason: 'duplicate-id', id: plugin.meta.id } }),\n );\n }\n persistRemotePlugin(storage, key, { id: plugin.meta.id, url: locator });\n }\n return { plugin, dev: manifest.dev };\n });\n};\n\n/**\n * Removes a previously installed remote plugin: drops the persisted entry, evicts cached\n * assets, and removes any stylesheet `<link>` tags that {@link loadFromManifest} appended.\n *\n * Cache eviction failures are logged and swallowed — the persisted entry has already been\n * dropped so the user-visible state is consistent regardless of whether the platform\n * cache cooperated.\n */\nexport const uninstall = (pluginId: string, options: Options = {}): Effect.Effect<void, never> =>\n Effect.gen(function* () {\n const storage = options.storage ?? defaultStorage();\n const key = options.key ?? DEFAULT_KEY;\n const cache = options.cache ?? PluginAssetCache.noop();\n\n removePersistedRemotePlugin(storage, key, pluginId);\n if (typeof document !== 'undefined') {\n document.querySelectorAll(`link[data-dxos-plugin-id=\"${pluginId}\"]`).forEach((node) => node.remove());\n }\n yield* cache.evict(pluginId).pipe(\n Effect.tapError((error) => Effect.sync(() => log.warn('failed to evict plugin assets', { pluginId, error }))),\n Effect.ignore,\n );\n });\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { BaseError } from '@dxos/errors';\n\n/**\n * Tagged error for cache operations. Construction sites supply `context.operation`\n * (one of `'cache' | 'evict' | 'resolve' | 'list'`) and `context.pluginId` so\n * downstream handlers can route on the failed call without scanning the message.\n */\nexport class PluginAssetCacheError extends BaseError.extend(\n 'PluginAssetCacheError',\n 'Plugin asset cache operation failed',\n) {}\n\n/**\n * Per-platform offline cache for third-party plugin assets.\n *\n * Implementations live alongside their platform glue (composer-app's\n * `asset-cache/{tauri,service-worker}.ts`); the no-op default is for tests\n * and unsupported environments.\n */\nexport interface Cache {\n /**\n * Persist all listed URLs under the namespace of `pluginId`. Idempotent.\n * The order of `urls` is significant — the first entry is treated as the entry module.\n */\n cache(pluginId: string, urls: readonly string[]): Effect.Effect<void, PluginAssetCacheError>;\n\n /**\n * Drop all assets for a plugin (uninstall).\n */\n evict(pluginId: string): Effect.Effect<void, PluginAssetCacheError>;\n\n /**\n * Resolves a plugin asset URL to a platform-specific cached URL when one is available.\n * Returns the original URL when no cached copy exists or the platform serves cached\n * responses transparently (e.g. service worker fetch interception on web).\n */\n resolve(pluginId: string, url: string): Effect.Effect<string, PluginAssetCacheError>;\n\n /**\n * List currently cached plugin ids (diagnostic).\n */\n list(): Effect.Effect<readonly string[], PluginAssetCacheError>;\n}\n\n/**\n * No-op implementation. Used when no platform cache is registered (tests, unsupported environments).\n * Plugins still load — they just have no offline guarantee.\n */\nexport const noop = (): Cache => ({\n cache: () => Effect.void,\n evict: () => Effect.void,\n resolve: (_pluginId, url) => Effect.succeed(url),\n list: () => Effect.succeed([] as readonly string[]),\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"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["Effect", "Option", "BaseError", "log", "Effect", "BaseError", "PluginAssetCacheError", "extend", "noop", "cache", "void", "evict", "resolve", "_pluginId", "url", "succeed", "list", "FetchHttpClient", "HttpClient", "HttpClientRequest", "HttpClientResponse", "Effect", "Schema", "BaseError", "PLUGIN_ENTRY_FILENAME", "PLUGIN_DEV_SERVER_PORT", "PluginManifestError", "extend", "Manifest", "Struct", "id", "String", "name", "version", "assets", "Array", "devEntry", "pipe", "optional", "resolve", "manifestUrl", "manifest", "dev", "undefined", "entryUrl", "URL", "toString", "assetUrls", "map", "asset", "parse", "payload", "decodeUnknownSync", "includes", "Error", "fetchManifest", "gen", "response", "get", "execute", "mapError", "cause", "context", "reason", "status", "fail", "schemaBodyJson", "scoped", "provide", "layer", "DEFAULT_KEY", "defaultStorage", "BaseError", "value", "localStorage", "getPersistedRemotePlugins", "storage", "key", "get", "parsed", "entries", "error", "log", "entry", "pluginId", "url", "URL", "hostname", "locator", "options", "index", "findIndex", "version", "id", "find", "normalizePluginExport", "mod", "exported", "Plugin", "result", "resolved", "resolve", "manifest", "document", "querySelector", "link", "href", "dataset", "head", "loadFromManifest", "manifestUrl", "context", "reason", "cause", "wrapCacheError", "assetUrls", "cache", "entryUrl", "try", "catch", "RemotePluginLoadError", "plugin", "metaId", "manifestId", "PluginAssetCache", "noop", "onPluginLoaded", "info", "total", "results", "pipe", "andThen", "Effect", "loaded", "flatMap", "onSome", "gen", "builtin", "duplicate", "persistRemotePlugin", "dev", "removePersistedRemotePlugin", "querySelectorAll", "evict", "sync", "warn"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/core/plugin-manager.ts", "../../../src/core/capability-manager.ts", "../../../src/core/registry.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom, Registry } from '@effect-atom/atom-react';\nimport * as Array from 'effect/Array';\nimport * as Cause from 'effect/Cause';\nimport * as Deferred from 'effect/Deferred';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as Function from 'effect/Function';\nimport * as HashSet from 'effect/HashSet';\nimport * as PubSub from 'effect/PubSub';\nimport * as Ref from 'effect/Ref';\n\nimport { EffectEx, Performance } from '@dxos/effect';\nimport { BaseError } from '@dxos/errors';\nimport { log } from '@dxos/log';\n\nimport * as ActivationEvent from './activation-event';\nimport * as Capability from './capability';\nimport * as CapabilityManager from './capability-manager';\nimport * as Plugin from './plugin';\n// Imported with a `PluginRegistry` alias because the unrelated `@effect-atom/atom-react`\n// `Registry` is already imported above; from outside this file the namespace is\n// re-exported as `Registry` via `./index.ts`.\nimport * as PluginRegistry from './registry';\n\n/**\n * Tagged error for failures during the constructor-launched core/enabled\n * `enable()` chain. Surfaces via {@link PluginManager.activate}'s wait on\n * `_initialization` so a caller blocked on initialization gets a typed\n * failure (with the original error preserved as `cause`) instead of an\n * untyped `Error`.\n */\nexport class PluginInitializationError extends BaseError.extend(\n 'PluginInitializationError',\n 'Plugin manager initialization failed',\n) {}\n\n/**\n * Tagged error raised when a plugin exceeds its configured load or activation\n * timeout. The plugin manager records the failure on the `failed` atom and\n * auto-disables the plugin so that one stuck remote does not stall app boot.\n * `context.id` is the plugin id, `context.phase` is `'load'` or `'activation'`.\n */\nexport class PluginTimeoutError extends BaseError.extend('PluginTimeoutError', 'Plugin operation timed out') {}\n\n/** Phase of the plugin lifecycle in which the failure was observed. */\nexport type PluginFailurePhase = 'load' | 'activation';\n\n/** Why the plugin entered a failed state. */\nexport type PluginFailureReason = 'timeout' | 'error';\n\n/**\n * Record of a plugin that failed to load or activate. Surfaced via the\n * {@link PluginManager.failed} atom so registry / UI consumers can flag\n * unhealthy plugins (e.g. a remote host that has gone offline) rather than\n * leaving the app in a half-broken state.\n */\nexport type PluginFailure = {\n readonly id: string;\n readonly phase: PluginFailurePhase;\n readonly reason: PluginFailureReason;\n readonly error: Error;\n /** `Date.now()` when the failure was recorded. */\n readonly timestamp: number;\n};\n\n/** Default deadline for resolving a lazy plugin's dynamic import. */\nconst DEFAULT_LOAD_TIMEOUT = Duration.seconds(30);\n\n/** Default deadline for a single module's `activate()` body. */\nconst DEFAULT_ACTIVATION_TIMEOUT = Duration.seconds(30);\n\n/**\n * Identifier denoting a Manager.\n */\nexport const ManagerTypeId: unique symbol = Symbol.for('@dxos/app-framework/Manager');\nexport type ManagerTypeId = typeof ManagerTypeId;\n\n/**\n * Loader result that carries optional metadata about how the plugin was sourced.\n *\n * `dev: true` marks a plugin as session-only and triggers shadow-on-id-collision\n * inside the manager: if a plugin with the same id is already registered (a\n * builtin, or a previously-installed plugin from the registry), the dev plugin\n * temporarily takes over that id slot. The original is restored when the dev\n * plugin is removed (or on page reload, since dev plugins aren't persisted).\n */\nexport type LoadedPlugin = {\n plugin: Plugin.Plugin;\n /** True when the plugin came from a dev source. See type doc for semantics. */\n dev?: boolean;\n};\n\nexport type ManagerOptions = {\n pluginLoader: (id: string) => Effect.Effect<LoadedPlugin, Error>;\n plugins?: Plugin.Plugin[];\n enabled?: string[];\n registry?: Registry.Registry;\n /**\n * Backend for the plugin registry catalog. When omitted the manager exposes a\n * no-op `pluginRegistry` (empty list, no versions endpoint). Implementations\n * live in app-framework alongside the interface (e.g.\n * `EdgeRegistryPluginProvider`); the host app instantiates one and passes it in.\n */\n pluginRegistryProvider?: PluginRegistry.PluginProvider;\n /**\n * Hook called when a plugin is removed via {@link PluginManager.remove}. Used by the\n * host app to clean up persisted state (e.g. evict offline-cached plugin assets).\n * Failures are logged and swallowed; removal still succeeds even if the hook fails.\n */\n onRemove?: (id: string) => Effect.Effect<void, unknown>;\n /**\n * Maximum time allowed for a lazy plugin's dynamic `import()` to resolve.\n * Plugins that exceed this are flagged on the {@link PluginManager.failed}\n * atom and auto-disabled so a stuck remote host can't stall app boot.\n * Defaults to 30 seconds; pass `Duration.infinity` to disable.\n */\n loadTimeout?: Duration.DurationInput;\n /**\n * Maximum time allowed for a single module's `activate()` Effect to settle.\n * Modules that exceed this fail with {@link PluginTimeoutError}; the owning\n * plugin is recorded on `failed` and auto-disabled. Defaults to 30 seconds;\n * pass `Duration.infinity` to disable.\n */\n activationTimeout?: Duration.DurationInput;\n};\n\nexport type ActivationMessage = {\n event: string;\n state: 'activating' | 'activated' | 'error';\n /** Module ID when the message pertains to a specific module activation. */\n module?: string;\n error?: Error;\n};\n\n/**\n * Interface for the Plugin Manager.\n */\nexport interface PluginManager {\n readonly [ManagerTypeId]: ManagerTypeId;\n readonly activation: PubSub.PubSub<ActivationMessage>;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.Registry;\n /**\n * Cached registry catalog state plus pass-throughs for `listVersions` /\n * `getPlugin`. Always present — the host supplies a `pluginRegistryProvider`\n * via {@link ManagerOptions} for real backends, or it falls back to a no-op\n * implementation that yields an empty catalog.\n */\n readonly pluginRegistry: PluginRegistry.Manager;\n\n readonly plugins: Atom.Atom<readonly Plugin.Plugin[]>;\n readonly core: Atom.Atom<readonly string[]>;\n readonly enabled: Atom.Atom<readonly string[]>;\n readonly modules: Atom.Atom<readonly Plugin.PluginModule[]>;\n readonly active: Atom.Atom<readonly string[]>;\n readonly eventsFired: Atom.Atom<readonly string[]>;\n readonly pendingReset: Atom.Atom<readonly string[]>;\n /**\n * Plugins that failed to load or activate. Subscribers (e.g. the registry\n * UI) can use this to flag unhealthy entries; a plugin id appears here at\n * most once with its most recent failure.\n */\n readonly failed: Atom.Atom<readonly PluginFailure[]>;\n /**\n * Ids of currently-registered plugins that came from a dev source (loaded\n * via {@link LoadedPlugin} with `dev: true`). Subscribers can use this to\n * badge dev-overridden plugins or to derive the id of the active dev plugin\n * for an \"uninstall dev plugin\" affordance.\n */\n readonly devPluginIds: Atom.Atom<readonly string[]>;\n\n getPlugins(): readonly Plugin.Plugin[];\n getCore(): readonly string[];\n getEnabled(): readonly string[];\n getModules(): readonly Plugin.PluginModule[];\n getActive(): readonly string[];\n getEventsFired(): readonly string[];\n getPendingReset(): readonly string[];\n getFailed(): readonly PluginFailure[];\n getDevPluginIds(): readonly string[];\n\n /**\n * Clears the failure record for a plugin so it can be retried. Returns\n * whether a failure record existed and was removed.\n */\n clearFailure(id: string): boolean;\n\n /**\n * Loads a plugin via the plugin loader and registers it without enabling it.\n * Returns the loaded plugin so callers can enable it by its canonical id\n * (which may differ from the locator used to load it, e.g. URL loaders).\n */\n add(id: string): Effect.Effect<Plugin.Plugin, Error>;\n\n /**\n * Enables a plugin.\n *\n * Default behavior auto-resolves the plugin's declared `dependsOn` closure:\n * missing entries that exist in the plugin registry catalog are installed via\n * {@link add}, then enabled in dependency-first order. Set `resolveDependencies`\n * to `false` to enable only the named plugin and skip the closure walk\n * entirely — useful when substituting an alternative plugin that satisfies\n * the dependent's capability needs in its own way.\n */\n enable(id: string, opts?: { resolveDependencies?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Removes a plugin from the manager (disables then unregisters).\n *\n * Honors the same cascade option as {@link disable}.\n */\n remove(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Disables a plugin.\n *\n * By default, cascades to currently-enabled dependents (transitively, leaves\n * first) so disabling a depended-upon plugin never leaves its dependents\n * stranded. Pass `cascade: false` to disable only the named plugin and leave\n * its dependents enabled-but-broken — VS Code-style disable parity for\n * callers that want the escape hatch (e.g. when swapping in an alternative\n * implementation that satisfies the dependents' needs in its own way).\n *\n * Fails with {@link Plugin.PluginDependencyError} (`reason: 'core-dependent'`)\n * when cascading would require disabling a core plugin; UI flows should\n * surface their own confirmation before calling `disable` with the default.\n */\n disable(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error>;\n\n /**\n * Returns the plugin ids that the given plugin declares as dependencies.\n *\n * Walks `meta.dependsOn` from both registered plugins and the plugin registry\n * catalog so callers can preview the closure for a plugin that isn't yet\n * installed. With `transitive: true` (default), returns the full dependency\n * closure in dependency-first order (deps before dependents). Without it,\n * returns the direct declarations only.\n */\n getDependencies(id: string, opts?: { transitive?: boolean }): readonly string[];\n\n /**\n * Returns the plugin ids that declare the given plugin as a dependency.\n *\n * Walks `meta.dependsOn` over registered plugins. With `transitive: true`\n * (default), returns the full reverse closure. With `enabledOnly: true`,\n * filters to currently-enabled dependents — used by UI flows to preview what\n * a cascading disable would touch.\n */\n getDependents(id: string, opts?: { transitive?: boolean; enabledOnly?: boolean }): readonly string[];\n // TODO(wittjosiah): Improve error typing.\n activate(\n event: ActivationEvent.ActivationEvent | string,\n params?: { before?: string; after?: string },\n ): Effect.Effect<boolean, Error>;\n deactivate(id: string): Effect.Effect<boolean, Error>;\n reset(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error>;\n\n /**\n * Shuts down the manager by deactivating all active modules in reverse activation order,\n * clearing all capabilities, and resetting lifecycle bookkeeping.\n * Plugins, core, enabled, and modules remain intact so the manager can be reused.\n */\n shutdown(): Effect.Effect<boolean, Error>;\n}\n\n/**\n * Type guard to check if a value is a PluginManager.\n */\nexport const isManager = (value: unknown): value is PluginManager => {\n return typeof value === 'object' && value !== null && ManagerTypeId in value;\n};\n\n/**\n * Internal implementation of PluginManager.\n */\nclass ManagerImpl implements PluginManager {\n readonly [ManagerTypeId]: ManagerTypeId = ManagerTypeId;\n readonly activation = Effect.runSync(PubSub.unbounded<ActivationMessage>());\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.Registry;\n readonly pluginRegistry: PluginRegistry.Manager;\n\n private readonly _pluginsAtom: Atom.Writable<Plugin.Plugin[]>;\n private readonly _coreAtom: Atom.Writable<string[]>;\n private readonly _enabledAtom: Atom.Writable<string[]>;\n private readonly _modulesAtom: Atom.Writable<Plugin.PluginModule[]>;\n private readonly _activeAtom: Atom.Writable<string[]>;\n private readonly _eventsFiredAtom: Atom.Writable<string[]>;\n private readonly _pendingResetAtom: Atom.Writable<string[]>;\n private readonly _failedAtom: Atom.Writable<PluginFailure[]>;\n private readonly _pluginLoader: ManagerOptions['pluginLoader'];\n private readonly _onRemove: ManagerOptions['onRemove'];\n private readonly _loadTimeout: Duration.DurationInput;\n private readonly _activationTimeout: Duration.DurationInput;\n private readonly _capabilities = new Map<string, Capability.Any[]>();\n private readonly _moduleMemoMap = new Map<Plugin.PluginModule['id'], Deferred.Deferred<Capability.Any[], Error>>();\n private readonly _moduleSemaphores = new Map<Plugin.PluginModule['id'], Effect.Semaphore>();\n // Coalesces concurrent `_resolveLazyPlugin` calls per plugin id. Without\n // this, two callers entering `enable(id)` before the swap completes would\n // each invoke `mod.default(options)` and produce distinct module objects,\n // defeating `_addModule`'s reference-equality dedupe and racing the\n // `_pluginsAtom` swap.\n private readonly _resolvingPlugins = new Map<string, Deferred.Deferred<Plugin.Plugin, Plugin.LazyPluginError>>();\n // Tracks dev-source plugins (loaded via a Vite dev server) keyed by id.\n // When `shadow` is present, the entry has displaced an existing plugin —\n // `remove` reinstates it and re-enables iff `wasEnabled`. Entries without a\n // shadow are dev plugins with no underlying registry/builtin to restore.\n // The atom mirrors the map's keys for UI subscribers (they don't need the\n // shadow internals); the two stay in sync via {@link _markDev}/{@link _unmarkDev}.\n private readonly _devPlugins = new Map<string, { shadow?: { plugin: Plugin.Plugin; wasEnabled: boolean } }>();\n private readonly _devPluginIdsAtom: Atom.Writable<string[]>;\n private readonly _activatingEvents = Effect.runSync(Ref.make<string[]>([]));\n private readonly _activatingModules = Effect.runSync(Ref.make<string[]>([]));\n private readonly _inFlightFibers = Effect.runSync(Ref.make<Array<Fiber.Fiber<unknown, unknown>>>([]));\n private readonly _shutdownSemaphore = Effect.runSync(Effect.makeSemaphore(1));\n private readonly _shuttingDown = Effect.runSync(Ref.make(false));\n // Tracks the constructor-launched core/enabled `enable()` calls so that\n // `activate` can wait for module registration before dispatching events.\n // Lazy plugins make `enable` asynchronous (a dynamic `import()` happens\n // inside it), so without this synchronization an `activate` triggered\n // immediately after `make` could fire on an empty module set. Failures\n // are wrapped in `PluginInitializationError` so awaiters get a tagged\n // error rather than the wide `Error` produced by the underlying chain.\n private readonly _initialization = Effect.runSync(Deferred.make<void, PluginInitializationError>());\n\n constructor({\n pluginLoader,\n plugins = [],\n enabled = [],\n registry,\n pluginRegistryProvider,\n onRemove,\n loadTimeout = DEFAULT_LOAD_TIMEOUT,\n activationTimeout = DEFAULT_ACTIVATION_TIMEOUT,\n }: ManagerOptions) {\n // Core plugins are derived from `meta.tags.includes('system')`; the set is\n // a snapshot of the initial `plugins` array (later `add()` calls do not\n // promote plugins to core).\n const core: string[] = plugins.filter(({ meta }) => meta.tags?.includes('system')).map(({ meta }) => meta.id);\n this.registry = registry ?? Registry.make();\n this.capabilities = CapabilityManager.make({\n registry: this.registry,\n });\n this.pluginRegistry = new PluginRegistry.Manager(pluginRegistryProvider, this.registry);\n\n this._pluginLoader = pluginLoader;\n this._onRemove = onRemove;\n this._loadTimeout = loadTimeout;\n this._activationTimeout = activationTimeout;\n this._pluginsAtom = Atom.make(plugins).pipe(Atom.keepAlive);\n this._coreAtom = Atom.make(core).pipe(Atom.keepAlive);\n this._enabledAtom = Atom.make(enabled).pipe(Atom.keepAlive);\n this._modulesAtom = Atom.make<Plugin.PluginModule[]>([]).pipe(Atom.keepAlive);\n this._activeAtom = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this._eventsFiredAtom = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this._pendingResetAtom = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n this._failedAtom = Atom.make<PluginFailure[]>([]).pipe(Atom.keepAlive);\n this._devPluginIdsAtom = Atom.make<string[]>([]).pipe(Atom.keepAlive);\n plugins.forEach((plugin) => this._addPlugin(plugin));\n // Dedupe before mapping to `enable` — `core` and `enabled` may overlap (an\n // app-supplied plugin can be in both), and concurrent `enable(id)` calls\n // for the same id are not idempotent (each would re-run the lazy resolve\n // and double-register modules). `new Set([...])` preserves first-seen\n // order which matches the natural core-before-enabled precedence.\n const initialIds = [...new Set([...core, ...enabled])];\n void Effect.all(initialIds.map((id) => this.enable(id)))\n .pipe(\n Effect.mapError((cause) => new PluginInitializationError({ cause })),\n Effect.tap(() => Deferred.succeed(this._initialization, undefined)),\n Effect.tapErrorCause((cause) => Deferred.failCause(this._initialization, cause)),\n )\n .pipe(EffectEx.runAndForwardErrors);\n }\n\n get plugins(): Atom.Atom<readonly Plugin.Plugin[]> {\n return this._pluginsAtom;\n }\n\n get core(): Atom.Atom<readonly string[]> {\n return this._coreAtom;\n }\n\n /**\n * Ids of plugins that are currently enabled.\n */\n get enabled(): Atom.Atom<readonly string[]> {\n return this._enabledAtom;\n }\n\n /**\n * Modules of plugins which are currently enabled.\n */\n get modules(): Atom.Atom<readonly Plugin.PluginModule[]> {\n return this._modulesAtom;\n }\n\n /**\n * Ids of modules which are currently active.\n */\n get active(): Atom.Atom<readonly string[]> {\n return this._activeAtom;\n }\n\n /**\n * Ids of events which have been fired.\n */\n get eventsFired(): Atom.Atom<readonly string[]> {\n return this._eventsFiredAtom;\n }\n\n /**\n * Ids of modules which are pending reset.\n */\n get pendingReset(): Atom.Atom<readonly string[]> {\n return this._pendingResetAtom;\n }\n\n /**\n * Plugins that failed to load or activate.\n */\n get failed(): Atom.Atom<readonly PluginFailure[]> {\n return this._failedAtom;\n }\n\n /**\n * Ids of currently-registered plugins that came from a dev source.\n */\n get devPluginIds(): Atom.Atom<readonly string[]> {\n return this._devPluginIdsAtom;\n }\n\n getPlugins(): readonly Plugin.Plugin[] {\n return this._get(this._pluginsAtom);\n }\n\n getCore(): readonly string[] {\n return this._get(this._coreAtom);\n }\n\n getEnabled(): readonly string[] {\n return this._get(this._enabledAtom);\n }\n\n getModules(): readonly Plugin.PluginModule[] {\n return this._get(this._modulesAtom);\n }\n\n getActive(): readonly string[] {\n return this._get(this._activeAtom);\n }\n\n getEventsFired(): readonly string[] {\n return this._get(this._eventsFiredAtom);\n }\n\n getPendingReset(): readonly string[] {\n return this._get(this._pendingResetAtom);\n }\n\n getFailed(): readonly PluginFailure[] {\n return this._get(this._failedAtom);\n }\n\n getDevPluginIds(): readonly string[] {\n return this._get(this._devPluginIdsAtom);\n }\n\n /**\n * Marks `id` as dev-sourced. If the plugin displaced an existing one, pass\n * the shadow snapshot so `remove` can restore it. Repeat calls (e.g. a dev\n * plugin reload) preserve the original shadow target — restoration always\n * unwinds back to the real underlying plugin, never an intermediate dev build.\n */\n private _markDev(id: string, shadow?: { plugin: Plugin.Plugin; wasEnabled: boolean }): void {\n if (this._devPlugins.has(id)) {\n return;\n }\n this._devPlugins.set(id, { shadow });\n this._update(this._devPluginIdsAtom, (ids) => (ids.includes(id) ? ids : [...ids, id]));\n }\n\n /** Drops the dev-plugin entry and returns its shadow data (if any) for restoration. */\n private _unmarkDev(id: string): { plugin: Plugin.Plugin; wasEnabled: boolean } | undefined {\n const entry = this._devPlugins.get(id);\n this._devPlugins.delete(id);\n this._update(this._devPluginIdsAtom, (ids) => ids.filter((existing) => existing !== id));\n return entry?.shadow;\n }\n\n getDependencies(id: string, opts?: { transitive?: boolean }): readonly string[] {\n const transitive = opts?.transitive !== false;\n if (!transitive) {\n return this._directDependencies(id);\n }\n const walk = this._computeDependencyClosure(id);\n // Drop the target itself; callers asked for its dependencies, not the\n // closure including the root.\n return walk.order.filter((depId) => depId !== id);\n }\n\n getDependents(id: string, opts?: { transitive?: boolean; enabledOnly?: boolean }): readonly string[] {\n return this._collectDependents(id, {\n transitive: opts?.transitive !== false,\n enabledOnly: opts?.enabledOnly === true,\n });\n }\n\n clearFailure(id: string): boolean {\n const current = this._get(this._failedAtom);\n if (!current.some((failure) => failure.id === id)) {\n return false;\n }\n this._set(\n this._failedAtom,\n current.filter((failure) => failure.id !== id),\n );\n return true;\n }\n\n /**\n * Adds a plugin to the manager via the plugin loader.\n * The plugin is registered but not enabled; call `enable` separately to activate it.\n * @param id The id of the plugin.\n */\n add(id: string): Effect.Effect<Plugin.Plugin, Error> {\n return Effect.gen(this, function* () {\n log('add plugin', { id });\n const { plugin, dev = false } = yield* this._pluginLoader(id);\n const pluginId = plugin.meta.id;\n const existing = this._getPlugin(pluginId);\n\n if (dev && existing && existing !== plugin) {\n // Shadow path: a plugin with this id is already registered (a builtin,\n // a registry install, or a previous dev load). Disable it, stash it,\n // and swap the dev plugin into the same id slot. The dialog will call\n // `enable(pluginId)` next, which activates the dev plugin's modules.\n // `_markDev` is a no-op when the id is already tracked, so a dev-plugin\n // reload (after editing source) keeps the *original* shadow target —\n // removal restores the real underlying plugin, not an intermediate build.\n const wasEnabled = this._get(this._enabledAtom).includes(pluginId);\n if (wasEnabled) {\n yield* this.disable(pluginId);\n }\n this._markDev(pluginId, { plugin: existing, wasEnabled });\n this._update(this._pluginsAtom, (plugins) => plugins.map((p) => (p.meta.id === pluginId ? plugin : p)));\n } else {\n this._addPlugin(plugin);\n if (dev) {\n this._markDev(pluginId);\n }\n }\n\n return plugin;\n });\n }\n\n /**\n * Enables a plugin.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.enable}.\n */\n enable(id: string, opts?: { resolveDependencies?: boolean }): Effect.Effect<boolean, Error> {\n const resolveDependencies = opts?.resolveDependencies !== false;\n return Effect.gen(this, function* () {\n log('enable plugin', { id, resolveDependencies });\n\n if (!resolveDependencies) {\n return yield* this._enableOne(id);\n }\n\n // If the root id is unknown to both the registered set and the catalog,\n // fall back to the silent `_enableOne` path (which returns `false`).\n // This preserves the prior contract for persisted `enabled` entries\n // whose plugins are no longer bundled, instead of recording a confusing\n // \"missing self-dependency\" failure.\n if (!this._getPlugin(id) && !this._getCatalogEntry(id)) {\n return yield* this._enableOne(id);\n }\n\n // Compute the transitive closure across registered plugins and catalog\n // entries. Missing or cyclic entries are recorded as failures and the\n // target plugin is left disabled.\n const walk = this._computeDependencyClosure(id);\n if (walk.cycle) {\n this._recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'cycle', path: walk.cycle } }),\n );\n return false;\n }\n if (walk.missing.length > 0) {\n this._recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'missing', missing: walk.missing } }),\n );\n return false;\n }\n\n // Install any catalog-only entries before enabling them. `add` may also\n // discover further declared deps once the plugin's real meta is loaded;\n // we re-walk after each install to absorb those.\n let queue = walk.toInstall.slice();\n const installed = new Set<string>();\n while (queue.length > 0) {\n const next = queue.shift()!;\n if (installed.has(next) || this._getPlugin(next)) {\n continue;\n }\n const installResult = yield* this.add(next).pipe(Effect.either);\n if (installResult._tag === 'Left') {\n this._recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({\n context: { id, reason: 'install-failed', dependency: next },\n cause: installResult.left,\n }),\n );\n return false;\n }\n installed.add(next);\n const rewalk = this._computeDependencyClosure(id);\n if (rewalk.cycle) {\n this._recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'cycle', path: rewalk.cycle } }),\n );\n return false;\n }\n if (rewalk.missing.length > 0) {\n this._recordFailure(\n id,\n 'load',\n new Plugin.PluginDependencyError({ context: { id, reason: 'missing', missing: rewalk.missing } }),\n );\n return false;\n }\n queue = rewalk.toInstall.filter((depId) => !installed.has(depId));\n }\n\n // Enable in dependency-first order. `_enableOne` is idempotent on the\n // enabled atom so previously-enabled deps short-circuit.\n const order = this._computeDependencyClosure(id).order;\n let succeeded = false;\n for (const depId of order) {\n const ok = yield* this._enableOne(depId);\n if (depId === id) {\n succeeded = ok;\n }\n }\n return succeeded;\n });\n }\n\n /**\n * Enables a single plugin without consulting its declared dependencies.\n * Used by {@link enable} as the leaf step after closure resolution, and\n * directly when callers pass `{ resolveDependencies: false }`.\n *\n * The underlying operations (`_addModule`, `_setPendingResetByModule`,\n * `activate`) are all idempotent, so this method is safe to call multiple\n * times for the same id. The constructor's bootstrap path relies on this:\n * the persisted `enabled` ids are written into `_enabledAtom` up front, so\n * the very first `enable(id)` for those plugins sees `alreadyEnabled`-style\n * state but still needs to perform the module registration and activation.\n */\n private _enableOne(id: string): Effect.Effect<boolean, Error> {\n return Effect.gen(this, function* () {\n const stub = this._getPlugin(id);\n if (!stub) {\n return false;\n }\n\n // Clear any prior failure record so a retry starts from a clean slate.\n // The failure stays on the atom only if this attempt also fails.\n this.clearFailure(id);\n\n const plugin = yield* this._resolveLazyPlugin(stub);\n\n this._update(this._enabledAtom, (enabled) => (enabled.includes(id) ? enabled : [...enabled, id]));\n\n plugin.modules.forEach((module) => {\n this._addModule(module);\n this._setPendingResetByModule(module);\n });\n\n log('pending reset', { events: [...this.getPendingReset()] });\n yield* Effect.all(\n this.getPendingReset().map((event) => this.activate(event)),\n { concurrency: 'unbounded' },\n );\n\n return true;\n });\n }\n\n /**\n * Resolves a lazy plugin stub (returned by {@link Plugin.lazy}) to its\n * loaded form and swaps it into `_pluginsAtom`. Returns the input unchanged\n * when the plugin is already resolved, so callers can `yield*` this\n * unconditionally. The lazy stub carries `meta` synchronously but its\n * `modules` list is empty until the loader resolves; the swap ensures\n * subsequent enable/disable operations see the resolved plugin.\n *\n * Concurrent calls for the same id are coalesced via `_resolvingPlugins`:\n * the first caller starts the resolution, every subsequent caller awaits\n * the same `Deferred`. On failure we publish a `lazy:<id>` error message\n * and skip the atom swap so the failure is observable to the activation\n * subscriber and a retry can be attempted.\n */\n private _resolveLazyPlugin(plugin: Plugin.Plugin): Effect.Effect<Plugin.Plugin, Plugin.LazyPluginError> {\n return Effect.gen(this, function* () {\n if (!Plugin.isLazy(plugin)) {\n return plugin;\n }\n const id = plugin.meta.id;\n\n const existing = this._resolvingPlugins.get(id);\n if (existing) {\n return yield* Deferred.await(existing);\n }\n const deferred = yield* Deferred.make<Plugin.Plugin, Plugin.LazyPluginError>();\n this._resolvingPlugins.set(id, deferred);\n\n return yield* Effect.gen(this, function* () {\n log('resolving lazy plugin', { id });\n yield* PubSub.publish(this.activation, { event: '', state: 'activating', module: `lazy:${id}` });\n const resolvedPlugin = yield* Plugin.resolveLazy(plugin).pipe(\n // Cap how long a remote import can hang. Without this the host can\n // sit on a pending dynamic `import()` indefinitely if the plugin's\n // server is unreachable, which stalls every caller awaiting\n // `enable(id)` and (transitively) the manager's initialization.\n Effect.timeoutFail({\n duration: this._loadTimeout,\n onTimeout: () =>\n new Plugin.LazyPluginError({\n context: { id, reason: 'load-failed' },\n cause: new PluginTimeoutError({ context: { id, phase: 'load' as PluginFailurePhase } }),\n }),\n }),\n );\n this._update(this._pluginsAtom, (plugins) => plugins.map((p) => (p.meta.id === id ? resolvedPlugin : p)));\n yield* PubSub.publish(this.activation, { event: '', state: 'activated', module: `lazy:${id}` });\n return resolvedPlugin;\n }).pipe(\n Effect.tapError((error) =>\n Effect.gen(this, function* () {\n yield* PubSub.publish(this.activation, { event: '', state: 'error', module: `lazy:${id}`, error });\n this._recordFailure(id, 'load', error);\n this._scheduleAutoDisable(id);\n }),\n ),\n Effect.tap((value) => Deferred.succeed(deferred, value)),\n Effect.tapErrorCause((cause) => Deferred.failCause(deferred, cause)),\n Effect.ensuring(Effect.sync(() => this._resolvingPlugins.delete(id))),\n );\n });\n }\n\n /**\n * Removes a plugin from the manager.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.remove}.\n */\n remove(id: string, opts?: { cascade?: boolean }): Effect.Effect<boolean, Error> {\n return Effect.gen(this, function* () {\n log('remove plugin', { id });\n const wasDev = this._devPlugins.has(id);\n const disabled = yield* this.disable(id, opts);\n if (!disabled) {\n return false;\n }\n\n this._removePlugin(id);\n if (this._onRemove) {\n this._runForkedFiber(\n this._onRemove(id).pipe(\n Effect.tapError((error) => Effect.sync(() => log.warn('plugin remove hook failed', { id, error }))),\n Effect.ignore,\n ),\n );\n }\n\n // If a dev plugin was shadowing an existing plugin, reinstate the\n // original now that the dev plugin is gone. Re-enable only if the\n // original was enabled at shadow time — preserving the user's intent\n // for plugins they had explicitly disabled before iterating on a dev\n // build.\n if (wasDev) {\n const shadow = this._unmarkDev(id);\n if (shadow) {\n this._addPlugin(shadow.plugin);\n if (shadow.wasEnabled) {\n yield* this.enable(id);\n }\n }\n }\n return true;\n });\n }\n\n /**\n * Disables a plugin.\n * @param id The id of the plugin.\n * @param opts See {@link PluginManager.disable}.\n */\n disable(id: string, { cascade = true }: { cascade?: boolean } = {}): Effect.Effect<boolean, Error> {\n return Effect.gen(this, function* () {\n log('disable plugin', { id, cascade });\n if (this._get(this._coreAtom).includes(id)) {\n return false;\n }\n\n const plugin = this._getPlugin(id);\n if (!plugin) {\n return false;\n }\n\n if (cascade) {\n const enabledDependents = this._collectDependents(id, { transitive: true, enabledOnly: true });\n if (enabledDependents.length > 0) {\n const coreDependent = enabledDependents.find((dependentId) =>\n this._get(this._coreAtom).includes(dependentId),\n );\n if (coreDependent) {\n return yield* Effect.fail(\n new Plugin.PluginDependencyError({\n context: { id, reason: 'core-dependent', coreDependent },\n }),\n );\n }\n // Disable transitive dependents first (leaves before root). The\n // walk returns them in dependents-before-deps order — exactly what\n // we want for teardown.\n for (const dependentId of enabledDependents) {\n yield* this._disableOne(dependentId);\n }\n }\n }\n\n yield* this._disableOne(id);\n return true;\n });\n }\n\n /**\n * Disables a single plugin without consulting its dependents. Used by\n * {@link disable} after the dependents pass has run (or been skipped via\n * `cascade: false`).\n */\n private _disableOne(id: string): Effect.Effect<boolean, Error> {\n return Effect.gen(this, function* () {\n if (this._get(this._coreAtom).includes(id)) {\n return false;\n }\n const plugin = this._getPlugin(id);\n if (!plugin) {\n return false;\n }\n const enabledIndex = this._get(this._enabledAtom).findIndex((enabled) => enabled === id);\n if (enabledIndex !== -1) {\n this._update(this._enabledAtom, (enabled) => enabled.filter((item) => item !== id));\n yield* this.deactivate(id);\n plugin.modules.forEach((module) => {\n this._removeModule(module.id);\n });\n }\n return true;\n });\n }\n\n /**\n * Activates plugins based on the activation event.\n * @param event The activation event.\n * @returns Whether the activation was successful.\n */\n activate(\n event: ActivationEvent.ActivationEvent | string,\n params?: { before?: string; after?: string },\n ): Effect.Effect<boolean, Error> {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n return Effect.gen(this, function* () {\n if (yield* this._isShuttingDown()) {\n log('skipping activation during shutdown', { key, ...params });\n return false;\n }\n\n // Wait for the constructor's core/enabled `enable()` chain — including\n // any async dynamic imports for lazy plugins — to finish registering\n // modules. Without this, dispatching to an empty module set is the\n // observable symptom of the race.\n yield* Deferred.await(this._initialization);\n\n return yield* Effect.withFiberRuntime<boolean, Error>((fiber) =>\n this._activateEvent(key, params, fiber).pipe(\n together(\n Effect.sleep(Duration.seconds(15)).pipe(\n Effect.andThen(Effect.sync(() => log.warn('event activation is taking a long time', { event: key }))),\n ),\n ),\n Performance.addTrackEntry({\n name: typeof event === 'string' ? event : ActivationEvent.eventKey(event),\n devtools: {\n dataType: 'track-entry',\n track: 'Event Activation',\n trackGroup: 'Composer',\n color: 'primary',\n },\n }),\n ),\n );\n });\n }\n\n /**\n * Deactivates all of the modules for a plugin.\n * @param id The id of the plugin.\n * @returns Whether the deactivation was successful.\n */\n deactivate(id: string): Effect.Effect<boolean, Error> {\n return Effect.gen(this, function* () {\n const plugin = this._getPlugin(id);\n if (!plugin) {\n return false;\n }\n\n const modules = plugin.modules;\n const results = yield* Effect.all(\n modules.map((module) => this._deactivateModule(module)),\n { concurrency: 'unbounded' },\n );\n return results.every((result) => result);\n });\n }\n\n /**\n * Re-activates the modules that were activated by the event.\n * @param event The activation event.\n * @returns Whether the reset was successful.\n */\n reset(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error> {\n return Effect.gen(this, function* () {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n log('reset', { key });\n const modules = this._getActiveModulesByEvent(key);\n const results = yield* Effect.all(\n modules.map((module) => this._deactivateModule(module)),\n { concurrency: 'unbounded' },\n );\n\n if (results.every((result) => result)) {\n return yield* this.activate(key);\n } else {\n return false;\n }\n });\n }\n\n shutdown(): Effect.Effect<boolean, Error> {\n return this._shutdownSemaphore.withPermits(1)(\n Effect.gen(this, function* () {\n yield* Ref.set(this._shuttingDown, true);\n log('shutdown');\n\n yield* this._interruptInFlightActivations();\n\n const activeIds = [...this._get(this._activeAtom)].reverse();\n const allModules = this._get(this._modulesAtom);\n const modulesToDeactivate = activeIds\n .map((id) => allModules.find((module) => module.id === id))\n .filter((module): module is Plugin.PluginModule => module != null);\n\n for (const module of modulesToDeactivate) {\n yield* this._deactivateModule(module);\n }\n\n this._set(this._eventsFiredAtom, []);\n this._set(this._pendingResetAtom, []);\n this._moduleMemoMap.clear();\n yield* Ref.set(this._activatingEvents, []);\n yield* Ref.set(this._activatingModules, []);\n\n log('shutdown complete');\n return true;\n }).pipe(Effect.ensuring(Ref.set(this._shuttingDown, false))),\n );\n }\n\n //\n // State helpers\n //\n\n private _get<T>(atom: Atom.Atom<T>): T {\n return this.registry.get(atom);\n }\n\n private _set<T>(atom: Atom.Writable<T>, value: T): void {\n this.registry.set(atom, value);\n }\n\n private _update<T>(atom: Atom.Writable<T>, updater: (current: T) => T): void {\n this._set(atom, updater(this._get(atom)));\n }\n\n private _isShuttingDown(): Effect.Effect<boolean> {\n return Ref.get(this._shuttingDown);\n }\n\n private _getPlugin(id: string): Plugin.Plugin | undefined {\n return this._get(this._pluginsAtom).find((plugin) => plugin.meta.id === id);\n }\n\n private _getPluginIdForModule(moduleId: string): string | undefined {\n return this._get(this._pluginsAtom).find((plugin) => plugin.modules.some((module) => module.id === moduleId))?.meta\n .id;\n }\n\n /** Looks up an id in the cached registry catalog, returning the entry or `undefined`. */\n private _getCatalogEntry(id: string): PluginRegistry.Plugin | undefined {\n return this._get(this.pluginRegistry.plugins).entries.find((entry) => entry.id === id);\n }\n\n /**\n * Returns the direct `dependsOn` declarations for an id, drawing from the\n * registered plugin's meta when available and falling back to the registry\n * catalog entry. Unknown ids return an empty list (callers detect \"missing\"\n * separately).\n */\n private _directDependencies(id: string): string[] {\n const plugin = this._getPlugin(id);\n if (plugin) {\n return [...(plugin.meta.dependsOn ?? [])];\n }\n const catalog = this._getCatalogEntry(id);\n return catalog?.dependsOn ? [...catalog.dependsOn] : [];\n }\n\n /**\n * Computes the transitive dependency closure for an id.\n *\n * Walks {@link _directDependencies} (registered plugins ∪ catalog entries).\n * Returns:\n * - `order`: closure including the root in dependency-first topological order.\n * - `missing`: ids in the closure that are neither registered nor in the catalog.\n * - `toInstall`: ids in the closure that are in the catalog but not yet registered.\n * - `cycle`: when a cycle is detected, the cycle path; otherwise `undefined`.\n */\n private _computeDependencyClosure(id: string): {\n order: string[];\n missing: string[];\n toInstall: string[];\n cycle?: string[];\n } {\n const order: string[] = [];\n const visited = new Set<string>();\n const onStack = new Set<string>();\n const stackPath: string[] = [];\n const missing: string[] = [];\n const toInstall: string[] = [];\n let cycle: string[] | undefined;\n\n const knownIds = new Set<string>([\n ...this._get(this._pluginsAtom).map((plugin) => plugin.meta.id),\n ...this._get(this.pluginRegistry.plugins).entries.map((entry) => entry.id),\n ]);\n\n const visit = (currentId: string): void => {\n if (cycle) {\n return;\n }\n if (visited.has(currentId)) {\n return;\n }\n if (onStack.has(currentId)) {\n const cycleStart = stackPath.indexOf(currentId);\n cycle = [...stackPath.slice(cycleStart), currentId];\n return;\n }\n onStack.add(currentId);\n stackPath.push(currentId);\n\n if (!knownIds.has(currentId)) {\n missing.push(currentId);\n } else if (!this._getPlugin(currentId)) {\n toInstall.push(currentId);\n }\n\n for (const depId of this._directDependencies(currentId)) {\n visit(depId);\n if (cycle) {\n break;\n }\n }\n\n onStack.delete(currentId);\n stackPath.pop();\n if (!cycle) {\n visited.add(currentId);\n order.push(currentId);\n }\n };\n\n visit(id);\n return { order, missing, toInstall, cycle };\n }\n\n /**\n * Walks the reverse `dependsOn` edges across registered plugins. With\n * `enabledOnly`, filters the result to currently-enabled ids. Returns\n * dependents in dependents-before-deps order so callers (cascade-disable)\n * can iterate and tear down leaves first.\n */\n private _collectDependents(id: string, opts: { transitive: boolean; enabledOnly: boolean }): string[] {\n const direct = this._get(this._pluginsAtom)\n .filter((plugin) => plugin.meta.dependsOn?.some((dep) => dep === id))\n .map((plugin) => plugin.meta.id);\n\n if (!opts.transitive) {\n return opts.enabledOnly\n ? direct.filter((dependentId) => this._get(this._enabledAtom).includes(dependentId))\n : direct;\n }\n\n const result: string[] = [];\n const visited = new Set<string>();\n const visit = (currentId: string): void => {\n if (visited.has(currentId)) {\n return;\n }\n visited.add(currentId);\n const parents = this._get(this._pluginsAtom)\n .filter((plugin) => plugin.meta.dependsOn?.some((dep) => dep === currentId))\n .map((plugin) => plugin.meta.id);\n for (const parentId of parents) {\n visit(parentId);\n if (parentId !== id && !result.includes(parentId)) {\n result.push(parentId);\n }\n }\n };\n visit(id);\n\n return opts.enabledOnly\n ? result.filter((dependentId) => this._get(this._enabledAtom).includes(dependentId))\n : result;\n }\n\n /**\n * Records a failure for a plugin. Latest failure wins so the registry UI\n * always sees the most recent reason. Walks the `cause` chain when checking\n * for timeouts: lazy-load timeouts arrive wrapped in `LazyPluginError` (the\n * timeout is the cause), but the operator-visible reason should still be\n * `'timeout'`.\n */\n private _recordFailure(id: string, phase: PluginFailurePhase, error: Error): void {\n const reason: PluginFailureReason = isTimeoutCause(error) ? 'timeout' : 'error';\n const failure: PluginFailure = { id, phase, reason, error, timestamp: Date.now() };\n log.warn('plugin failed to activate', { id, phase, reason, error: error.message });\n this._update(this._failedAtom, (current) => [...current.filter((entry) => entry.id !== id), failure]);\n }\n\n /**\n * Fire-and-forget disable of a failed plugin. Forked because a failure can\n * happen mid-activation chain — yielding a `disable` inline would deadlock\n * on the shared semaphores. Core plugins are skipped (the host opted into\n * them being non-removable; the failure record is enough signal).\n */\n private _scheduleAutoDisable(id: string): void {\n if (import.meta.env.DEV && import.meta.env.MODE !== 'test') {\n // Transient HMR failures must not persist; skip auto-disable in dev server.\n return;\n }\n if (this._get(this._coreAtom).includes(id)) {\n return;\n }\n if (!this._get(this._enabledAtom).includes(id)) {\n return;\n }\n this._runForkedFiber(\n this.disable(id).pipe(\n Effect.tap(() => Effect.sync(() => log.error('plugin auto-disabled', { id }))),\n Effect.tapError((error) => Effect.sync(() => log.warn('auto-disable failed', { id, error }))),\n Effect.ignore,\n ),\n );\n }\n\n private _getActiveModules(): Plugin.PluginModule[] {\n const active = this._get(this._activeAtom);\n return this._get(this._modulesAtom).filter((module) => active.includes(module.id));\n }\n\n private _getInactiveModules(): Plugin.PluginModule[] {\n const active = this._get(this._activeAtom);\n return this._get(this._modulesAtom).filter((module) => !active.includes(module.id));\n }\n\n private _getActiveModulesByEvent(key: string): Plugin.PluginModule[] {\n return this._getActiveModules().filter((module) =>\n ActivationEvent.getEvents(module.activatesOn).map(ActivationEvent.eventKey).includes(key),\n );\n }\n\n private _getInactiveModulesByEvent(key: string): Plugin.PluginModule[] {\n return this._getInactiveModules().filter((module) =>\n ActivationEvent.getEvents(module.activatesOn).map(ActivationEvent.eventKey).includes(key),\n );\n }\n\n private _setPendingResetByModule(module: Plugin.PluginModule): void {\n const activationEvents = ActivationEvent.getEvents(module.activatesOn)\n .map(ActivationEvent.eventKey)\n .filter((key) => this._get(this._eventsFiredAtom).includes(key));\n\n const pendingReset = Array.fromIterable(new Set(activationEvents)).filter((event) => {\n const pending = this._get(this._pendingResetAtom);\n return !pending.includes(event);\n });\n if (pendingReset.length > 0) {\n log('pending reset', { events: pendingReset });\n this._update(this._pendingResetAtom, (current) => [...current, ...pendingReset]);\n }\n }\n\n private _clearPendingReset(key: string): void {\n const pendingIndex = this._get(this._pendingResetAtom).findIndex((event) => event === key);\n if (pendingIndex !== -1) {\n this._update(this._pendingResetAtom, (pending) => pending.filter((event) => event !== key));\n }\n }\n\n //\n // Fiber helpers\n //\n\n private _interruptInFlightActivations(): Effect.Effect<void> {\n return Effect.gen(this, function* () {\n const inFlightFibers = yield* Ref.get(this._inFlightFibers);\n yield* Effect.forEach(inFlightFibers, (fiber) => Fiber.interrupt(fiber), {\n concurrency: 'unbounded',\n });\n });\n }\n\n private _trackFiber(\n ref: Ref.Ref<Array<Fiber.Fiber<unknown, unknown>>>,\n fiber: Fiber.Fiber<unknown, unknown>,\n ): Effect.Effect<void> {\n return Ref.update(ref, (fibers) => [...fibers, fiber]);\n }\n\n private _untrackFiber(\n ref: Ref.Ref<Array<Fiber.Fiber<unknown, unknown>>>,\n fiber: Fiber.Fiber<unknown, unknown>,\n ): Effect.Effect<void> {\n return Ref.update(ref, (fibers) => fibers.filter((trackedFiber) => trackedFiber !== fiber));\n }\n\n /**\n * Spawns an effect on the default runtime and registers the resulting fiber in\n * `_inFlightFibers` so {@link shutdown} can interrupt it. Used from sync entry\n * points like {@link remove} where there is no enclosing Effect to fork from;\n * inside an Effect chain prefer the existing track/await/untrack pattern.\n */\n private _runForkedFiber<E>(effect: Effect.Effect<void, E>): void {\n const fiber = Effect.runFork(effect);\n Effect.runSync(this._trackFiber(this._inFlightFibers, fiber));\n Effect.runFork(Fiber.await(fiber).pipe(Effect.andThen(() => this._untrackFiber(this._inFlightFibers, fiber))));\n }\n\n //\n // Registration helpers\n //\n\n private _addPlugin(plugin: Plugin.Plugin): void {\n log('add plugin', { id: plugin.meta.id });\n // TODO(wittjosiah): Find a way to add a warning for duplicate plugins that doesn't cause log spam.\n this._update(this._pluginsAtom, (plugins) => (plugins.includes(plugin) ? plugins : [...plugins, plugin]));\n }\n\n private _removePlugin(id: string): void {\n log('remove plugin', { id });\n this._update(this._pluginsAtom, (plugins) => plugins.filter((plugin) => plugin.meta.id !== id));\n }\n\n private _addModule(module: Plugin.PluginModule): void {\n log('add module', { id: module.id });\n // TODO(wittjosiah): Find a way to add a warning for duplicate modules that doesn't cause log spam.\n this._update(this._modulesAtom, (modules) => (modules.includes(module) ? modules : [...modules, module]));\n }\n\n private _removeModule(id: string): void {\n log('remove module', { id });\n this._update(this._modulesAtom, (modules) => modules.filter((module) => module.id !== id));\n }\n\n //\n // Activation helpers\n //\n\n private _activateEvent(\n key: string,\n params: { before?: string; after?: string } | undefined,\n fiber: Fiber.Fiber<unknown, unknown>,\n ): Effect.Effect<boolean, Error> {\n return Effect.gen(this, function* () {\n yield* this._trackFiber(this._inFlightFibers, fiber);\n log('activating', { key, ...params });\n yield* Ref.update(this._activatingEvents, (activating) => Array.append(activating, key));\n this._clearPendingReset(key);\n\n const activatingEvents = yield* this._activatingEvents;\n const activatingModules = yield* this._activatingModules;\n const modules = this._getModulesForActivation(key, activatingEvents, activatingModules);\n if (modules.length === 0) {\n log('no modules to activate', { key });\n if (!this._get(this._eventsFiredAtom).includes(key)) {\n this._update(this._eventsFiredAtom, (events) => [...events, key]);\n }\n return false;\n }\n\n return yield* this._activateModulesForEvent(key, modules, activatingEvents);\n }).pipe(\n Effect.ensuring(\n Effect.all([\n this._untrackFiber(this._inFlightFibers, fiber),\n Ref.update(this._activatingEvents, (activating) => Array.filter(activating, (event) => event !== key)),\n ]),\n ),\n );\n }\n\n private _activateModulesForEvent(\n key: string,\n modules: Plugin.PluginModule[],\n activatingEvents: string[],\n ): Effect.Effect<boolean, Error> {\n const activatingModuleIds = modules.map((module) => module.id);\n return Effect.gen(this, function* () {\n yield* Ref.update(this._activatingModules, (activating) => Array.appendAll(activating, activatingModuleIds));\n\n log('activation wave', { event: key, modules: activatingModuleIds });\n performance.mark(`event:${key}:start`);\n yield* PubSub.publish(this.activation, { event: key, state: 'activating' });\n\n yield* this._activateRelatedEvents(key, this._getBeforeEvents(modules, activatingEvents), 'before');\n\n const capabilities = yield* this._loadCapabilitiesForModules(key, modules);\n yield* this._contributeCapabilitiesForModules(modules, capabilities);\n\n yield* this._activateRelatedEvents(key, this._getAfterEvents(modules, activatingEvents), 'after');\n\n if (!this._get(this._eventsFiredAtom).includes(key)) {\n this._update(this._eventsFiredAtom, (events) => [...events, key]);\n }\n\n performance.mark(`event:${key}:end`);\n performance.measure(`event:${key}`, `event:${key}:start`, `event:${key}:end`);\n yield* PubSub.publish(this.activation, { event: key, state: 'activated' });\n log('activated', { key });\n\n return true;\n }).pipe(\n Effect.ensuring(\n Ref.update(this._activatingModules, (activating) =>\n Array.filter(activating, (module) => !activatingModuleIds.includes(module)),\n ),\n ),\n );\n }\n\n private _getModulesForActivation(\n key: string,\n activatingEvents: string[],\n activatingModules: string[],\n ): Plugin.PluginModule[] {\n return this._getInactiveModulesByEvent(key).filter((module) => {\n const allOf = ActivationEvent.isAllOf(module.activatesOn);\n if (!allOf) {\n return true;\n }\n\n // Check to see if all of the events in the `allOf` have been fired.\n // An event can be considered \"fired\" if it is in the `eventsFired` list or if it is currently being activated.\n const events = ActivationEvent.getEvents(module.activatesOn).filter(\n (event) => ActivationEvent.eventKey(event) !== key,\n );\n return (\n events.every(\n (event) =>\n this._get(this._eventsFiredAtom).includes(ActivationEvent.eventKey(event)) ||\n activatingEvents.includes(ActivationEvent.eventKey(event)),\n ) && !activatingModules.includes(module.id)\n );\n });\n }\n\n private _getBeforeEvents(\n modules: Plugin.PluginModule[],\n activatingEvents: string[],\n ): ActivationEvent.ActivationEvent[] {\n return Function.pipe(\n modules,\n Array.flatMap((module) => module.firesBeforeActivation ?? []),\n HashSet.fromIterable,\n HashSet.toValues,\n Array.filter((event) => !activatingEvents.includes(ActivationEvent.eventKey(event))),\n );\n }\n\n private _getAfterEvents(\n modules: Plugin.PluginModule[],\n activatingEvents: string[],\n ): ActivationEvent.ActivationEvent[] {\n return Function.pipe(\n modules,\n Array.flatMap((module) => module.firesAfterActivation ?? []),\n HashSet.fromIterable,\n HashSet.toValues,\n Array.filter((event) => !activatingEvents.includes(ActivationEvent.eventKey(event))),\n );\n }\n\n private _activateRelatedEvents(\n key: string,\n events: ActivationEvent.ActivationEvent[],\n phase: 'before' | 'after',\n ): Effect.Effect<void, Error> {\n const logLabel = phase === 'before' ? 'firesBeforeActivation' : 'firesAfterActivation';\n const eventKey = phase === 'before' ? 'beforeEvents' : 'afterEvents';\n return Function.pipe(\n events,\n Array.map((event) => this.activate(event, phase === 'before' ? { before: key } : { after: key })),\n Effect.allWith({ concurrency: 'unbounded' }),\n together(\n Effect.sleep(Duration.seconds(10)).pipe(\n Effect.andThen(\n Effect.sync(() =>\n log.warn(`${logLabel} is taking a long time`, {\n event: key,\n [eventKey]: events.map(ActivationEvent.eventKey),\n }),\n ),\n ),\n ),\n ),\n Effect.asVoid,\n );\n }\n\n //\n // Module lifecycle helpers\n //\n\n private _loadCapabilitiesForModules(\n key: string,\n modules: Plugin.PluginModule[],\n ): Effect.Effect<Capability.Any[][], Error> {\n return Function.pipe(\n modules,\n Array.map((mod) => this._loadModule(mod, key)),\n Effect.allWith({ concurrency: 'unbounded' }),\n Effect.catchAll((error) => {\n return Effect.gen(this, function* () {\n yield* PubSub.publish(this.activation, { event: key, state: 'error', error });\n return yield* Effect.fail(error);\n });\n }),\n );\n }\n\n private _contributeCapabilitiesForModules(\n modules: Plugin.PluginModule[],\n capabilities: Capability.Any[][],\n ): Effect.Effect<void, Error> {\n return Function.pipe(\n modules,\n Array.zip(capabilities),\n Array.map(([module, capabilitySet]) => this._contributeCapabilities(module, capabilitySet)),\n // TODO(wittjosiah): This currently can't be run in parallel, and inserting\n // any yield between contributions (`Effect.yieldNow()`, `Effect.sleep(0)`)\n // races the `allOf` activation-event resolver — observed as a System\n // Error dialog on warm reloads. Contributions must stay strictly\n // synchronous within an event; React paint slots have to be found at\n // event boundaries higher up the call chain.\n Effect.all,\n Effect.asVoid,\n );\n }\n\n private _getModuleSemaphore(moduleId: Plugin.PluginModule['id']): Effect.Semaphore {\n let semaphore = this._moduleSemaphores.get(moduleId);\n if (!semaphore) {\n semaphore = Effect.runSync(Effect.makeSemaphore(1));\n this._moduleSemaphores.set(moduleId, semaphore);\n }\n return semaphore;\n }\n\n // `parentEvent` is the activation event that first triggered this module\n // load — included in `activating`/`activated` PubSub messages so subscribers\n // (e.g. the boot loader's status listener) can associate a module with its\n // triggering event in the trace. The same module may be referenced by\n // multiple events, but module loads are memoized via `_moduleMemoMap`, so\n // only the first event to need it will appear here; later events await the\n // cached deferred without re-publishing.\n private _loadModule = (module: Plugin.PluginModule, parentEvent: string): Effect.Effect<Capability.Any[], Error> =>\n Effect.gen(this, function* () {\n const semaphore = this._getModuleSemaphore(module.id);\n\n // Atomically check-and-set under per-module semaphore to prevent race conditions.\n const deferredToAwait = yield* Effect.gen(this, function* () {\n const existing = this._moduleMemoMap.get(module.id);\n if (existing) {\n return existing;\n }\n\n // First caller - create deferred, store it, and start loading in background.\n const deferred = yield* Deferred.make<Capability.Any[], Error>();\n this._moduleMemoMap.set(module.id, deferred);\n\n const loadEffect = Effect.gen(this, function* () {\n log('loading module', { module: module.id, parentEvent });\n performance.mark(`module:${module.id}:start`);\n yield* PubSub.publish(this.activation, { event: parentEvent, state: 'activating', module: module.id });\n const pluginId = this._getPluginIdForModule(module.id);\n const [duration, capabilities] = yield* module.activate().pipe(\n Effect.provideService(Capability.Service, this.capabilities),\n Effect.provideService(Plugin.Service, this),\n // Cap activation so a single misbehaving module can't hold the\n // event chain open. On timeout the failure is recorded against\n // the plugin and surfaced as `PluginTimeoutError`.\n Effect.timeoutFail({\n duration: this._activationTimeout,\n onTimeout: () =>\n new PluginTimeoutError({\n context: { id: pluginId ?? module.id, module: module.id, phase: 'activation' as PluginFailurePhase },\n }),\n }),\n Effect.timed,\n );\n const normalized = capabilities == null ? [] : Array.isArray(capabilities) ? capabilities : [capabilities];\n const elapsed = Duration.toMillis(duration);\n performance.mark(`module:${module.id}:end`);\n performance.measure(`module:${module.id}`, `module:${module.id}:start`, `module:${module.id}:end`);\n yield* PubSub.publish(this.activation, { event: parentEvent, state: 'activated', module: module.id });\n log('loaded module', {\n module: module.id,\n parentEvent,\n elapsed,\n failed: false,\n });\n return normalized as Capability.Any[];\n }).pipe(\n Effect.withSpan('PluginManager._loadModule'),\n together(\n Effect.sleep(Duration.seconds(10)).pipe(\n Effect.andThen(\n Effect.sync(() => log.warn(`module is taking a long time to activate`, { module: module.id })),\n ),\n ),\n ),\n Performance.addTrackEntry({\n name: module.id,\n devtools: {\n dataType: 'track-entry',\n track: 'Module Activation',\n trackGroup: 'Composer',\n color: 'primary',\n },\n }),\n );\n\n // Fork the load to run in background, completing the deferred when done.\n const fiber = yield* Effect.forkDaemon(\n loadEffect.pipe(\n Effect.tap((result) => Deferred.succeed(deferred, result)),\n Effect.catchAllCause((cause) => {\n const error = Cause.squash(cause);\n const errorMessage = error instanceof Error ? error.message : String(error);\n const missingCapability = errorMessage.match(/No capability found for ([^\\s\\[]+)/)?.[1];\n log.error('module failed to activate', {\n module: module.id,\n parentEvent,\n missingCapability,\n registeredCapabilities: this.capabilities.listRegisteredIdentifiers(),\n error: errorMessage,\n stack: error instanceof Error ? error.stack : undefined,\n isDefect: !Cause.isFailure(cause),\n });\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n const pluginId = this._getPluginIdForModule(module.id);\n if (pluginId !== undefined) {\n this._recordFailure(pluginId, 'activation', normalizedError);\n this._scheduleAutoDisable(pluginId);\n }\n return Deferred.fail(deferred, normalizedError);\n }),\n ),\n );\n yield* this._trackFiber(this._inFlightFibers, fiber);\n yield* Effect.forkDaemon(\n Fiber.await(fiber).pipe(Effect.andThen(() => this._untrackFiber(this._inFlightFibers, fiber))),\n );\n\n return deferred;\n }).pipe(semaphore.withPermits(1));\n\n // Wait for result outside the semaphore so multiple waiters can proceed concurrently.\n return yield* Deferred.await(deferredToAwait);\n });\n\n private _contributeCapabilities(\n module: Plugin.PluginModule,\n capabilities: Capability.Any[],\n ): Effect.Effect<void, Error> {\n return Effect.gen(this, function* () {\n capabilities.forEach((capability) => {\n this.capabilities.contribute({ module: module.id, ...capability });\n });\n this._update(this._activeAtom, (active) => [...active, module.id]);\n this._capabilities.set(module.id, capabilities);\n });\n }\n\n private _deactivateModule(module: Plugin.PluginModule): Effect.Effect<boolean, Error> {\n return Effect.gen(this, function* () {\n const id = module.id;\n log('deactivating', { id });\n this._moduleMemoMap.delete(id);\n\n const capabilities = this._capabilities.get(id);\n if (capabilities) {\n for (const capability of capabilities) {\n this.capabilities.remove(capability.interface, capability.implementation);\n const program = capability.deactivate?.() ?? Effect.succeed(undefined);\n yield* program;\n }\n this._capabilities.delete(id);\n }\n\n const activeIndex = this._get(this._activeAtom).findIndex((event) => event === id);\n if (activeIndex !== -1) {\n this._update(this._activeAtom, (active) => active.filter((event) => event !== id));\n }\n\n log('deactivated', { id });\n return true;\n });\n }\n}\n\n/**\n * Creates a new Plugin Manager instance.\n */\nexport const make = (options: ManagerOptions): PluginManager => new ManagerImpl(options);\n\n/**\n * True when `error` (or anything along its `cause` chain) is a\n * {@link PluginTimeoutError}. Lazy-load timeouts wrap the timeout inside\n * `LazyPluginError`, so a shallow check on the outer error misses them.\n * Bounded depth so a circular chain can't loop forever.\n */\nconst isTimeoutCause = (error: unknown, depth = 0): boolean => {\n if (depth > 5 || !(error instanceof Error)) {\n return false;\n }\n if (PluginTimeoutError.is(error)) {\n return true;\n }\n return isTimeoutCause((error as Error & { cause?: unknown }).cause, depth + 1);\n};\n\n/**\n * Runs an effect concurrently with another effect.\n * If the first effect completes, the second effect is interrupted.\n */\n// TODO(dmaretskyi): Effect.race > Effect.asVoid\nconst together =\n <R1>(togetherEffect: Effect.Effect<void, never, R1>) =>\n <A, E, R2>(effect: Effect.Effect<A, E, R2>): Effect.Effect<A, E, R1 | R2> =>\n Effect.gen(function* () {\n const togetherFiber = yield* Effect.fork(togetherEffect);\n const result = yield* effect;\n yield* Fiber.interrupt(togetherFiber);\n return result;\n });\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom, type Registry } from '@effect-atom/atom-react';\nimport * as Deferred from 'effect/Deferred';\nimport * as Effect from 'effect/Effect';\n\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport type * as Capability from './capability';\n\ntype CapabilityEntry<T> = {\n moduleId: string;\n implementation: T;\n};\n\n/**\n * Options for creating a capability manager.\n * @internal\n */\nexport type CapabilityManagerOptions = {\n registry: Registry.Registry;\n};\n\n/**\n * Interface for the Capability Manager.\n * Provides methods for contributing, removing, and accessing capabilities.\n */\nexport interface CapabilityManager {\n contribute<T>(args: { module: string; interface: Capability.InterfaceDef<T>; implementation: T }): void;\n\n remove<T>(interfaceDef: Capability.InterfaceDef<T>, implementation: T): void;\n\n /**\n * Get the Atom reference to the available capabilities for a given interface.\n * Primarily useful for deriving other Atom values based on the capabilities or\n * for subscribing to changes in the capabilities.\n * @returns An atom reference to the available capabilities.\n */\n atom<T>(interfaceDef: Capability.InterfaceDef<T>): Atom.Atom<T[]>;\n\n /**\n * Get capabilities from the capability manager.\n * @returns An array of capabilities.\n */\n getAll<T>(interfaceDef: Capability.InterfaceDef<T>): T[];\n\n /**\n * Requests a single capability from the capability manager.\n * @returns The capability.\n * @throws If no capability is found.\n */\n get<T>(interfaceDef: Capability.InterfaceDef<T>): T;\n\n /**\n * Waits for a capability to be available.\n * @returns The capability.\n */\n waitFor<T>(interfaceDef: Capability.InterfaceDef<T>): Effect.Effect<T, Error>;\n\n /**\n * Get capabilities grouped by the module that contributed them.\n * @returns An atom containing a record from module ID to capability implementations.\n */\n atomByModule<T>(interfaceDef: Capability.InterfaceDef<T>): Atom.Atom<Record<string, T[]>>;\n\n /**\n * Lists capability interface identifiers that currently have at least one contribution.\n */\n listRegisteredIdentifiers(): string[];\n}\n\n/**\n * Internal implementation of CapabilityManager.\n */\nclass CapabilityManagerImpl implements CapabilityManager {\n private readonly _registry: Registry.Registry;\n\n private readonly _registeredIdentifiers = new Set<string>();\n\n private readonly _capabilityEntries = Atom.family<string, Atom.Writable<CapabilityEntry<unknown>[]>>(() => {\n return Atom.make<CapabilityEntry<unknown>[]>([]).pipe(Atom.keepAlive);\n });\n\n readonly _capabilities = Atom.family<string, Atom.Atom<unknown[]>>((id: string) => {\n return Atom.make((get) => {\n const current = get(this._capabilityEntries(id));\n return current.map((c) => c.implementation);\n }).pipe(Atom.keepAlive);\n });\n\n readonly _capabilitiesByModule = Atom.family<string, Atom.Atom<Record<string, unknown[]>>>((id: string) => {\n return Atom.make((get) => {\n const entries = get(this._capabilityEntries(id));\n const result: Record<string, unknown[]> = {};\n for (const entry of entries) {\n (result[entry.moduleId] ??= []).push(entry.implementation);\n }\n return result;\n }).pipe(Atom.keepAlive);\n });\n\n readonly _capability = Atom.family<string, Atom.Atom<unknown>>((id: string) => {\n return Atom.make((get) => {\n const current = get(this._capabilities(id));\n invariant(current.length > 0, `No capability found for ${id}`);\n return current[0];\n });\n });\n\n constructor({ registry }: CapabilityManagerOptions) {\n this._registry = registry;\n }\n\n contribute<T>({\n module: moduleId,\n interface: interfaceDef,\n implementation,\n }: {\n module: string;\n interface: Capability.InterfaceDef<T>;\n implementation: T;\n }): void {\n const current = this._registry.get(this._capabilityEntries(interfaceDef.identifier));\n const isDuplicate = current.some((c) => c.moduleId === moduleId && c.implementation === implementation);\n if (isDuplicate) {\n log('capability already contributed, skipping', { id: interfaceDef.identifier, moduleId });\n return;\n }\n\n const entry: CapabilityEntry<T> = { moduleId, implementation };\n this._registry.set(this._capabilityEntries(interfaceDef.identifier), [...current, entry]);\n this._registeredIdentifiers.add(interfaceDef.identifier);\n log('capability contributed', {\n id: interfaceDef.identifier,\n moduleId,\n count: current.length,\n });\n }\n\n remove<T>(interfaceDef: Capability.InterfaceDef<T>, implementation: T): void {\n const current = this._registry.get(this._capabilityEntries(interfaceDef.identifier));\n if (current.length === 0) {\n return;\n }\n\n const next = current.filter((c) => c.implementation !== implementation);\n if (next.length !== current.length) {\n this._registry.set(this._capabilityEntries(interfaceDef.identifier), next);\n if (next.length === 0) {\n this._registeredIdentifiers.delete(interfaceDef.identifier);\n }\n log('capability removed', { id: interfaceDef.identifier, count: current.length });\n } else {\n log.warn('capability not removed', { id: interfaceDef.identifier });\n }\n }\n\n atom<T>(interfaceDef: Capability.InterfaceDef<T>): Atom.Atom<T[]> {\n // NOTE: This the type-checking for capabilities is done at the time of contribution.\n return this._capabilities(interfaceDef.identifier) as Atom.Atom<T[]>;\n }\n\n getAll<T>(interfaceDef: Capability.InterfaceDef<T>): T[] {\n return this._registry.get(this.atom(interfaceDef));\n }\n\n get<T>(interfaceDef: Capability.InterfaceDef<T>): T {\n const capabilities = this.getAll(interfaceDef);\n if (capabilities.length === 0) {\n log('capability not available', {\n requested: interfaceDef.identifier,\n registered: this.listRegisteredIdentifiers(),\n });\n invariant(capabilities.length > 0, `No capability found for ${interfaceDef.identifier}`);\n }\n return capabilities[0];\n }\n\n listRegisteredIdentifiers(): string[] {\n return [...this._registeredIdentifiers].sort();\n }\n\n waitFor<T>(interfaceDef: Capability.InterfaceDef<T>): Effect.Effect<T, Error> {\n return Effect.gen(this, function* () {\n const [capability] = this.getAll(interfaceDef);\n if (capability) {\n return capability;\n }\n\n const deferred = yield* Deferred.make<T, Error>();\n const cancel = this._registry.subscribe(this.atom(interfaceDef), (capabilities) => {\n if (capabilities.length > 0) {\n Effect.runSync(Deferred.succeed(deferred, capabilities[0]));\n }\n });\n const result = yield* Deferred.await(deferred);\n cancel();\n return result;\n });\n }\n\n atomByModule<T>(interfaceDef: Capability.InterfaceDef<T>): Atom.Atom<Record<string, T[]>> {\n return this._capabilitiesByModule(interfaceDef.identifier) as Atom.Atom<Record<string, T[]>>;\n }\n}\n\n/**\n * Creates a new Capability Manager instance.\n */\nexport const make = (options: CapabilityManagerOptions): CapabilityManager => new CapabilityManagerImpl(options);\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { Atom, type Registry as AtomRegistry } from '@effect-atom/atom-react';\nimport * as Effect from 'effect/Effect';\n\nimport { EffectEx } from '@dxos/effect';\nimport { log } from '@dxos/log';\n\n/**\n * A registry plugin entry as seen by the plugin manager layer.\n * Populated from the registry catalog; represents the latest available version of a plugin.\n *\n * Independently defined from @dxos/protocols PluginEntry — similar shape but not the same type.\n * Implementations of {@link PluginProvider} (e.g. {@link EdgeRegistryPluginProvider})\n * are responsible for mapping their wire-format entries to this shape.\n */\nexport type Plugin = {\n id: string;\n name: string;\n description?: string;\n homePage?: string;\n source?: string;\n screenshots?: string[];\n tags?: string[];\n icon?: string;\n iconHue?: string;\n /**\n * IDs of plugins this entry declares as runtime dependencies. Mirrors\n * {@link Plugin.Meta.dependsOn}. Surfaced in the catalog so the manager can\n * resolve and auto-install transitive deps before they are first loaded.\n */\n dependsOn?: string[];\n /** URL to dynamic-import the latest version of this plugin module. */\n moduleUrl: string;\n /** GitHub repository slug, e.g. `owner/name`. Used to fetch version history. */\n repo: string;\n /**\n * Latest known version string, e.g. `v1.2.0`.\n * Corresponds to releaseTag in the wire-format PluginEntry; named `version` here\n * because the plugin manager layer speaks versions, not release tags.\n */\n version: string;\n};\n\n/**\n * A single installable version of a registry plugin.\n */\nexport type PluginVersion = {\n /** Version string, e.g. `v1.2.0`. */\n tag: string;\n /** URL to dynamic-import this specific version of the plugin module. */\n moduleUrl: string;\n /** Unix ms of when this version was published (optional; omitted when unknown). */\n releasedAt?: number;\n};\n\n/**\n * Abstraction over the plugin registry catalog backend.\n * Implementations may call Edge, a local cache, or a stub.\n *\n * The interface itself is transport-agnostic; concrete implementations live\n * alongside it in this package (see {@link EdgeRegistryPluginProvider}) so we\n * avoid `app-framework ↔ edge-client` cycles, but they only need to satisfy\n * this shape — callers can substitute their own.\n */\nexport interface PluginProvider {\n /**\n * Returns all healthy registry plugins (latest version of each).\n */\n listPlugins(): Effect.Effect<readonly Plugin[], Error>;\n\n /**\n * Returns all known versions of a plugin identified by its GitHub repo slug.\n * Until the backend implements a versions endpoint, implementations MUST\n * return at least one entry representing the current/latest release.\n */\n listVersions(repo: string): Effect.Effect<readonly PluginVersion[], Error>;\n\n /**\n * Returns a single plugin entry for the given repo.\n * If `version` is omitted, returns the latest.\n * Fails if the specified version is not found.\n */\n getPlugin(repo: string, version?: string): Effect.Effect<Plugin, Error>;\n}\n\n/**\n * Atomic snapshot of the registry catalog as observed by the host.\n * Exposed via {@link Manager.plugins} so consumers can subscribe reactively\n * (loading state, list contents, last error).\n */\nexport type PluginsState = {\n entries: readonly Plugin[];\n loading: boolean;\n error: Error | null;\n};\n\n/**\n * Default no-op provider used when no `PluginProvider` is supplied at construction\n * time (e.g. tests, stories, environments without an Edge connection).\n *\n * `listPlugins` returns an empty list (so `Manager.plugins` settles to a stable\n * empty state). `listVersions` and `getPlugin` fail with an explicit error so\n * callers know they need to configure a real provider.\n */\nconst NULL_PROVIDER: PluginProvider = {\n listPlugins: () => Effect.succeed([] as readonly Plugin[]),\n listVersions: () => Effect.fail(new Error('No plugin registry provider configured')),\n getPlugin: () => Effect.fail(new Error('No plugin registry provider configured')),\n};\n\n/**\n * Owns the cached registry catalog state and forwards `listVersions` / `getPlugin`\n * calls to the underlying {@link PluginProvider}. Lives on the `PluginManager`\n * (as `manager.pluginRegistry`) so consumers can reach it through the manager\n * without a separate capability lookup.\n *\n * On construction the manager kicks off a background fetch via `provider.listPlugins()`\n * and writes the result into the {@link plugins} atom. Subscribers see `loading: true`\n * during the fetch and `loading: false` once it settles.\n */\nexport class Manager {\n readonly plugins: Atom.Writable<PluginsState>;\n readonly #provider: PluginProvider;\n\n constructor(provider: PluginProvider | undefined, atomRegistry: AtomRegistry.Registry) {\n this.#provider = provider ?? NULL_PROVIDER;\n const initialLoading = provider !== undefined;\n this.plugins = Atom.make<PluginsState>({ entries: [], loading: initialLoading, error: null }).pipe(Atom.keepAlive);\n\n if (provider !== undefined) {\n // Fire-and-forget initial load. Errors are surfaced via the atom's `error` field.\n void EffectEx.runAndForwardErrors(\n provider.listPlugins().pipe(\n Effect.match({\n onSuccess: (entries) => atomRegistry.set(this.plugins, { entries, loading: false, error: null }),\n onFailure: (error) => {\n log.catch(error);\n atomRegistry.set(this.plugins, { entries: [], loading: false, error });\n },\n }),\n ),\n );\n }\n }\n\n /** Forwards to the underlying provider. */\n listPlugins(): Effect.Effect<readonly Plugin[], Error> {\n return this.#provider.listPlugins();\n }\n\n /** Forwards to the underlying provider. */\n listVersions(repo: string): Effect.Effect<readonly PluginVersion[], Error> {\n return this.#provider.listVersions(repo);\n }\n\n /** Forwards to the underlying provider. */\n getPlugin(repo: string, version?: string): Effect.Effect<Plugin, Error> {\n return this.#provider.getPlugin(repo, version);\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["make", "Atom", "Registry", "Array", "Cause", "Deferred", "Duration", "Effect", "Fiber", "Function", "HashSet", "PubSub", "Ref", "EffectEx", "Performance", "BaseError", "log", "make", "Atom", "Deferred", "Effect", "invariant", "log", "_registeredIdentifiers", "_capabilityEntries", "pipe", "_capabilities", "family", "id", "current", "c", "keepAlive", "_capabilitiesByModule", "get", "result", "entry", "entries", "_capability", "length", "contribute", "moduleId", "isDuplicate", "implementation", "interfaceDef", "identifier", "count", "remove", "_registry", "set", "next", "atom", "getAll", "capabilities", "requested", "registered", "listRegisteredIdentifiers", "waitFor", "capability", "deferred", "runSync", "cancel", "atomByModule", "Atom", "Effect", "EffectEx", "log", "__dxlog_file", "listVersions", "getPlugin", "fail", "Error", "initialLoading", "provider", "plugins", "entries", "loading", "error", "pipe", "keepAlive", "runAndForwardErrors", "onFailure", "atomRegistry", "__dxlog_file", "DEFAULT_LOAD_TIMEOUT", "seconds", "activation", "Effect", "capabilities", "registry", "pluginRegistry", "_pluginsAtom", "_coreAtom", "_enabledAtom", "_modulesAtom", "_activeAtom", "_eventsFiredAtom", "_pendingResetAtom", "_failedAtom", "_pluginLoader", "_onRemove", "_loadTimeout", "_activationTimeout", "_capabilities", "_moduleMemoMap", "_moduleSemaphores", "Map", "_activatingEvents", "_activatingModules", "_inFlightFibers", "runSync", "make", "_shutdownSemaphore", "makeSemaphore", "_shuttingDown", "CapabilityManager", "onRemove", "loadTimeout", "Atom", "enabled", "pipe", "keepAlive", "_devPluginIdsAtom", "plugins", "plugin", "_addPlugin", "core", "tap", "Deferred", "succeed", "_initialization", "undefined", "tapErrorCause", "failCause", "EffectEx", "getPlugins", "getCore", "getEnabled", "getModules", "getActive", "getEventsFired", "getPendingReset", "getFailed", "getDevPluginIds", "id", "_update", "shadow", "getDependencies", "transitive", "_directDependencies", "walk", "_computeDependencyClosure", "getDependents", "opts", "enabledOnly", "clearFailure", "current", "some", "log", "pluginId", "meta", "existing", "_getPlugin", "dev", "disable", "_markDev", "wasEnabled", "gen", "resolveDependencies", "_enableOne", "_recordFailure", "Plugin", "context", "reason", "path", "missing", "length", "queue", "shift", "installed", "next", "PluginDependencyError", "dependency", "cause", "installResult", "add", "rewalk", "cycle", "depId", "succeeded", "ok", "stub", "modules", "_setPendingResetByModule", "concurrency", "isLazy", "deferred", "module", "resolvedPlugin", "onTimeout", "PluginTimeoutError", "phase", "event", "error", "value", "disabled", "_removePlugin", "_runForkedFiber", "enable", "cascade", "enabledDependents", "coreDependent", "_get", "enabledIndex", "filter", "item", "deactivate", "forEach", "_removeModule", "_isShuttingDown", "key", "Performance", "addTrackEntry", "name", "devtools", "dataType", "track", "trackGroup", "color", "every", "results", "map", "shutdown", "_interruptInFlightActivations", "activeIds", "reverse", "allModules", "modulesToDeactivate", "_deactivateModule", "Ref", "set", "_set", "atom", "updater", "_getPluginIdForModule", "moduleId", "_getCatalogEntry", "dependsOn", "Set", "onStack", "stackPath", "toInstall", "knownIds", "visit", "currentId", "visited", "slice", "cycleStart", "push", "order", "direct", "dependentId", "includes", "result", "has", "parentId", "failure", "timestamp", "warn", "entry", "tapError", "_getActiveModules", "_getInactiveModules", "_getActiveModulesByEvent", "_getInactiveModulesByEvent", "Array", "fromIterable", "pendingReset", "_clearPendingReset", "pendingIndex", "pending", "inFlightFibers", "_trackFiber", "fibers", "fiber", "_untrackFiber", "await", "_addModule", "activatingEvents", "activatingModules", "_getModulesForActivation", "events", "_activateModulesForEvent", "activating", "activatingModuleIds", "performance", "mark", "publish", "_contributeCapabilitiesForModules", "_activateRelatedEvents", "PubSub", "ensuring", "update", "ActivationEvent", "allOf", "_getBeforeEvents", "_getAfterEvents", "after", "together", "sleep", "eventKey", "catchAll", "_getModuleSemaphore", "semaphore", "deferredToAwait", "loadEffect", "parentEvent", "Service", "timed", "normalized", "elapsed", "failed", "withSpan", "errorMessage", "message", "String", "missingCapability", "registeredCapabilities", "stack", "Error", "isDefect", "normalizedError", "_scheduleAutoDisable", "withPermits", "_contributeCapabilities", "capability", "get", "program", "activeIndex", "active", "isTimeoutCause", "effect", "togetherFiber"]
|
|
7
|
-
}
|