@dxos/app-framework 0.9.0 → 0.9.1-staging.ee54ba693a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/{capability-BOPAKKWG.mjs → capability-S44TE2H7.mjs} +9 -9
- package/dist/lib/browser/{chunk-66IXTIVK.mjs → chunk-3NQLTQCP.mjs} +6 -7
- package/dist/lib/browser/chunk-3NQLTQCP.mjs.map +7 -0
- package/dist/lib/browser/chunk-53HJHMS5.mjs +7 -0
- package/dist/lib/browser/chunk-53HJHMS5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-Y66ELD4U.mjs → chunk-KRJ4KK2W.mjs} +36 -7
- package/dist/lib/browser/chunk-KRJ4KK2W.mjs.map +7 -0
- package/dist/lib/browser/{chunk-KZUDO43J.mjs → chunk-LUH4Y5F2.mjs} +31 -23
- package/dist/lib/browser/chunk-LUH4Y5F2.mjs.map +7 -0
- package/dist/lib/browser/{chunk-CO3XLNUX.mjs → chunk-NKVRSMFN.mjs} +18 -18
- package/dist/lib/browser/chunk-NKVRSMFN.mjs.map +7 -0
- package/dist/lib/browser/{chunk-DC3WRPBV.mjs → chunk-OO53M5UK.mjs} +45 -12
- package/dist/lib/browser/chunk-OO53M5UK.mjs.map +7 -0
- package/dist/lib/browser/{chunk-IW44C7UL.mjs → chunk-OPTS3ZSN.mjs} +1 -1
- package/dist/lib/browser/chunk-OPTS3ZSN.mjs.map +7 -0
- package/dist/lib/browser/{chunk-HFLKXMT7.mjs → chunk-U5MESPM5.mjs} +61 -45
- package/dist/lib/browser/chunk-U5MESPM5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-XHS5KDNX.mjs → chunk-UGYCLOXE.mjs} +25 -25
- package/dist/lib/browser/chunk-UGYCLOXE.mjs.map +7 -0
- package/dist/lib/browser/{chunk-5GY3YOEL.mjs → chunk-VF37YTXJ.mjs} +5 -5
- package/dist/lib/browser/chunk-VF37YTXJ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FO3IYSLV.mjs → chunk-YUVQIOTB.mjs} +29 -37
- package/dist/lib/browser/chunk-YUVQIOTB.mjs.map +7 -0
- package/dist/lib/browser/cli/index.mjs +9 -9
- package/dist/lib/browser/cli/index.mjs.map +2 -2
- package/dist/lib/browser/common/activation-events.mjs +7 -7
- package/dist/lib/browser/common/capabilities.mjs +7 -7
- package/dist/lib/browser/config/index.mjs +8 -0
- package/dist/lib/browser/config/index.mjs.map +7 -0
- package/dist/lib/browser/core/activation-event.mjs +1 -1
- package/dist/lib/browser/core/capability.mjs +1 -1
- package/dist/lib/browser/core/plugin-manager.mjs +4 -4
- package/dist/lib/browser/core/plugin.mjs +12 -2
- package/dist/lib/browser/core/url-loader.mjs +3 -3
- package/dist/lib/browser/index.mjs +14 -10
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{process-manager-capability-GXNUO7AR.mjs → process-manager-capability-QK4BMKMN.mjs} +9 -9
- package/dist/lib/browser/testing/index.mjs +15 -15
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/testing/react.mjs +11 -11
- package/dist/lib/browser/testing/react.mjs.map +3 -3
- package/dist/lib/browser/ui/index.mjs +18 -10
- package/dist/lib/node-esm/{capability-KZWRTX7R.mjs → capability-3YRF77LV.mjs} +9 -9
- package/dist/lib/node-esm/chunk-2UPUZXGU.mjs +9 -0
- package/dist/lib/node-esm/chunk-2UPUZXGU.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-XIGPWXCQ.mjs → chunk-4SE7SX7N.mjs} +45 -12
- package/dist/lib/node-esm/chunk-4SE7SX7N.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-XOCUANHO.mjs → chunk-BMW6P6QA.mjs} +6 -7
- package/dist/lib/node-esm/chunk-BMW6P6QA.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-A5CHGAZE.mjs → chunk-DRT75WGD.mjs} +61 -45
- package/dist/lib/node-esm/chunk-DRT75WGD.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-XGBUKRCK.mjs → chunk-FKMVORZN.mjs} +31 -23
- package/dist/lib/node-esm/chunk-FKMVORZN.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-CTKEZHKF.mjs → chunk-GLH4LGHZ.mjs} +1 -1
- package/dist/lib/node-esm/chunk-GLH4LGHZ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-SX5NVETP.mjs → chunk-IL7O7IRX.mjs} +25 -25
- package/dist/lib/node-esm/chunk-IL7O7IRX.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-FSVGKTF6.mjs → chunk-ND2HETHD.mjs} +36 -7
- package/dist/lib/node-esm/chunk-ND2HETHD.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-KFZEB6BV.mjs → chunk-TLKYZKPW.mjs} +5 -5
- package/dist/lib/node-esm/chunk-TLKYZKPW.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-WK7OIQKI.mjs → chunk-VCPGX7WN.mjs} +29 -37
- package/dist/lib/node-esm/chunk-VCPGX7WN.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-NULBHQYS.mjs → chunk-XSZMX53L.mjs} +18 -18
- package/dist/lib/node-esm/chunk-XSZMX53L.mjs.map +7 -0
- package/dist/lib/node-esm/cli/index.mjs +9 -9
- package/dist/lib/node-esm/cli/index.mjs.map +2 -2
- package/dist/lib/node-esm/common/activation-events.mjs +7 -7
- package/dist/lib/node-esm/common/capabilities.mjs +7 -7
- package/dist/lib/node-esm/config/index.mjs +9 -0
- package/dist/lib/node-esm/config/index.mjs.map +7 -0
- package/dist/lib/node-esm/core/activation-event.mjs +1 -1
- package/dist/lib/node-esm/core/capability.mjs +1 -1
- package/dist/lib/node-esm/core/plugin-manager.mjs +4 -4
- package/dist/lib/node-esm/core/plugin.mjs +12 -2
- package/dist/lib/node-esm/core/url-loader.mjs +3 -3
- package/dist/lib/node-esm/index.mjs +14 -10
- package/dist/lib/node-esm/index.mjs.map +1 -1
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{process-manager-capability-TX5TA6YN.mjs → process-manager-capability-5S7WZ2JR.mjs} +9 -9
- package/dist/lib/node-esm/testing/index.mjs +15 -15
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/testing/react.mjs +11 -11
- package/dist/lib/node-esm/testing/react.mjs.map +3 -3
- package/dist/lib/node-esm/ui/index.mjs +18 -10
- package/dist/plugin/node-esm/index.mjs +414 -81
- package/dist/plugin/node-esm/index.mjs.map +4 -4
- package/dist/plugin/node-esm/meta.json +1 -1
- package/dist/types/src/cli/cli.d.ts +1 -1
- package/dist/types/src/common/activation-events.d.ts.map +1 -1
- package/dist/types/src/common/capabilities.d.ts +2 -2
- package/dist/types/src/common/capabilities.d.ts.map +1 -1
- package/dist/types/src/config/index.d.ts +2 -0
- package/dist/types/src/config/index.d.ts.map +1 -0
- package/dist/types/src/core/activation-event.d.ts +9 -6
- package/dist/types/src/core/activation-event.d.ts.map +1 -1
- package/dist/types/src/core/capability.d.ts +9 -3
- package/dist/types/src/core/capability.d.ts.map +1 -1
- package/dist/types/src/core/edge-registry-plugin-provider.d.ts +6 -11
- package/dist/types/src/core/edge-registry-plugin-provider.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manifest.d.ts +25 -7
- package/dist/types/src/core/plugin-manifest.d.ts.map +1 -1
- package/dist/types/src/core/plugin.d.ts +89 -91
- package/dist/types/src/core/plugin.d.ts.map +1 -1
- package/dist/types/src/core/registry.d.ts +17 -57
- package/dist/types/src/core/registry.d.ts.map +1 -1
- package/dist/types/src/core/url-loader.d.ts +2 -2
- package/dist/types/src/core/url-loader.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/history/capability.d.ts +1 -3
- package/dist/types/src/plugin-process-manager/history/capability.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/meta.d.ts +32 -2
- package/dist/types/src/plugin-process-manager/meta.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts +1 -4
- package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -1
- package/dist/types/src/testing/harness.d.ts +1 -1
- package/dist/types/src/testing/harness.d.ts.map +1 -1
- package/dist/types/src/testing/react.d.ts +6 -5
- package/dist/types/src/testing/react.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/App/App.stories.d.ts +2 -2
- package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +6 -0
- package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +6 -10
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/context.d.ts +6 -2
- package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/index.d.ts +11 -4
- package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/types.d.ts +52 -72
- package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useApp.d.ts +1 -1
- package/dist/types/src/ui/hooks/useCapabilities.d.ts +17 -1
- package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/composer/index.d.ts +11 -4
- package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/index.d.ts +1 -0
- package/dist/types/src/vite-plugin/index.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/load.d.ts +16 -0
- package/dist/types/src/vite-plugin/load.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/manifest.d.ts +16 -4
- package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/packages.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/docs/registry-spec.md +331 -0
- package/moon.yml +1 -0
- package/package.json +50 -39
- package/src/cli/cli.ts +2 -2
- package/src/common/activation-events.ts +3 -3
- package/src/common/capabilities.ts +18 -18
- package/src/config/index.ts +5 -0
- package/src/core/activation-event.ts +15 -8
- package/src/core/capability.ts +18 -6
- package/src/core/edge-registry-plugin-provider.ts +41 -42
- package/src/core/plugin-manager.test.ts +133 -137
- package/src/core/plugin-manager.ts +25 -19
- package/src/core/plugin-manifest.test.ts +5 -5
- package/src/core/plugin-manifest.ts +13 -10
- package/src/core/plugin.ts +58 -114
- package/src/core/registry.ts +20 -60
- package/src/core/url-loader.test.ts +2 -2
- package/src/core/url-loader.ts +23 -19
- package/src/index.ts +1 -0
- package/src/testing/harness.ts +5 -3
- package/src/testing/react.test.tsx +4 -2
- package/src/testing/react.tsx +10 -9
- package/src/testing/service.ts +2 -2
- package/src/testing/withPluginManager.stories.tsx +4 -2
- package/src/testing/withPluginManager.tsx +3 -1
- package/src/ui/components/App/App.stories.tsx +2 -2
- package/src/ui/components/PluginManager/PluginManagerProvider.ts +7 -0
- package/src/ui/components/Surface/SurfaceComponent.stories.tsx +22 -22
- package/src/ui/components/Surface/SurfaceComponent.tsx +90 -79
- package/src/ui/components/Surface/SurfaceProfilerContext.tsx +1 -1
- package/src/ui/components/Surface/context.ts +6 -4
- package/src/ui/components/Surface/index.ts +14 -3
- package/src/ui/components/Surface/types.test.ts +43 -51
- package/src/ui/components/Surface/types.ts +99 -64
- package/src/ui/hooks/useApp.test.tsx +1 -1
- package/src/ui/hooks/useApp.tsx +2 -2
- package/src/ui/hooks/useCapabilities.ts +49 -2
- package/src/vite-plugin/boot-loader/BootLoader.solid-stories.tsx +11 -11
- package/src/vite-plugin/boot-loader/loader.ts +3 -3
- package/src/vite-plugin/composer/index.ts +134 -61
- package/src/vite-plugin/import-map/index.ts +23 -7
- package/src/vite-plugin/index.ts +1 -0
- package/src/vite-plugin/load.ts +57 -0
- package/src/vite-plugin/manifest.test.ts +3 -3
- package/src/vite-plugin/manifest.ts +21 -10
- package/src/vite-plugin/packages.ts +0 -2
- package/tsconfig.json +5 -2
- package/dist/lib/browser/chunk-5GY3YOEL.mjs.map +0 -7
- package/dist/lib/browser/chunk-66IXTIVK.mjs.map +0 -7
- package/dist/lib/browser/chunk-CO3XLNUX.mjs.map +0 -7
- package/dist/lib/browser/chunk-DC3WRPBV.mjs.map +0 -7
- package/dist/lib/browser/chunk-FO3IYSLV.mjs.map +0 -7
- package/dist/lib/browser/chunk-HFLKXMT7.mjs.map +0 -7
- package/dist/lib/browser/chunk-IW44C7UL.mjs.map +0 -7
- package/dist/lib/browser/chunk-KZUDO43J.mjs.map +0 -7
- package/dist/lib/browser/chunk-XHS5KDNX.mjs.map +0 -7
- package/dist/lib/browser/chunk-Y66ELD4U.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-A5CHGAZE.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-CTKEZHKF.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-FSVGKTF6.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-KFZEB6BV.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NULBHQYS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SX5NVETP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-WK7OIQKI.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XGBUKRCK.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XIGPWXCQ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XOCUANHO.mjs.map +0 -7
- /package/dist/lib/browser/{capability-BOPAKKWG.mjs.map → capability-S44TE2H7.mjs.map} +0 -0
- /package/dist/lib/browser/{process-manager-capability-GXNUO7AR.mjs.map → process-manager-capability-QK4BMKMN.mjs.map} +0 -0
- /package/dist/lib/node-esm/{capability-KZWRTX7R.mjs.map → capability-3YRF77LV.mjs.map} +0 -0
- /package/dist/lib/node-esm/{process-manager-capability-TX5TA6YN.mjs.map → process-manager-capability-5S7WZ2JR.mjs.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/testing/harness.ts", "../../../../src/testing/operationCapture.ts", "../../../../src/testing/service.ts", "../../../../src/testing/withPluginManager.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Registry } from '@effect-atom/atom-react';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as PubSub from 'effect/PubSub';\nimport * as Queue from 'effect/Queue';\n\nimport { type Operation } from '@dxos/compute';\nimport { EffectEx } from '@dxos/effect';\nimport { invariant } from '@dxos/invariant';\n\nimport { ActivationEvents, Capabilities } from '../common';\nimport { ActivationEvent, type Capability, type CapabilityManager, type Plugin, PluginManager } from '../core';\n\nexport type TestAppOptions = {\n /**\n * Plugins to register. Plugins whose `meta.tags` includes `'system'` are treated as core\n * (force-enabled). For test convenience, plugins without a `'system'` tag are enabled by\n * default unless `enabled` is provided.\n */\n plugins: Plugin.Plugin[];\n /** Plugin ids that are enabled by default in addition to core. Defaults to all non-system plugin ids. */\n enabled?: string[];\n /** Additional activation events fired alongside SetupReactSurface. */\n setupEvents?: ActivationEvent.ActivationEvent[];\n /**\n * Whether to automatically fire SetupReactSurface + Startup during setup.\n * Defaults to true.\n */\n autoStart?: boolean;\n /**\n * Whether to register the PluginManager + AtomRegistry framework capabilities.\n * Defaults to true.\n */\n registerFrameworkCapabilities?: boolean;\n};\n\n/**\n * A running plugin manager plus helpers for driving it in tests.\n */\nexport interface TestHarness {\n readonly manager: PluginManager.PluginManager;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.Registry;\n\n /** Activate the given event. Equivalent to `manager.activate(event)`. */\n fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;\n /** Re-activate all modules that were activated by the given event. */\n reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;\n\n /** Returns the first contributed capability for the given interface. Throws if none are present. */\n get<T>(iface: Capability.InterfaceDef<T>): T;\n /** Returns all contributed capabilities for the given interface. */\n getAll<T>(iface: Capability.InterfaceDef<T>): T[];\n /** Waits until at least one capability is contributed for the given interface. */\n waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T>;\n /** Waits until the given activation event has completed. */\n waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void>;\n\n /** Invokes an operation through the `Capabilities.OperationInvoker` capability. */\n invoke<I, O>(op: Operation.Definition<I, O>, ...args: void extends I ? [input?: I] : [input: I]): Promise<O>;\n\n /**\n * Waits for `Capabilities.ProcessManagerRuntime` and runs the given effect on it.\n * Convenience around `waitForCapability(ProcessManagerRuntime).runPromise(effect)`.\n */\n runPromise<A, E>(\n effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,\n options?: { readonly timeout?: number; readonly signal?: AbortSignal },\n ): Promise<A>;\n\n enable(id: string): Promise<boolean>;\n disable(id: string): Promise<boolean>;\n\n /** Shuts down the underlying plugin manager. */\n dispose(): Promise<void>;\n\n /** Async-disposable support so tests can use `await using harness = ...`. */\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5_000;\n\n/**\n * Creates a TestHarness with the same bootstrap sequence that `useApp` performs,\n * minus the React provider tree.\n *\n * For Node-only tests, this is enough to fire activation events, read\n * capabilities, and invoke operations.\n *\n * For React tests, pass the returned harness to `render` or `renderSurface`\n * from `@dxos/app-framework/testing-react`.\n */\nexport const createTestApp = async (opts: TestAppOptions): Promise<TestHarness> => {\n const {\n plugins,\n enabled = plugins.filter(({ meta }) => !meta.tags?.includes('system')).map((plugin) => plugin.meta.id),\n setupEvents = [],\n autoStart = true,\n registerFrameworkCapabilities = true,\n } = opts;\n\n const pluginLoader = (id: string) =>\n Effect.sync(() => {\n const plugin = plugins.find((plugin) => plugin.meta.id === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n });\n\n const manager = PluginManager.make({ pluginLoader, plugins, enabled });\n\n if (registerFrameworkCapabilities) {\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n }\n\n if (autoStart) {\n try {\n await EffectEx.runAndForwardErrors(\n Effect.all([\n ...setupEvents.map((event) => manager.activate(event)),\n manager.activate(ActivationEvents.SetupReactSurface),\n manager.activate(ActivationEvents.Startup),\n ]),\n );\n } catch (err) {\n await EffectEx.runAndForwardErrors(manager.shutdown()).catch(() => undefined);\n throw err;\n }\n }\n\n return new TestHarnessImpl(manager);\n};\n\nclass TestHarnessImpl implements TestHarness {\n constructor(readonly manager: PluginManager.PluginManager) {}\n\n get capabilities(): CapabilityManager.CapabilityManager {\n return this.manager.capabilities;\n }\n\n get registry(): Registry.Registry {\n return this.manager.registry;\n }\n\n fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.activate(event));\n }\n\n reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.reset(event));\n }\n\n get<T>(iface: Capability.InterfaceDef<T>): T {\n return this.manager.capabilities.get(iface);\n }\n\n getAll<T>(iface: Capability.InterfaceDef<T>): T[] {\n return this.manager.capabilities.getAll(iface);\n }\n\n waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n return EffectEx.runAndForwardErrors(\n this.manager.capabilities.waitFor(iface).pipe(\n Effect.timeoutFail({\n duration: Duration.millis(timeout),\n onTimeout: () => timeoutError(iface.identifier),\n }),\n ),\n );\n }\n\n waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void> {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n\n const program = Effect.gen(this, function* () {\n const queue = yield* PubSub.subscribe(this.manager.activation);\n // Re-check after subscribing to avoid a race where the event fires\n // between the caller invoking this and the subscription being installed.\n if (this.manager.getEventsFired().includes(key)) {\n return;\n }\n while (true) {\n const message = yield* Queue.take(queue);\n if (message.event === key && message.state === 'activated') {\n return;\n }\n }\n }).pipe(\n Effect.scoped,\n Effect.timeoutFail({\n duration: Duration.millis(timeout),\n onTimeout: () => timeoutError(key),\n }),\n );\n\n return EffectEx.runAndForwardErrors(program);\n }\n\n async invoke<I, O>(op: Operation.Definition<I, O>, ...args: [input?: I]): Promise<O> {\n const invoker = await this.waitForCapability(Capabilities.OperationInvoker);\n const result = await invoker.invokePromise(op as any, ...(args as [any]));\n if (result.error) {\n throw result.error;\n }\n return result.data as O;\n }\n\n async runPromise<A, E>(\n effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,\n options?: { readonly timeout?: number; readonly signal?: AbortSignal },\n ): Promise<A> {\n const runtime = await this.waitForCapability(Capabilities.ProcessManagerRuntime, { timeout: options?.timeout });\n return runtime.runPromise(effect, options?.signal ? { signal: options.signal } : undefined);\n }\n\n enable(id: string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.enable(id));\n }\n\n disable(id: string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.disable(id));\n }\n\n async dispose(): Promise<void> {\n await EffectEx.runAndForwardErrors(this.manager.shutdown());\n }\n\n [Symbol.asyncDispose](): Promise<void> {\n return this.dispose();\n }\n}\n\nconst timeoutError = (id: string) => new Error(`Timed out waiting for ${id}`);\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { type Operation } from '@dxos/compute';\n\nimport { Capabilities } from '../common';\nimport { Capability } from '../core';\n\nexport type CapturedCall<I = unknown> = {\n /** The DXN key string of the invoked operation. */\n operationKey: string;\n /** The input passed to the operation. */\n input: I;\n};\n\ntype CapabilityManagerLike = {\n get: (cap: Capability.InterfaceDef<Capabilities.OperationInvoker>) => Capabilities.OperationInvoker;\n getAll: (cap: Capability.InterfaceDef<Capabilities.OperationInvoker>) => Capabilities.OperationInvoker[];\n};\n\nexport type OperationCapture = {\n /**\n * Wraps the real OperationInvoker from the given manager. Pass to\n * `withPluginManager({ capabilities: (m) => capture.wrap(m) })`.\n */\n wrap(manager: CapabilityManagerLike): Capability.Any[];\n /** Returns all recorded calls (mocked or real) for the given operation. */\n getCalls<I, O>(op: Operation.Definition<I, O>): CapturedCall<I>[];\n /** Clears all recorded calls (useful between play function steps). */\n reset(): void;\n};\n\n/**\n * Creates a capture that wraps the real `Capabilities.OperationInvoker`:\n *\n * - **Mocked operations** (declared in `mockedOperations`) are intercepted: the call is recorded\n * and returns `{ data: undefined }` without executing. Use this for side-effecting operations\n * you don't want to run in tests, such as `LayoutOperation.Open` (navigation).\n *\n * - **All other operations** are forwarded to the real invoker and still execute normally. The\n * call is still recorded so you can assert it was triggered even though it ran for real.\n *\n * Pass a `spyFn` wrapper (e.g. `fn` from `storybook/test`) to get Storybook Actions panel\n * integration and vi-style matchers on the recording.\n *\n * @example\n * ```ts\n * import { fn } from 'storybook/test';\n *\n * const capture = makeOperationCapture(\n * // These ops are mocked: captured but not executed.\n * [AssistantOperation.RunPromptInNewChat, LayoutOperation.Open],\n * fn,\n * );\n *\n * // Wire into withPluginManager:\n * capabilities: (manager) => capture.wrap(manager)\n *\n * // Assert in a play function:\n * const calls = capture.getCalls(AssistantOperation.RunPromptInNewChat);\n * expect(calls).toHaveLength(1);\n * expect(calls[0].input.prompt).toBe('Draft a new document');\n * ```\n *\n * @idiom org.dxos.app-framework.testing.operationCapture\n * applies: Storybook play-function tests for components that call plugin operations\n * instead-of: Loading every plugin whose operations the component triggers\n * uses: {@link makeOperationCapture}, {@link withPluginManager}\n */\nexport const makeOperationCapture = (\n mockedOperations: readonly Operation.Definition.Any[],\n spyFn?: (impl: (...args: any[]) => any) => any,\n): OperationCapture => {\n const calls: CapturedCall[] = [];\n\n const mockedKeys = new Set(mockedOperations.map((op) => String(op.meta.key)));\n\n const record = (op: Operation.Definition<any, any>, input?: unknown) => {\n calls.push({ operationKey: String(op.meta.key), input: input ?? {} });\n };\n\n const recordFn = spyFn ? spyFn(record) : record;\n\n return {\n wrap(manager) {\n // Use getAll to find the real invoker that was registered before our wrapper. manager.get\n // returns the last contribution (ours, once added), but getAll returns them all in order.\n // On first invocation (when activation is complete) we find the non-wrapper contribution.\n let real: Capabilities.OperationInvoker | undefined;\n const delegate = () => {\n if (!real) {\n const all = manager.getAll(Capabilities.OperationInvoker);\n real = all.find((inv) => inv !== wrapped);\n }\n return real;\n };\n\n const wrapped: Capabilities.OperationInvoker = {\n get invocations() {\n return delegate()!.invocations;\n },\n get pendingFollowups() {\n return delegate()!.pendingFollowups;\n },\n get awaitFollowups() {\n return delegate()!.awaitFollowups;\n },\n invoke: (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return Effect.succeed(undefined as any);\n }\n return (delegate()!.invoke as any)(op, input, ...rest);\n },\n invokePromise: async (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return { data: undefined };\n }\n return (delegate()!.invokePromise as any)(op, input, ...rest);\n },\n schedule: (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return Effect.succeed(undefined);\n }\n return (delegate()!.schedule as any)(op, input, ...rest);\n },\n };\n\n return [Capability.contributes(Capabilities.OperationInvoker, wrapped)];\n },\n getCalls<I, O>(op: Operation.Definition<I, O>): CapturedCall<I>[] {\n const key = String(op.meta.key);\n return calls.filter((c) => c.operationKey === key) as CapturedCall<I>[];\n },\n reset() {\n calls.length = 0;\n },\n };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nimport { invariant } from '@dxos/invariant';\n\nimport { ActivationEvents, Capabilities } from '../common';\nimport { Plugin, PluginManager } from '../core';\n\n/**\n * Creates a Plugin.Service layer from a list of plugins.\n * This is primarily used for testing.\n */\nexport const fromPlugins = (plugins: Plugin.Plugin[]) =>\n Layer.effect(\n Plugin.Service,\n Effect.gen(function* () {\n // TODO(wittjosiah): Try to dedupe logic between here, createCliApp and useApp.\n\n const pluginLoader = (id: string) =>\n Effect.sync(() => {\n const plugin = plugins.find((plugin) => plugin.meta.id === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n });\n\n const manager = PluginManager.make({\n pluginLoader,\n plugins,\n enabled: plugins.map((plugin) => plugin.meta.id),\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n\n yield* manager.activate(ActivationEvents.Startup);\n\n return manager;\n }),\n );\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Decorator, type StoryContext } from '@storybook/react';\nimport * as Effect from 'effect/Effect';\nimport React, { useEffect, useState } from 'react';\n\nimport { raise } from '@dxos/debug';\nimport { EffectEx } from '@dxos/effect';\nimport { DXN } from '@dxos/keys';\nimport { useAsyncEffect } from '@dxos/react-hooks';\nimport { type MaybeProvider, getProviderValue } from '@dxos/util';\n\nimport { ActivationEvents, Capabilities } from '../common';\nimport { type ActivationEvent, Capability, type CapabilityManager, Plugin, PluginManager } from '../core';\nimport { type UseAppOptions, useApp } from '../ui';\n\n/**\n * @internal\n */\nexport const setupPluginManager = ({\n capabilities,\n plugins = [],\n ...options\n}: UseAppOptions & Pick<WithPluginManagerOptions, 'capabilities'> = {}) => {\n // Auto-enable every non-system plugin so stories don't have to spell out\n // enablement. System-tagged plugins are force-enabled by the manager.\n const enabled = plugins.filter(({ meta }) => !meta.tags?.includes('system')).map(({ meta }) => meta.id);\n const pluginManager = PluginManager.make({\n pluginLoader: () => raise(new Error('Not implemented')),\n plugins: [StoryPlugin, ...plugins],\n enabled,\n ...options,\n });\n\n if (capabilities) {\n getProviderValue(capabilities, pluginManager.capabilities).forEach((capability) => {\n pluginManager.capabilities.contribute({\n interface: capability.interface,\n implementation: capability.implementation,\n module: 'story',\n });\n });\n }\n\n return pluginManager;\n};\n\ntype ManagedPluginManagerState = {\n fireEvents?: (ActivationEvent.ActivationEvent | string)[];\n pluginManager: PluginManager.PluginManager;\n setupEvents?: ActivationEvent.ActivationEvent[];\n storyId: string;\n};\n\nexport type WithPluginManagerOptions = UseAppOptions & {\n /** @deprecated */\n capabilities?: MaybeProvider<Capability.Any[], CapabilityManager.CapabilityManager>;\n /** @deprecated */\n fireEvents?: (ActivationEvent.ActivationEvent | string)[];\n};\n\nexport type WithPluginManagerInitializer<Args = void> =\n | WithPluginManagerOptions\n | ((context: StoryContext<Args>) => WithPluginManagerOptions);\n\n/**\n * Wraps a story with a plugin manager.\n * NOTE: This builds up and tears down the plugin manager on every render.\n */\nexport const withPluginManager = <Args,>(init: WithPluginManagerInitializer<Args> = {}): Decorator => {\n return (Story, context) => {\n const storyId = context.id;\n const options = typeof init === 'function' ? init(context as any) : init;\n const [managerState, setManagerState] = useState<ManagedPluginManagerState>();\n\n // Storybook replaces the full context object often, so key manager ownership by story id.\n useEffect(() => {\n const pluginManager = setupPluginManager(options);\n const capability = Capability.contributes(Capabilities.ReactRoot, {\n id: storyId,\n root: () => <Story />,\n });\n\n pluginManager.capabilities.contribute({\n ...capability,\n module: 'org.dxos.app-framework.with-plugin-manager',\n });\n\n setManagerState({\n pluginManager,\n setupEvents: options.setupEvents,\n fireEvents: options.fireEvents,\n storyId,\n });\n\n return () => {\n pluginManager.capabilities.remove(capability.interface, capability.implementation);\n void EffectEx.runAndForwardErrors(pluginManager.shutdown());\n };\n }, [storyId, init]);\n\n // Avoid mounting useApp with a stale manager from the previous story.\n if (!managerState || managerState.storyId !== storyId) {\n return <></>;\n }\n\n return <WithPluginManagerApp {...managerState} />;\n };\n};\n\nconst WithPluginManagerApp = ({ fireEvents, pluginManager, setupEvents, storyId }: ManagedPluginManagerState) => {\n // Fire deprecated events only after the effect-owned manager for this story exists.\n useAsyncEffect(async () => {\n await Promise.all(fireEvents?.map((event) => pluginManager.activate(event)) ?? []);\n }, [fireEvents, pluginManager, storyId]);\n\n const App = useApp({ pluginManager, setupEvents });\n return <App />;\n};\n\nconst storyMeta = Plugin.makeMeta({\n key: DXN.make('org.dxos.appFramework.story'),\n name: 'Story',\n tags: ['system'],\n});\n\n// No-op plugin to ensure there exists at least one plugin for the startup event.\n// This is necessary because `createApp` expects the startup event to complete before the app is ready.\nconst StoryPlugin = Plugin.define(storyMeta).pipe(\n Plugin.addModule({\n id: 'Story',\n activatesOn: ActivationEvents.Startup,\n activate: () => Effect.succeed([]),\n }),\n Plugin.make,\n)();\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,YAAYA,cAAc;AAC1B,YAAYC,YAAY;AACxB,YAAYC,YAAY;AACxB,YAAYC,WAAW;AAGvB,SAASC,gBAAgB;AACzB,SAASC,iBAAiB;AAwE1B,IAAA,eAAMC;;
|
|
6
|
-
"names": ["Duration", "Effect", "PubSub", "Queue", "EffectEx", "invariant", "DEFAULT_TIMEOUT_MS", "pluginLoader", "Effect", "sync", "plugin", "plugins", "meta", "id", "manager", "enabled", "registerFrameworkCapabilities", "PluginManager", "implementation", "module", "capabilities", "registry", "autoStart", "EffectEx", "activate", "SetupReactSurface", "ActivationEvents", "Startup", "err", "TestHarnessImpl", "fire", "reset", "iface", "getAll", "waitForCapability", "runAndForwardErrors", "duration", "Duration", "timeout", "onTimeout", "identifier", "waitForEvent", "opts", "program", "queue", "subscribe", "message", "timeoutError", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Registry } from '@effect-atom/atom-react';\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as PubSub from 'effect/PubSub';\nimport * as Queue from 'effect/Queue';\n\nimport { type Operation } from '@dxos/compute';\nimport { EffectEx } from '@dxos/effect';\nimport { invariant } from '@dxos/invariant';\n\nimport { ActivationEvents, Capabilities } from '../common';\nimport { ActivationEvent, type Capability, type CapabilityManager, type Plugin, PluginManager } from '../core';\n\nexport type TestAppOptions = {\n /**\n * Plugins to register. Plugins whose `meta.profile.tags` includes `'system'` are treated as core\n * (force-enabled). For test convenience, plugins without a `'system'` tag are enabled by\n * default unless `enabled` is provided.\n */\n plugins: Plugin.Plugin[];\n /** Plugin ids that are enabled by default in addition to core. Defaults to all non-system plugin ids. */\n enabled?: string[];\n /** Additional activation events fired alongside SetupReactSurface. */\n setupEvents?: ActivationEvent.ActivationEvent[];\n /**\n * Whether to automatically fire SetupReactSurface + Startup during setup.\n * Defaults to true.\n */\n autoStart?: boolean;\n /**\n * Whether to register the PluginManager + AtomRegistry framework capabilities.\n * Defaults to true.\n */\n registerFrameworkCapabilities?: boolean;\n};\n\n/**\n * A running plugin manager plus helpers for driving it in tests.\n */\nexport interface TestHarness {\n readonly manager: PluginManager.PluginManager;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.Registry;\n\n /** Activate the given event. Equivalent to `manager.activate(event)`. */\n fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;\n /** Re-activate all modules that were activated by the given event. */\n reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;\n\n /** Returns the first contributed capability for the given interface. Throws if none are present. */\n get<T>(iface: Capability.InterfaceDef<T>): T;\n /** Returns all contributed capabilities for the given interface. */\n getAll<T>(iface: Capability.InterfaceDef<T>): T[];\n /** Waits until at least one capability is contributed for the given interface. */\n waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T>;\n /** Waits until the given activation event has completed. */\n waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void>;\n\n /** Invokes an operation through the `Capabilities.OperationInvoker` capability. */\n invoke<I, O>(op: Operation.Definition<I, O>, ...args: void extends I ? [input?: I] : [input: I]): Promise<O>;\n\n /**\n * Waits for `Capabilities.ProcessManagerRuntime` and runs the given effect on it.\n * Convenience around `waitForCapability(ProcessManagerRuntime).runPromise(effect)`.\n */\n runPromise<A, E>(\n effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,\n options?: { readonly timeout?: number; readonly signal?: AbortSignal },\n ): Promise<A>;\n\n enable(id: string): Promise<boolean>;\n disable(id: string): Promise<boolean>;\n\n /** Shuts down the underlying plugin manager. */\n dispose(): Promise<void>;\n\n /** Async-disposable support so tests can use `await using harness = ...`. */\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5_000;\n\n/**\n * Creates a TestHarness with the same bootstrap sequence that `useApp` performs,\n * minus the React provider tree.\n *\n * For Node-only tests, this is enough to fire activation events, read\n * capabilities, and invoke operations.\n *\n * For React tests, pass the returned harness to `render` or `renderSurface`\n * from `@dxos/app-framework/testing-react`.\n */\nexport const createTestApp = async (opts: TestAppOptions): Promise<TestHarness> => {\n const {\n plugins,\n enabled = plugins\n .filter(({ meta }) => !meta.profile.tags?.includes('system'))\n .map((plugin) => plugin.meta.profile.key),\n setupEvents = [],\n autoStart = true,\n registerFrameworkCapabilities = true,\n } = opts;\n\n const pluginLoader = (id: string) =>\n Effect.sync(() => {\n const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n });\n\n const manager = PluginManager.make({ pluginLoader, plugins, enabled });\n\n if (registerFrameworkCapabilities) {\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n }\n\n if (autoStart) {\n try {\n await EffectEx.runAndForwardErrors(\n Effect.all([\n ...setupEvents.map((event) => manager.activate(event)),\n manager.activate(ActivationEvents.SetupReactSurface),\n manager.activate(ActivationEvents.Startup),\n ]),\n );\n } catch (err) {\n await EffectEx.runAndForwardErrors(manager.shutdown()).catch(() => undefined);\n throw err;\n }\n }\n\n return new TestHarnessImpl(manager);\n};\n\nclass TestHarnessImpl implements TestHarness {\n constructor(readonly manager: PluginManager.PluginManager) {}\n\n get capabilities(): CapabilityManager.CapabilityManager {\n return this.manager.capabilities;\n }\n\n get registry(): Registry.Registry {\n return this.manager.registry;\n }\n\n fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.activate(event));\n }\n\n reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.reset(event));\n }\n\n get<T>(iface: Capability.InterfaceDef<T>): T {\n return this.manager.capabilities.get(iface);\n }\n\n getAll<T>(iface: Capability.InterfaceDef<T>): T[] {\n return this.manager.capabilities.getAll(iface);\n }\n\n waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n return EffectEx.runAndForwardErrors(\n this.manager.capabilities.waitFor(iface).pipe(\n Effect.timeoutFail({\n duration: Duration.millis(timeout),\n onTimeout: () => timeoutError(iface.identifier),\n }),\n ),\n );\n }\n\n waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void> {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n\n const program = Effect.gen(this, function* () {\n const queue = yield* PubSub.subscribe(this.manager.activation);\n // Re-check after subscribing to avoid a race where the event fires\n // between the caller invoking this and the subscription being installed.\n if (this.manager.getEventsFired().includes(key)) {\n return;\n }\n while (true) {\n const message = yield* Queue.take(queue);\n if (message.event === key && message.state === 'activated') {\n return;\n }\n }\n }).pipe(\n Effect.scoped,\n Effect.timeoutFail({\n duration: Duration.millis(timeout),\n onTimeout: () => timeoutError(key),\n }),\n );\n\n return EffectEx.runAndForwardErrors(program);\n }\n\n async invoke<I, O>(op: Operation.Definition<I, O>, ...args: [input?: I]): Promise<O> {\n const invoker = await this.waitForCapability(Capabilities.OperationInvoker);\n const result = await invoker.invokePromise(op as any, ...(args as [any]));\n if (result.error) {\n throw result.error;\n }\n return result.data as O;\n }\n\n async runPromise<A, E>(\n effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,\n options?: { readonly timeout?: number; readonly signal?: AbortSignal },\n ): Promise<A> {\n const runtime = await this.waitForCapability(Capabilities.ProcessManagerRuntime, { timeout: options?.timeout });\n return runtime.runPromise(effect, options?.signal ? { signal: options.signal } : undefined);\n }\n\n enable(id: string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.enable(id));\n }\n\n disable(id: string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.disable(id));\n }\n\n async dispose(): Promise<void> {\n await EffectEx.runAndForwardErrors(this.manager.shutdown());\n }\n\n [Symbol.asyncDispose](): Promise<void> {\n return this.dispose();\n }\n}\n\nconst timeoutError = (id: string) => new Error(`Timed out waiting for ${id}`);\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { type Operation } from '@dxos/compute';\n\nimport { Capabilities } from '../common';\nimport { Capability } from '../core';\n\nexport type CapturedCall<I = unknown> = {\n /** The DXN key string of the invoked operation. */\n operationKey: string;\n /** The input passed to the operation. */\n input: I;\n};\n\ntype CapabilityManagerLike = {\n get: (cap: Capability.InterfaceDef<Capabilities.OperationInvoker>) => Capabilities.OperationInvoker;\n getAll: (cap: Capability.InterfaceDef<Capabilities.OperationInvoker>) => Capabilities.OperationInvoker[];\n};\n\nexport type OperationCapture = {\n /**\n * Wraps the real OperationInvoker from the given manager. Pass to\n * `withPluginManager({ capabilities: (m) => capture.wrap(m) })`.\n */\n wrap(manager: CapabilityManagerLike): Capability.Any[];\n /** Returns all recorded calls (mocked or real) for the given operation. */\n getCalls<I, O>(op: Operation.Definition<I, O>): CapturedCall<I>[];\n /** Clears all recorded calls (useful between play function steps). */\n reset(): void;\n};\n\n/**\n * Creates a capture that wraps the real `Capabilities.OperationInvoker`:\n *\n * - **Mocked operations** (declared in `mockedOperations`) are intercepted: the call is recorded\n * and returns `{ data: undefined }` without executing. Use this for side-effecting operations\n * you don't want to run in tests, such as `LayoutOperation.Open` (navigation).\n *\n * - **All other operations** are forwarded to the real invoker and still execute normally. The\n * call is still recorded so you can assert it was triggered even though it ran for real.\n *\n * Pass a `spyFn` wrapper (e.g. `fn` from `storybook/test`) to get Storybook Actions panel\n * integration and vi-style matchers on the recording.\n *\n * @example\n * ```ts\n * import { fn } from 'storybook/test';\n *\n * const capture = makeOperationCapture(\n * // These ops are mocked: captured but not executed.\n * [AssistantOperation.RunPromptInNewChat, LayoutOperation.Open],\n * fn,\n * );\n *\n * // Wire into withPluginManager:\n * capabilities: (manager) => capture.wrap(manager)\n *\n * // Assert in a play function:\n * const calls = capture.getCalls(AssistantOperation.RunPromptInNewChat);\n * expect(calls).toHaveLength(1);\n * expect(calls[0].input.prompt).toBe('Draft a new document');\n * ```\n *\n * @idiom org.dxos.app-framework.testing.operationCapture\n * applies: Storybook play-function tests for components that call plugin operations\n * instead-of: Loading every plugin whose operations the component triggers\n * uses: {@link makeOperationCapture}, {@link withPluginManager}\n */\nexport const makeOperationCapture = (\n mockedOperations: readonly Operation.Definition.Any[],\n spyFn?: (impl: (...args: any[]) => any) => any,\n): OperationCapture => {\n const calls: CapturedCall[] = [];\n\n const mockedKeys = new Set(mockedOperations.map((op) => String(op.meta.key)));\n\n const record = (op: Operation.Definition<any, any>, input?: unknown) => {\n calls.push({ operationKey: String(op.meta.key), input: input ?? {} });\n };\n\n const recordFn = spyFn ? spyFn(record) : record;\n\n return {\n wrap(manager) {\n // Use getAll to find the real invoker that was registered before our wrapper. manager.get\n // returns the last contribution (ours, once added), but getAll returns them all in order.\n // On first invocation (when activation is complete) we find the non-wrapper contribution.\n let real: Capabilities.OperationInvoker | undefined;\n const delegate = () => {\n if (!real) {\n const all = manager.getAll(Capabilities.OperationInvoker);\n real = all.find((inv) => inv !== wrapped);\n }\n return real;\n };\n\n const wrapped: Capabilities.OperationInvoker = {\n get invocations() {\n return delegate()!.invocations;\n },\n get pendingFollowups() {\n return delegate()!.pendingFollowups;\n },\n get awaitFollowups() {\n return delegate()!.awaitFollowups;\n },\n invoke: (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return Effect.succeed(undefined as any);\n }\n return (delegate()!.invoke as any)(op, input, ...rest);\n },\n invokePromise: async (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return { data: undefined };\n }\n return (delegate()!.invokePromise as any)(op, input, ...rest);\n },\n schedule: (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return Effect.succeed(undefined);\n }\n return (delegate()!.schedule as any)(op, input, ...rest);\n },\n };\n\n return [Capability.contributes(Capabilities.OperationInvoker, wrapped)];\n },\n getCalls<I, O>(op: Operation.Definition<I, O>): CapturedCall<I>[] {\n const key = String(op.meta.key);\n return calls.filter((c) => c.operationKey === key) as CapturedCall<I>[];\n },\n reset() {\n calls.length = 0;\n },\n };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nimport { invariant } from '@dxos/invariant';\n\nimport { ActivationEvents, Capabilities } from '../common';\nimport { Plugin, PluginManager } from '../core';\n\n/**\n * Creates a Plugin.Service layer from a list of plugins.\n * This is primarily used for testing.\n */\nexport const fromPlugins = (plugins: Plugin.Plugin[]) =>\n Layer.effect(\n Plugin.Service,\n Effect.gen(function* () {\n // TODO(wittjosiah): Try to dedupe logic between here, createCliApp and useApp.\n\n const pluginLoader = (id: string) =>\n Effect.sync(() => {\n const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n });\n\n const manager = PluginManager.make({\n pluginLoader,\n plugins,\n enabled: plugins.map((plugin) => plugin.meta.profile.key),\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n\n yield* manager.activate(ActivationEvents.Startup);\n\n return manager;\n }),\n );\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Decorator, type StoryContext } from '@storybook/react';\nimport * as Effect from 'effect/Effect';\nimport React, { useEffect, useState } from 'react';\n\nimport { raise } from '@dxos/debug';\nimport { EffectEx } from '@dxos/effect';\nimport { DXN } from '@dxos/keys';\nimport { useAsyncEffect } from '@dxos/react-hooks';\nimport { type MaybeProvider, getProviderValue } from '@dxos/util';\n\nimport { ActivationEvents, Capabilities } from '../common';\nimport { type ActivationEvent, Capability, type CapabilityManager, Plugin, PluginManager } from '../core';\nimport { type UseAppOptions, useApp } from '../ui';\n\n/**\n * @internal\n */\nexport const setupPluginManager = ({\n capabilities,\n plugins = [],\n ...options\n}: UseAppOptions & Pick<WithPluginManagerOptions, 'capabilities'> = {}) => {\n // Auto-enable every non-system plugin so stories don't have to spell out\n // enablement. System-tagged plugins are force-enabled by the manager.\n const enabled = plugins\n .filter(({ meta }) => !meta.profile.tags?.includes('system'))\n .map(({ meta }) => meta.profile.key);\n const pluginManager = PluginManager.make({\n pluginLoader: () => raise(new Error('Not implemented')),\n plugins: [StoryPlugin, ...plugins],\n enabled,\n ...options,\n });\n\n if (capabilities) {\n getProviderValue(capabilities, pluginManager.capabilities).forEach((capability) => {\n pluginManager.capabilities.contribute({\n interface: capability.interface,\n implementation: capability.implementation,\n module: 'story',\n });\n });\n }\n\n return pluginManager;\n};\n\ntype ManagedPluginManagerState = {\n fireEvents?: (ActivationEvent.ActivationEvent | string)[];\n pluginManager: PluginManager.PluginManager;\n setupEvents?: ActivationEvent.ActivationEvent[];\n storyId: string;\n};\n\nexport type WithPluginManagerOptions = UseAppOptions & {\n /** @deprecated */\n capabilities?: MaybeProvider<Capability.Any[], CapabilityManager.CapabilityManager>;\n /** @deprecated */\n fireEvents?: (ActivationEvent.ActivationEvent | string)[];\n};\n\nexport type WithPluginManagerInitializer<Args = void> =\n | WithPluginManagerOptions\n | ((context: StoryContext<Args>) => WithPluginManagerOptions);\n\n/**\n * Wraps a story with a plugin manager.\n * NOTE: This builds up and tears down the plugin manager on every render.\n */\nexport const withPluginManager = <Args,>(init: WithPluginManagerInitializer<Args> = {}): Decorator => {\n return (Story, context) => {\n const storyId = context.id;\n const options = typeof init === 'function' ? init(context as any) : init;\n const [managerState, setManagerState] = useState<ManagedPluginManagerState>();\n\n // Storybook replaces the full context object often, so key manager ownership by story id.\n useEffect(() => {\n const pluginManager = setupPluginManager(options);\n const capability = Capability.contributes(Capabilities.ReactRoot, {\n id: storyId,\n root: () => <Story />,\n });\n\n pluginManager.capabilities.contribute({\n ...capability,\n module: 'org.dxos.app-framework.with-plugin-manager',\n });\n\n setManagerState({\n pluginManager,\n setupEvents: options.setupEvents,\n fireEvents: options.fireEvents,\n storyId,\n });\n\n return () => {\n pluginManager.capabilities.remove(capability.interface, capability.implementation);\n void EffectEx.runAndForwardErrors(pluginManager.shutdown());\n };\n }, [storyId, init]);\n\n // Avoid mounting useApp with a stale manager from the previous story.\n if (!managerState || managerState.storyId !== storyId) {\n return <></>;\n }\n\n return <WithPluginManagerApp {...managerState} />;\n };\n};\n\nconst WithPluginManagerApp = ({ fireEvents, pluginManager, setupEvents, storyId }: ManagedPluginManagerState) => {\n // Fire deprecated events only after the effect-owned manager for this story exists.\n useAsyncEffect(async () => {\n await Promise.all(fireEvents?.map((event) => pluginManager.activate(event)) ?? []);\n }, [fireEvents, pluginManager, storyId]);\n\n const App = useApp({ pluginManager, setupEvents });\n return <App />;\n};\n\nconst storyMeta = Plugin.makeMeta({\n key: DXN.make('org.dxos.appFramework.story'),\n name: 'Story',\n tags: ['system'],\n});\n\n// No-op plugin to ensure there exists at least one plugin for the startup event.\n// This is necessary because `createApp` expects the startup event to complete before the app is ready.\nconst StoryPlugin = Plugin.define(storyMeta).pipe(\n Plugin.addModule({\n id: 'Story',\n activatesOn: ActivationEvents.Startup,\n activate: () => Effect.succeed([]),\n }),\n Plugin.make,\n)();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Duration", "Effect", "PubSub", "Queue", "EffectEx", "invariant", "DEFAULT_TIMEOUT_MS", "pluginLoader", "Effect", "sync", "plugin", "plugins", "meta", "profile", "key", "id", "manager", "enabled", "registerFrameworkCapabilities", "PluginManager", "implementation", "module", "capabilities", "registry", "autoStart", "EffectEx", "activate", "SetupReactSurface", "ActivationEvents", "Startup", "err", "TestHarnessImpl", "fire", "reset", "iface", "getAll", "waitForCapability", "runAndForwardErrors", "duration", "Duration", "timeout", "onTimeout", "identifier", "waitForEvent", "opts", "program", "queue", "subscribe", "message", "timeoutError", "invoke", "args", "result", "invoker", "error", "data", "runPromise", "effect", "options", "runtime", "undefined", "enable", "disable", "dispose", "Symbol", "asyncDispose", "Effect", "makeOperationCapture", "mockedOperations", "spyFn", "calls", "mockedKeys", "Set", "map", "op", "String", "meta", "key", "record", "input", "push", "operationKey", "recordFn", "wrap", "manager", "real", "delegate", "all", "getAll", "Capabilities", "OperationInvoker", "find", "inv", "wrapped", "invocations", "pendingFollowups", "awaitFollowups", "invoke", "rest", "has", "succeed", "undefined", "invokePromise", "data", "schedule", "Capability", "contributes", "getCalls", "filter", "c", "reset", "length", "Effect", "Layer", "invariant", "__dxlog_file", "pluginLoader", "id", "plugin", "manager", "plugins", "enabled", "capabilities", "contribute", "implementation", "module", "registry", "Effect", "React", "useEffect", "useState", "raise", "EffectEx", "DXN", "useAsyncEffect", "getProviderValue", "setupPluginManager", "capabilities", "plugins", "options", "enabled", "filter", "meta", "profile", "tags", "includes", "map", "key", "pluginManager", "PluginManager", "make", "pluginLoader", "raise", "Error", "StoryPlugin", "getProviderValue", "forEach", "capability", "contribute", "interface", "implementation", "module", "withPluginManager", "init", "Story", "context", "storyId", "id", "managerState", "setManagerState", "useState", "useEffect", "Capability", "contributes", "Capabilities", "ReactRoot", "root", "setupEvents", "fireEvents", "remove", "EffectEx", "runAndForwardErrors", "shutdown", "WithPluginManagerApp", "useAsyncEffect", "Promise", "all", "event", "activate", "App", "useApp", "storyMeta", "Plugin", "makeMeta", "DXN", "name", "define", "pipe", "addModule", "activatesOn", "ActivationEvents", "Startup", "succeed"]
|
|
7
7
|
}
|
|
@@ -2,21 +2,21 @@ import {
|
|
|
2
2
|
PluginManagerProvider,
|
|
3
3
|
SurfaceComponent,
|
|
4
4
|
topologicalSort
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-U5MESPM5.mjs";
|
|
6
6
|
import {
|
|
7
7
|
PluginManagerContext
|
|
8
8
|
} from "../chunk-FJ4765WW.mjs";
|
|
9
9
|
import "../chunk-Q2GLJTVV.mjs";
|
|
10
10
|
import {
|
|
11
11
|
capabilities_exports
|
|
12
|
-
} from "../chunk-
|
|
13
|
-
import "../chunk-
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-
|
|
19
|
-
import "../chunk-
|
|
12
|
+
} from "../chunk-NKVRSMFN.mjs";
|
|
13
|
+
import "../chunk-VF37YTXJ.mjs";
|
|
14
|
+
import "../chunk-YUVQIOTB.mjs";
|
|
15
|
+
import "../chunk-LUH4Y5F2.mjs";
|
|
16
|
+
import "../chunk-UGYCLOXE.mjs";
|
|
17
|
+
import "../chunk-3NQLTQCP.mjs";
|
|
18
|
+
import "../chunk-OO53M5UK.mjs";
|
|
19
|
+
import "../chunk-OPTS3ZSN.mjs";
|
|
20
20
|
import "../chunk-J5LGTIGS.mjs";
|
|
21
21
|
|
|
22
22
|
// src/testing/react.tsx
|
|
@@ -36,9 +36,9 @@ var render = (harness, ui, options) => {
|
|
|
36
36
|
});
|
|
37
37
|
};
|
|
38
38
|
var renderSurface = (harness, props, options) => {
|
|
39
|
-
const {
|
|
39
|
+
const { type, data, limit, fallback, placeholder } = props;
|
|
40
40
|
return render(harness, /* @__PURE__ */ React.createElement(SurfaceComponent, {
|
|
41
|
-
|
|
41
|
+
type,
|
|
42
42
|
data,
|
|
43
43
|
limit,
|
|
44
44
|
fallback,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/testing/react.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport { RegistryContext } from '@effect-atom/atom-react';\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;AAIA,SAASA,uBAAuB;AAChC,
|
|
6
|
-
"names": ["RegistryContext", "render", "rtlRender", "React", "Fragment", "ContextProtocolProvider", "render", "harness", "ui", "options", "reactContexts", "rest", "Wrapper", "children", "HarnessProviders", "extra", "rtlRender", "wrapper", "renderSurface", "props", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport { RegistryContext } from '@effect-atom/atom-react';\nimport { type RenderOptions, type RenderResult, render as rtlRender } from '@testing-library/react';\nimport React, { type FC, Fragment, type PropsWithChildren, type ReactNode } from 'react';\n\nimport { ContextProtocolProvider } from '@dxos/web-context-react';\n\nimport { Capabilities } from '../common';\nimport { PluginManagerContext } from '../context';\nimport { topologicalSort } from '../helpers';\nimport { PluginManagerProvider } from '../ui/components/PluginManager/PluginManagerProvider';\nimport { SurfaceComponent } from '../ui/components/Surface/SurfaceComponent';\nimport { type RoleToken } from '../ui/components/Surface/types';\nimport { type TestHarness } from './harness';\n\nexport type HarnessRenderOptions = Omit<RenderOptions, 'wrapper'> & {\n /** Additional providers to wrap around the harness tree (applied innermost first). */\n reactContexts?: FC<PropsWithChildren>[];\n};\n\n/**\n * Renders `ui` wrapped in the same provider tree as `useApp` plus every contributed\n * `Capabilities.ReactContext`.\n */\nexport const render = (harness: TestHarness, ui: ReactNode, options?: HarnessRenderOptions): RenderResult => {\n const { reactContexts = [], ...rest } = options ?? {};\n const Wrapper = ({ children }: PropsWithChildren) => (\n <HarnessProviders harness={harness} extra={reactContexts}>\n {children}\n </HarnessProviders>\n );\n return rtlRender(<>{ui}</>, { ...rest, wrapper: Wrapper });\n};\n\nexport type RenderSurfaceProps<TToken extends RoleToken<any>> = {\n type: TToken;\n data?: TToken extends RoleToken<infer D> ? D : never;\n limit?: number;\n fallback?: FC<{ error: Error; data?: any }>;\n placeholder?: ReactNode;\n};\n\n/**\n * Renders a `Surface` with the given role token/data inside the harness provider tree.\n */\nexport const renderSurface = <TToken extends RoleToken<any>>(\n harness: TestHarness,\n props: RenderSurfaceProps<TToken>,\n options?: HarnessRenderOptions,\n): RenderResult => {\n const { type, data, limit, fallback, placeholder } = props;\n return render(\n harness,\n <SurfaceComponent type={type} data={data as any} limit={limit} fallback={fallback} placeholder={placeholder} />,\n options,\n );\n};\n\ntype HarnessProvidersProps = PropsWithChildren<{\n harness: TestHarness;\n extra: FC<PropsWithChildren>[];\n}>;\n\nconst HarnessProviders = ({ harness, extra, children }: HarnessProvidersProps) => {\n const contributed = harness.getAll(Capabilities.ReactContext);\n const ContributedContext = composeContexts(contributed);\n const ExtraContext = composeExtra(extra);\n return (\n <PluginManagerProvider value={harness.manager}>\n <ContextProtocolProvider value={harness.manager} context={PluginManagerContext}>\n <RegistryContext.Provider value={harness.registry}>\n <ContributedContext>\n <ExtraContext>{children}</ExtraContext>\n </ContributedContext>\n </RegistryContext.Provider>\n </ContextProtocolProvider>\n </PluginManagerProvider>\n );\n};\n\nconst composeContexts = (contexts: Capabilities.ReactContext[]): FC<PropsWithChildren> => {\n if (contexts.length === 0) {\n return Passthrough;\n }\n return topologicalSort(contexts)\n .map(({ context }) => context)\n .reduce((Acc, Next) => ({ children }: PropsWithChildren) => (\n <Acc>\n <Next>{children}</Next>\n </Acc>\n ));\n};\n\n// Composes in innermost-first order: the first context in the array wraps\n// `children` directly; subsequent contexts wrap the accumulator.\nconst composeExtra = (contexts: FC<PropsWithChildren>[]): FC<PropsWithChildren> => {\n if (contexts.length === 0) {\n return Passthrough;\n }\n return contexts.reduce<FC<PropsWithChildren>>(\n (Acc, Next) =>\n ({ children }: PropsWithChildren) => (\n <Next>\n <Acc>{children}</Acc>\n </Next>\n ),\n Passthrough,\n );\n};\n\nconst Passthrough: FC<PropsWithChildren> = ({ children }) => <Fragment>{children}</Fragment>;\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;AAIA,SAASA,uBAAuB;AAChC,SAAgDC,UAAUC,iBAAiB;AAC3E,OAAOC,SAAkBC,gBAAwD;AAEjF,SAASC,+BAA+B;AAmBjC,IAAMC,SAAS,CAACC,SAAsBC,IAAeC,YAAAA;AAC1D,QAAM,EAAEC,gBAAgB,CAAA,GAAI,GAAGC,KAAAA,IAASF,WAAW,CAAC;AACpD,QAAMG,UAAU,CAAC,EAAEC,SAAQ,MACzB,sBAAA,cAACC,kBAAAA;IAAiBP;IAAkBQ,OAAOL;KACxCG,QAAAA;AAGL,SAAOG,UAAU,sBAAA,cAAA,MAAA,UAAA,MAAGR,EAAAA,GAAQ;IAAE,GAAGG;IAAMM,SAASL;EAAQ,CAAA;AAC1D;AAaO,IAAMM,gBAAgB,CAC3BX,SACAY,OACAV,YAAAA;AAEA,QAAM,EAAEW,MAAMC,MAAMC,OAAOC,UAAUC,YAAW,IAAKL;AACrD,SAAOb,OACLC,SACA,sBAAA,cAACkB,kBAAAA;IAAiBL;IAAYC;IAAmBC;IAAcC;IAAoBC;MACnFf,OAAAA;AAEJ;AAOA,IAAMK,mBAAmB,CAAC,EAAEP,SAASQ,OAAOF,SAAQ,MAAyB;AAC3E,QAAMa,cAAcnB,QAAQoB,OAAOC,qBAAaC,YAAY;AAC5D,QAAMC,qBAAqBC,gBAAgBL,WAAAA;AAC3C,QAAMM,eAAeC,aAAalB,KAAAA;AAClC,SACE,sBAAA,cAACmB,uBAAAA;IAAsBC,OAAO5B,QAAQ6B;KACpC,sBAAA,cAACC,yBAAAA;IAAwBF,OAAO5B,QAAQ6B;IAASE,SAASC;KACxD,sBAAA,cAACC,gBAAgBC,UAAQ;IAACN,OAAO5B,QAAQmC;KACvC,sBAAA,cAACZ,oBAAAA,MACC,sBAAA,cAACE,cAAAA,MAAcnB,QAAAA,CAAAA,CAAAA,CAAAA,CAAAA;AAM3B;AAEA,IAAMkB,kBAAkB,CAACY,aAAAA;AACvB,MAAIA,SAASC,WAAW,GAAG;AACzB,WAAOC;EACT;AACA,SAAOC,gBAAgBH,QAAAA,EACpBI,IAAI,CAAC,EAAET,QAAO,MAAOA,OAAAA,EACrBU,OAAO,CAACC,KAAKC,SAAS,CAAC,EAAErC,SAAQ,MAChC,sBAAA,cAACoC,KAAAA,MACC,sBAAA,cAACC,MAAAA,MAAMrC,QAAAA,CAAAA,CAAAA;AAGf;AAIA,IAAMoB,eAAe,CAACU,aAAAA;AACpB,MAAIA,SAASC,WAAW,GAAG;AACzB,WAAOC;EACT;AACA,SAAOF,SAASK,OACd,CAACC,KAAKC,SACJ,CAAC,EAAErC,SAAQ,MACT,sBAAA,cAACqC,MAAAA,MACC,sBAAA,cAACD,KAAAA,MAAKpC,QAAAA,CAAAA,GAGZgC,WAAAA;AAEJ;AAEA,IAAMA,cAAqC,CAAC,EAAEhC,SAAQ,MAAO,sBAAA,cAACsC,UAAAA,MAAUtC,QAAAA;",
|
|
6
|
+
"names": ["RegistryContext", "render", "rtlRender", "React", "Fragment", "ContextProtocolProvider", "render", "harness", "ui", "options", "reactContexts", "rest", "Wrapper", "children", "HarnessProviders", "extra", "rtlRender", "wrapper", "renderSurface", "props", "type", "data", "limit", "fallback", "placeholder", "SurfaceComponent", "contributed", "getAll", "Capabilities", "ReactContext", "ContributedContext", "composeContexts", "ExtraContext", "composeExtra", "PluginManagerProvider", "value", "manager", "ContextProtocolProvider", "context", "PluginManagerContext", "RegistryContext", "Provider", "registry", "contexts", "length", "Passthrough", "topologicalSort", "map", "reduce", "Acc", "Next", "Fragment"]
|
|
7
7
|
}
|
|
@@ -8,27 +8,31 @@ import {
|
|
|
8
8
|
useCapability,
|
|
9
9
|
useLoading,
|
|
10
10
|
useOperationInvoker,
|
|
11
|
+
useOptionalAtomCapabilityState,
|
|
12
|
+
useOptionalCapabilities,
|
|
13
|
+
useOptionalCapability,
|
|
11
14
|
useProcessManagerRuntime,
|
|
12
15
|
useSettingsState,
|
|
13
16
|
useSpaceCallback,
|
|
14
17
|
useSpaceService
|
|
15
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-KRJ4KK2W.mjs";
|
|
16
19
|
import {
|
|
17
20
|
PluginManagerProvider,
|
|
18
21
|
Surface,
|
|
22
|
+
useOptionalPluginManager,
|
|
19
23
|
usePluginManager,
|
|
20
24
|
useSurface
|
|
21
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-U5MESPM5.mjs";
|
|
22
26
|
import "../chunk-FJ4765WW.mjs";
|
|
23
27
|
import "../chunk-Q2GLJTVV.mjs";
|
|
24
|
-
import "../chunk-
|
|
25
|
-
import "../chunk-
|
|
26
|
-
import "../chunk-
|
|
27
|
-
import "../chunk-
|
|
28
|
-
import "../chunk-
|
|
29
|
-
import "../chunk-
|
|
30
|
-
import "../chunk-
|
|
31
|
-
import "../chunk-
|
|
28
|
+
import "../chunk-NKVRSMFN.mjs";
|
|
29
|
+
import "../chunk-VF37YTXJ.mjs";
|
|
30
|
+
import "../chunk-YUVQIOTB.mjs";
|
|
31
|
+
import "../chunk-LUH4Y5F2.mjs";
|
|
32
|
+
import "../chunk-UGYCLOXE.mjs";
|
|
33
|
+
import "../chunk-3NQLTQCP.mjs";
|
|
34
|
+
import "../chunk-OO53M5UK.mjs";
|
|
35
|
+
import "../chunk-OPTS3ZSN.mjs";
|
|
32
36
|
import "../chunk-J5LGTIGS.mjs";
|
|
33
37
|
export {
|
|
34
38
|
App,
|
|
@@ -42,6 +46,10 @@ export {
|
|
|
42
46
|
useCapability,
|
|
43
47
|
useLoading,
|
|
44
48
|
useOperationInvoker,
|
|
49
|
+
useOptionalAtomCapabilityState,
|
|
50
|
+
useOptionalCapabilities,
|
|
51
|
+
useOptionalCapability,
|
|
52
|
+
useOptionalPluginManager,
|
|
45
53
|
usePluginManager,
|
|
46
54
|
useProcessManagerRuntime,
|
|
47
55
|
useSettingsState,
|
|
@@ -6,16 +6,16 @@ import {
|
|
|
6
6
|
import "./chunk-FPW45EZH.mjs";
|
|
7
7
|
import {
|
|
8
8
|
capabilities_exports
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-XSZMX53L.mjs";
|
|
10
|
+
import "./chunk-TLKYZKPW.mjs";
|
|
11
|
+
import "./chunk-VCPGX7WN.mjs";
|
|
12
|
+
import "./chunk-FKMVORZN.mjs";
|
|
13
|
+
import "./chunk-IL7O7IRX.mjs";
|
|
14
|
+
import "./chunk-BMW6P6QA.mjs";
|
|
15
|
+
import "./chunk-4SE7SX7N.mjs";
|
|
16
16
|
import {
|
|
17
17
|
capability_exports
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-GLH4LGHZ.mjs";
|
|
19
19
|
import "./chunk-HSLMI22Q.mjs";
|
|
20
20
|
|
|
21
21
|
// src/plugin-process-manager/history/capability.ts
|
|
@@ -33,4 +33,4 @@ var capability_default = capability_exports.makeModule(Effect.fnUntraced(functio
|
|
|
33
33
|
export {
|
|
34
34
|
capability_default as default
|
|
35
35
|
};
|
|
36
|
-
//# sourceMappingURL=capability-
|
|
36
|
+
//# sourceMappingURL=capability-3YRF77LV.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getModuleTag
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GLH4LGHZ.mjs";
|
|
5
5
|
import {
|
|
6
6
|
__export
|
|
7
7
|
} from "./chunk-HSLMI22Q.mjs";
|
|
@@ -10,13 +10,18 @@ import {
|
|
|
10
10
|
var plugin_exports = {};
|
|
11
11
|
__export(plugin_exports, {
|
|
12
12
|
LazyPluginError: () => LazyPluginError,
|
|
13
|
+
Meta: () => Meta,
|
|
13
14
|
PluginDependencyError: () => PluginDependencyError,
|
|
14
15
|
PluginModuleTypeId: () => PluginModuleTypeId,
|
|
15
16
|
PluginTypeId: () => PluginTypeId,
|
|
17
|
+
Profile: () => Profile,
|
|
18
|
+
Release: () => Release,
|
|
16
19
|
Service: () => Service,
|
|
17
20
|
activate: () => activate,
|
|
18
21
|
addModule: () => addModule,
|
|
19
22
|
define: () => define,
|
|
23
|
+
getMetaFromConfig: () => getMetaFromConfig,
|
|
24
|
+
getURI: () => getURI,
|
|
20
25
|
isLazy: () => isLazy,
|
|
21
26
|
isPlugin: () => isPlugin,
|
|
22
27
|
isPluginModule: () => isPluginModule,
|
|
@@ -31,9 +36,11 @@ import * as Context from "effect/Context";
|
|
|
31
36
|
import * as Effect from "effect/Effect";
|
|
32
37
|
import * as Option from "effect/Option";
|
|
33
38
|
import * as Pipeable from "effect/Pipeable";
|
|
39
|
+
import * as Schema from "effect/Schema";
|
|
34
40
|
import { BaseError } from "@dxos/errors";
|
|
35
41
|
import { invariant } from "@dxos/invariant";
|
|
36
42
|
import { DXN } from "@dxos/keys";
|
|
43
|
+
import { PluginProfileSchema, PluginReleaseSchema } from "@dxos/protocols";
|
|
37
44
|
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-framework/src/core/plugin.ts";
|
|
38
45
|
var Service = class extends Context.Tag("@dxos/app-framework/PluginManager")() {
|
|
39
46
|
};
|
|
@@ -62,11 +69,32 @@ var PluginModuleImpl = class {
|
|
|
62
69
|
this.activate = options.activate;
|
|
63
70
|
}
|
|
64
71
|
};
|
|
65
|
-
var
|
|
66
|
-
...
|
|
67
|
-
|
|
68
|
-
version: DXN.getVersion(options.key)
|
|
72
|
+
var Profile = Schema.Struct({
|
|
73
|
+
...PluginProfileSchema.fields,
|
|
74
|
+
author: Schema.optional(Schema.String)
|
|
69
75
|
});
|
|
76
|
+
var Release = PluginReleaseSchema;
|
|
77
|
+
var Meta = Schema.Struct({
|
|
78
|
+
profile: Profile,
|
|
79
|
+
release: Schema.optional(Release)
|
|
80
|
+
});
|
|
81
|
+
var makeMeta = (options) => {
|
|
82
|
+
const { key, ...rest } = options;
|
|
83
|
+
return {
|
|
84
|
+
profile: {
|
|
85
|
+
...rest,
|
|
86
|
+
key: DXN.getName(key)
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
var getURI = (meta) => DXN.make(meta.profile.key, meta.release?.version);
|
|
91
|
+
var getMetaFromConfig = ({ plugin }) => {
|
|
92
|
+
const { key, ...rest } = plugin;
|
|
93
|
+
return makeMeta({
|
|
94
|
+
key: DXN.make(key),
|
|
95
|
+
...rest
|
|
96
|
+
});
|
|
97
|
+
};
|
|
70
98
|
var PluginTypeId = /* @__PURE__ */ Symbol.for("@dxos/app-framework/Plugin");
|
|
71
99
|
var isPlugin = (value) => {
|
|
72
100
|
return typeof value === "object" && value !== null && PluginTypeId in value;
|
|
@@ -113,11 +141,11 @@ function addModule(moduleOptionsOrBuilder, moduleOptions) {
|
|
|
113
141
|
}
|
|
114
142
|
var resolveModule = (meta, module, options) => {
|
|
115
143
|
const moduleOptions = typeof module === "function" ? module(options) : module;
|
|
116
|
-
const pluginName = meta.
|
|
144
|
+
const pluginName = meta.profile.key;
|
|
117
145
|
const id = Option.fromNullable(moduleOptions.id).pipe(Option.match({
|
|
118
146
|
onNone: () => {
|
|
119
147
|
const exportName = getModuleTag(moduleOptions.activate);
|
|
120
|
-
invariant(exportName, `Plugin module missing name. Plugin: ${meta.
|
|
148
|
+
invariant(exportName, `Plugin module missing name. Plugin: ${meta.profile.key}`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 174, S: void 0, A: ["exportName", "`Plugin module missing name. Plugin: ${meta.profile.key}`"] });
|
|
121
149
|
return computeModuleId(pluginName, exportName);
|
|
122
150
|
},
|
|
123
151
|
onSome: (id2) => computeModuleId(pluginName, id2)
|
|
@@ -129,7 +157,7 @@ var resolveModule = (meta, module, options) => {
|
|
|
129
157
|
};
|
|
130
158
|
function make(builder) {
|
|
131
159
|
const meta = builder.meta;
|
|
132
|
-
invariant(!meta.dependsOn?.includes(meta.
|
|
160
|
+
invariant(!meta.profile.dependsOn?.includes(meta.profile.key), `Plugin ${meta.profile.key} declares itself as a dependency.`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 187, S: this, A: ["!meta.profile.dependsOn?.includes(meta.profile.key)", "`Plugin ${meta.profile.key} declares itself as a dependency.`"] });
|
|
133
161
|
const factory = (options) => {
|
|
134
162
|
const modules = builder.modules.map((module) => resolveModule(meta, module, options));
|
|
135
163
|
return new PluginImpl(meta, modules);
|
|
@@ -164,7 +192,7 @@ var resolveLazy = (plugin) => Effect.gen(function* () {
|
|
|
164
192
|
if (!isLazy(plugin)) {
|
|
165
193
|
return plugin;
|
|
166
194
|
}
|
|
167
|
-
const id = plugin.meta.
|
|
195
|
+
const id = plugin.meta.profile.key;
|
|
168
196
|
const { loader, options } = plugin[LazyTag];
|
|
169
197
|
const mod = yield* Effect.tryPromise({
|
|
170
198
|
try: loader,
|
|
@@ -193,12 +221,12 @@ var resolveLazy = (plugin) => Effect.gen(function* () {
|
|
|
193
221
|
}
|
|
194
222
|
}));
|
|
195
223
|
}
|
|
196
|
-
if (result.meta.
|
|
224
|
+
if (result.meta.profile.key !== id) {
|
|
197
225
|
return yield* Effect.fail(new LazyPluginError({
|
|
198
226
|
context: {
|
|
199
227
|
id,
|
|
200
228
|
reason: "meta-mismatch",
|
|
201
|
-
returnedId: result.meta.
|
|
229
|
+
returnedId: result.meta.profile.key
|
|
202
230
|
}
|
|
203
231
|
}));
|
|
204
232
|
}
|
|
@@ -212,7 +240,12 @@ export {
|
|
|
212
240
|
shutdown,
|
|
213
241
|
PluginModuleTypeId,
|
|
214
242
|
isPluginModule,
|
|
243
|
+
Profile,
|
|
244
|
+
Release,
|
|
245
|
+
Meta,
|
|
215
246
|
makeMeta,
|
|
247
|
+
getURI,
|
|
248
|
+
getMetaFromConfig,
|
|
216
249
|
PluginTypeId,
|
|
217
250
|
isPlugin,
|
|
218
251
|
define,
|
|
@@ -225,4 +258,4 @@ export {
|
|
|
225
258
|
resolveLazy,
|
|
226
259
|
plugin_exports
|
|
227
260
|
};
|
|
228
|
-
//# sourceMappingURL=chunk-
|
|
261
|
+
//# sourceMappingURL=chunk-4SE7SX7N.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/core/plugin.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\nimport * as Pipeable from 'effect/Pipeable';\nimport * as Schema from 'effect/Schema';\n\nimport { BaseError } from '@dxos/errors';\nimport { invariant } from '@dxos/invariant';\nimport { DXN } from '@dxos/keys';\nimport { Config2, PluginProfileSchema, PluginReleaseSchema } from '@dxos/protocols';\n\nimport type * as ActivationEvent from './activation-event';\nimport * as Capability from './capability';\nimport type * as PluginManager from './plugin-manager';\n\n//\n// Plugin Service Layer\n//\n\n/**\n * Effect Context.Tag for accessing PluginManager via the Effect layer system.\n * This allows lifecycle operations to access the plugin manager without having it passed as an argument.\n */\nexport class Service extends Context.Tag('@dxos/app-framework/PluginManager')<Service, PluginManager.PluginManager>() {}\n\n//\n// Lifecycle Functions\n//\n\n/**\n * Activates plugins based on the activation event.\n * Accesses the PluginManager via the Effect layer system.\n * @param event The activation event.\n * @returns Whether the activation was successful.\n */\nexport const activate = (event: ActivationEvent.ActivationEvent): Effect.Effect<boolean, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.activate(event));\n\n/**\n * Re-activates the modules that were activated by the event.\n * Accesses the PluginManager via the Effect layer system.\n * @param event The activation event.\n * @returns Whether the reset was successful.\n */\nexport const reset = (event: ActivationEvent.ActivationEvent): Effect.Effect<boolean, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.reset(event));\n\n/**\n * Shuts down the plugin manager, deactivating all active modules and clearing lifecycle state.\n * Accesses the PluginManager via the Effect layer system.\n */\nexport const shutdown = (): Effect.Effect<boolean, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.shutdown());\n\n/**\n * Computes a module ID from plugin ID and export name.\n */\nconst computeModuleId = (pluginId: string, moduleName: string): string => {\n return `${pluginId}.module.${moduleName}`;\n};\n\n/**\n * Identifier denoting a PluginModule.\n */\nexport const PluginModuleTypeId: unique symbol = Symbol.for('@dxos/app-framework/PluginModule');\nexport type PluginModuleTypeId = typeof PluginModuleTypeId;\n\n/**\n * Type guard to check if a value is a PluginModule.\n */\nexport const isPluginModule = (value: unknown): value is PluginModule => {\n return typeof value === 'object' && value !== null && PluginModuleTypeId in value;\n};\n\n/**\n * A unit of containment of modular functionality that can be provided to an application.\n * Activation of a module is async allowing for code to split and loaded lazily.\n */\nexport interface PluginModule {\n readonly [PluginModuleTypeId]: PluginModuleTypeId;\n /**\n * Unique id of the module.\n */\n id: string;\n\n /**\n * Events for which the module will be activated.\n */\n activatesOn: ActivationEvent.Events;\n\n /**\n * Events that this module fires *before* its own activation runs.\n *\n * When this module is asked to activate (via {@link activatesOn}), the\n * plugin manager first activates every event listed here, ensuring any\n * other modules that contribute to those events have completed before\n * this module's {@link activate} body executes. These events are fired\n * by the framework on this module's behalf — the module does not need\n * to wait for some other code to fire them.\n *\n * The module is marked as needing reset if a module activated by one\n * of these events is later removed.\n *\n * Read as: \"this module fires these events before [its] activation\".\n */\n firesBeforeActivation?: ActivationEvent.ActivationEvent[];\n\n /**\n * Events that this module fires *after* its own activation completes.\n *\n * Once this module's {@link activate} body has finished executing, the\n * plugin manager activates every event listed here, causing any modules\n * listening on those events to run. These events are fired by the\n * framework on this module's behalf as part of this module's lifecycle.\n *\n * Read as: \"this module fires these events after [its] activation\".\n */\n firesAfterActivation?: ActivationEvent.ActivationEvent[];\n\n /**\n * Called when the module is activated.\n * CapabilityManager is accessed via the Effect layer system (Capability.Service).\n * PluginManager is accessed via Plugin.Service.\n * @param props Optional props passed to the module.\n * @returns The capabilities of the module.\n */\n activate: (props?: any) => Effect.Effect<Capability.ModuleReturn, Error, Capability.Service | Service | never>;\n}\n\nexport type PluginModuleOptions = Omit<PluginModule, 'id' | typeof PluginModuleTypeId> & { id?: string };\n\nclass PluginModuleImpl implements PluginModule {\n readonly [PluginModuleTypeId]: PluginModuleTypeId = PluginModuleTypeId;\n readonly id: PluginModule['id'];\n readonly activatesOn: PluginModule['activatesOn'];\n readonly firesBeforeActivation?: PluginModule['firesBeforeActivation'];\n readonly firesAfterActivation?: PluginModule['firesAfterActivation'];\n readonly activate: PluginModule['activate'];\n\n constructor(options: Omit<PluginModule, typeof PluginModuleTypeId>) {\n this.id = options.id;\n this.activatesOn = options.activatesOn;\n this.firesBeforeActivation = options.firesBeforeActivation;\n this.firesAfterActivation = options.firesAfterActivation;\n this.activate = options.activate;\n }\n}\n\n/**\n * Runtime plugin metadata, derived from the `@dxos/protocols` registry schemas (protocols owns the\n * config + registry schemas; the runtime projection lives here).\n *\n * - {@link Profile}: version-independent identity + display + provenance — the wire `PluginProfileSchema`\n * (which carries `key`, the display fields, `dependsOn`, `spec`) plus `author` (resolved at runtime\n * from the publisher's handle/DID for registry plugins, or self-declared for bundled).\n * - {@link Release}: a specific hosted release — the wire `PluginReleaseSchema` (version, moduleUrl, dependencies).\n * - {@link Meta}: a resolved single-release view — `{ profile, release? }`, both nested. `release` is\n * unset for bundled plugins (compiled in) and set for registry plugins.\n */\nexport const Profile = Schema.Struct({\n ...PluginProfileSchema.fields,\n author: Schema.optional(Schema.String),\n});\nexport type Profile = Schema.Schema.Type<typeof Profile>;\n\nexport const Release = PluginReleaseSchema;\nexport type Release = Schema.Schema.Type<typeof Release>;\n\nexport const Meta = Schema.Struct({\n profile: Profile,\n release: Schema.optional(Release),\n});\nexport type Meta = Schema.Schema.Type<typeof Meta>;\n\n/** Options for {@link makeMeta}: the {@link Profile} content fields plus the canonical DXN `key`. */\nexport type MakeMetaOptions = {\n key: DXN.DXN;\n name: string;\n description?: string;\n author?: string;\n homePage?: string;\n source?: string;\n tags?: readonly string[];\n dependsOn?: readonly string[];\n spec?: string;\n icon?: Config2.Icon;\n screenshots?: ReadonlyArray<Config2.Screenshot>;\n};\n\n/** Constructs a bundled-plugin {@link Meta} from a canonical DXN. `profile.key` is the bare NSID derived from `key`. */\nexport const makeMeta = (options: MakeMetaOptions): Meta => {\n const { key, ...rest } = options;\n return { profile: { ...rest, key: DXN.getName(key) } };\n};\n\n/** Returns the plugin's canonical DXN URI, constructed from `meta.profile.key` and `meta.release?.version`. */\nexport const getURI = (meta: Meta): DXN.DXN => DXN.make(meta.profile.key, meta.release?.version);\n\n/**\n * Derives a runtime {@link Meta} from a loaded `dx.config.ts` (the `@dxos/protocols` `Config2.Config`).\n * Maps the flat authoring config to the nested profile; bundled plugins have no `release`.\n */\nexport const getMetaFromConfig = ({ plugin }: Config2.Config): Meta => {\n const { key, ...rest } = plugin;\n return makeMeta({ key: DXN.make(key), ...rest });\n};\n\n/**\n * Identifier denoting a Plugin.\n */\nexport const PluginTypeId: unique symbol = Symbol.for('@dxos/app-framework/Plugin');\nexport type PluginTypeId = typeof PluginTypeId;\n\n/**\n * Type guard to check if a value is a Plugin.\n */\nexport const isPlugin = (value: unknown): value is Plugin => {\n return typeof value === 'object' && value !== null && PluginTypeId in value;\n};\n\n/**\n * A collection of modules that are be enabled/disabled as a unit.\n * Plugins provide things such as components, state, actions, etc. to the application.\n */\n// TODO(burdon): Convert to ECHO schema.\nexport interface Plugin {\n readonly [PluginTypeId]: PluginTypeId;\n readonly meta: Readonly<Meta>;\n readonly modules: ReadonlyArray<PluginModule>;\n}\n\n/**\n * Internal implementation of Plugin.\n * @internal\n */\nclass PluginImpl implements Plugin {\n readonly [PluginTypeId]: PluginTypeId = PluginTypeId;\n\n constructor(\n private readonly _meta: Meta,\n private readonly _modules: PluginModule[],\n ) {}\n\n get meta(): Readonly<Meta> {\n return this._meta;\n }\n\n get modules(): ReadonlyArray<PluginModule> {\n return this._modules;\n }\n}\n\n/**\n * Builder interface for creating plugins incrementally.\n */\nexport interface PluginBuilder<T = void> extends Pipeable.Pipeable {\n readonly meta: Meta;\n readonly modules: ReadonlyArray<PluginModuleOptions | ((options: T) => PluginModuleOptions)>;\n addModule(moduleOptions: PluginModuleOptions | ((options: T) => PluginModuleOptions)): PluginBuilder<T>;\n}\n\n/**\n * Builder implementation for creating plugins incrementally.\n */\nclass PluginBuilderImpl<T = void> implements PluginBuilder<T> {\n readonly meta: Meta;\n private readonly _modules: Array<PluginModuleOptions | ((options: T) => PluginModuleOptions)> = [];\n\n constructor(meta: Meta) {\n this.meta = meta;\n }\n\n get modules(): ReadonlyArray<PluginModuleOptions | ((options: T) => PluginModuleOptions)> {\n return this._modules;\n }\n\n addModule(moduleOptions: PluginModuleOptions | ((options: T) => PluginModuleOptions)): PluginBuilder<T> {\n this._modules.push(moduleOptions);\n return this;\n }\n\n pipe() {\n // eslint-disable-next-line prefer-rest-params\n return Pipeable.pipeArguments(this, arguments);\n }\n}\n\n/**\n * Creates a new PluginBuilder to start building a plugin.\n */\nexport const define = <T = void>(meta: Meta): PluginBuilder<T> => new PluginBuilderImpl<T>(meta);\n\n/**\n * Adds a module to a plugin builder.\n * Supports both pipeline and direct call styles.\n * Modules can be either PluginModuleOptions or functions that receive options.\n */\nexport function addModule<T>(\n moduleOptions: PluginModuleOptions | ((options: T) => PluginModuleOptions),\n): (builder: PluginBuilder<T>) => PluginBuilder<T>;\nexport function addModule<T>(\n builder: PluginBuilder<T>,\n moduleOptions: PluginModuleOptions | ((options: T) => PluginModuleOptions),\n): PluginBuilder<T>;\nexport function addModule<T>(\n moduleOptionsOrBuilder: PluginModuleOptions | ((options: T) => PluginModuleOptions) | PluginBuilder<T>,\n moduleOptions?: PluginModuleOptions | ((options: T) => PluginModuleOptions),\n): ((builder: PluginBuilder<T>) => PluginBuilder<T>) | PluginBuilder<T> {\n // If second arg is provided, it's the direct call style: addModule(builder, moduleOptions)\n if (moduleOptions !== undefined) {\n return (moduleOptionsOrBuilder as PluginBuilder<T>).addModule(moduleOptions);\n }\n // Otherwise it's pipeline style: addModule(moduleOptions) returns a function\n const moduleOpts = moduleOptionsOrBuilder as PluginModuleOptions | ((options: T) => PluginModuleOptions);\n return (builder: PluginBuilder<T>) => builder.addModule(moduleOpts);\n}\n\nexport type PluginFactory<T = void> = ((options: T) => Plugin) & { meta: Meta };\n\n/**\n * Resolves a module from either PluginModuleOptions or a function that returns PluginModuleOptions.\n */\nconst resolveModule = (\n meta: Meta,\n module: PluginModuleOptions | ((options: any) => PluginModuleOptions),\n options?: any,\n): PluginModuleImpl => {\n const moduleOptions = typeof module === 'function' ? module(options) : module;\n const pluginName = meta.profile.key;\n const id = Option.fromNullable(moduleOptions.id).pipe(\n Option.match({\n onNone: () => {\n const exportName = Capability.getModuleTag(moduleOptions.activate);\n invariant(exportName, `Plugin module missing name. Plugin: ${meta.profile.key}`);\n return computeModuleId(pluginName, exportName);\n },\n onSome: (id) => computeModuleId(pluginName, id),\n }),\n );\n return new PluginModuleImpl({ ...moduleOptions, id });\n};\n\n/**\n * Creates a Plugin from a builder.\n * Supports both pipeline and direct call styles.\n * Always returns a factory function (options: T) => Plugin.\n * When T is void, the function takes no arguments: () => Plugin.\n */\nexport function make<T>(builder: PluginBuilder<T>): PluginFactory<T>;\nexport function make<T>(builder: PluginBuilder<T>): PluginFactory<T> {\n const meta = builder.meta;\n // `dependsOn` entries and `key` are both bare NSIDs, so compare directly.\n invariant(\n !meta.profile.dependsOn?.includes(meta.profile.key),\n `Plugin ${meta.profile.key} declares itself as a dependency.`,\n );\n\n const factory = (options: T) => {\n const modules = builder.modules.map((module) => resolveModule(meta, module, options));\n return new PluginImpl(meta, modules);\n };\n\n return Object.assign(factory, { meta });\n}\n\n//\n// Lazy plugin loading\n//\n\n/**\n * Symbol used to tag lazy plugin stubs with their loader closure.\n * Hidden from enumeration so plugin manager iteration / serialization paths\n * don't trip over it.\n */\nconst LazyTag: unique symbol = Symbol.for('@dxos/app-framework/Plugin/Lazy');\n\n/**\n * Async loader for a lazy plugin's real implementation.\n * The default export of the loaded module must be a `PluginFactory<T>` —\n * i.e. the same shape `Plugin.make` produces.\n */\nexport type LazyLoader<T = void> = () => Promise<{ default: PluginFactory<T> }>;\n\n/** Internal: payload carried on a lazy stub. */\ntype LazyPayload = { loader: LazyLoader<any>; options: unknown };\n\n/**\n * Defines a lazy plugin whose body is loaded on first enable.\n *\n * The returned factory produces a stub `Plugin` that exposes `meta`\n * synchronously (so callers can read `Plugin.meta.profile.key` for free) but defers\n * loading the real plugin's modules until the manager calls\n * `Plugin.resolveLazy`. This lets the plugin's main entry point ship as a\n * tiny meta-only chunk — the heavy capabilities, schema, React surfaces,\n * etc. live behind the dynamic `import()` and become a separate Rollup\n * chunk that is only fetched when the plugin is enabled.\n *\n * @example\n * ```ts\n * // plugin-markdown/src/index.ts\n * import { Plugin } from '@dxos/app-framework';\n * import { meta } from './meta';\n *\n * export const MarkdownPlugin = Plugin.lazy(meta, () => import('./MarkdownPlugin'));\n *\n * // plugin-markdown/src/MarkdownPlugin.tsx\n * export const MarkdownPlugin = Plugin.define(meta).pipe(...heavy modules..., Plugin.make);\n * export default MarkdownPlugin;\n * ```\n */\nexport const lazy = <T = void>(meta: Meta, loader: LazyLoader<T>): PluginFactory<T> => {\n const factory = (options: T): Plugin => {\n const stub = new PluginImpl(meta, []);\n Object.defineProperty(stub, LazyTag, {\n value: { loader, options } satisfies LazyPayload,\n enumerable: false,\n });\n return stub;\n };\n return Object.assign(factory, { meta });\n};\n\n/**\n * Type guard for lazy plugin stubs produced by {@link lazy}.\n */\nexport const isLazy = (plugin: Plugin): boolean => LazyTag in plugin;\n\n/**\n * Tagged error for failures during lazy plugin resolution. `context.id` is\n * the lazy plugin's `meta.profile.key`; `context.reason` discriminates the failure\n * mode (`'load-failed' | 'missing-default' | 'invalid-plugin' |\n * 'meta-mismatch'`) so callers can route on it.\n */\nexport class LazyPluginError extends BaseError.extend('LazyPluginError', 'Failed to resolve lazy plugin') {}\n\n/**\n * Tagged error for plugin-level dependency resolution failures.\n *\n * `context.id` is the plugin id the manager was acting on. `context.reason`\n * discriminates the failure mode:\n * - `'missing'` — declared dep is neither registered nor in the catalog.\n * `context.missing` lists offending ids.\n * - `'install-failed'` — dep was found in the catalog but `add()` failed.\n * `cause` carries the original error.\n * - `'cycle'` — closure walk detected a cycle. `context.path` is the cycle path.\n * - `'core-dependent'` — cascade-disable would have to disable a core plugin.\n * `context.coreDependent` is the blocking id.\n */\nexport class PluginDependencyError extends BaseError.extend(\n 'PluginDependencyError',\n 'Plugin dependency resolution failed',\n) {}\n\n/**\n * Resolves a lazy plugin stub to its real plugin.\n * Returns the plugin unchanged if it is not lazy. Failures surface as\n * {@link LazyPluginError} with `context.reason` indicating the failure mode\n * and (for loader failures) `cause` set to the original error.\n */\nexport const resolveLazy = (plugin: Plugin): Effect.Effect<Plugin, LazyPluginError> =>\n Effect.gen(function* () {\n if (!isLazy(plugin)) {\n return plugin;\n }\n const id = plugin.meta.profile.key;\n const { loader, options } = (plugin as unknown as { [LazyTag]: LazyPayload })[LazyTag];\n const mod = yield* Effect.tryPromise({\n try: loader,\n catch: (error) => new LazyPluginError({ context: { id, reason: 'load-failed' }, cause: error }),\n });\n if (!mod || typeof mod.default !== 'function') {\n return yield* Effect.fail(new LazyPluginError({ context: { id, reason: 'missing-default' } }));\n }\n const result = mod.default(options);\n if (!isPlugin(result)) {\n return yield* Effect.fail(new LazyPluginError({ context: { id, reason: 'invalid-plugin' } }));\n }\n if (result.meta.profile.key !== id) {\n return yield* Effect.fail(\n new LazyPluginError({ context: { id, reason: 'meta-mismatch', returnedId: result.meta.profile.key } }),\n );\n }\n return result;\n });\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Context", "Effect", "Option", "Pipeable", "Schema", "BaseError", "invariant", "DXN", "PluginProfileSchema", "PluginReleaseSchema", "PluginModuleImpl", "id", "activatesOn", "firesBeforeActivation", "firesAfterActivation", "activate", "author", "Schema", "Release", "PluginReleaseSchema", "profile", "Profile", "release", "optional", "DXN", "makeMeta", "key", "make", "rest", "_meta", "_modules", "meta", "modules", "addModule", "moduleOptions", "pipe", "undefined", "pluginName", "fromNullable", "Option", "onNone", "exportName", "Capability", "getModuleTag", "invariant", "onSome", "computeModuleId", "builder", "module", "resolveModule", "options", "PluginImpl", "Object", "assign", "factory", "stub", "defineProperty", "value", "loader", "enumerable", "plugin", "mod", "Effect", "tryPromise", "try", "catch", "error", "LazyPluginError", "reason", "cause", "context", "result", "fail", "returnedId"]
|
|
7
|
+
}
|
|
@@ -14,13 +14,12 @@ __export(activation_event_exports, {
|
|
|
14
14
|
make: () => make,
|
|
15
15
|
oneOf: () => oneOf
|
|
16
16
|
});
|
|
17
|
+
import { DXN } from "@dxos/keys";
|
|
17
18
|
import { compositeKey } from "@dxos/util";
|
|
18
|
-
var make = (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
};
|
|
23
|
-
};
|
|
19
|
+
var make = (nsid, specifier) => ({
|
|
20
|
+
id: DXN.make(nsid),
|
|
21
|
+
specifier
|
|
22
|
+
});
|
|
24
23
|
var eventKey = (event) => event.specifier ? compositeKey(event.id, event.specifier) : event.id;
|
|
25
24
|
var oneOf = (...events) => ({
|
|
26
25
|
type: "one-of",
|
|
@@ -46,4 +45,4 @@ export {
|
|
|
46
45
|
getEvents,
|
|
47
46
|
activation_event_exports
|
|
48
47
|
};
|
|
49
|
-
//# sourceMappingURL=chunk-
|
|
48
|
+
//# sourceMappingURL=chunk-BMW6P6QA.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/core/activation-event.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { DXN } from '@dxos/keys';\nimport { compositeKey } from '@dxos/util';\n\n/**\n * A unique DXN identifier representing an event.\n *\n * @example dxn:org.dxos.plugin.example.event.ready\n */\nexport type ActivationEvent = {\n id: DXN.DXN;\n specifier?: string;\n};\n\n/**\n * An activation event that can be a single event, or a combination of events.\n */\nexport type Events =\n | ActivationEvent\n | { type: 'one-of'; events: ActivationEvent[] }\n | { type: 'all-of'; events: ActivationEvent[] };\n\n/**\n * Helper to define an activation event from an NSID.\n * Static NSID strings are validated at compile time via {@link DXN.Name}.\n */\nexport const make: {\n <T extends string>(\n nsid: [DXN.Name<T>] extends [never] ? `Invalid NSID \"${T}\": final segment must be camelCase (no hyphens)` : T,\n specifier?: string,\n ): ActivationEvent;\n} = (nsid: string, specifier?: string): ActivationEvent => ({\n id: DXN.make(nsid),\n specifier,\n});\n\n/**\n * Helper to create an activation event key.\n */\nexport const eventKey = (event: ActivationEvent) =>\n event.specifier ? compositeKey(event.id, event.specifier) : event.id;\n\n/**\n * Helper to create an activation event that triggers when any of the given events are activated.\n */\nexport const oneOf = (...events: ActivationEvent[]) => ({ type: 'one-of' as const, events });\n\n/**\n * Helper to create an activation event that triggers when all of the given events are activated.\n */\nexport const allOf = (...events: ActivationEvent[]) => ({ type: 'all-of' as const, events });\n\n/**\n * Helper to check if an activation event is a one-of event.\n */\nexport const isOneOf = (events: Events): events is { type: 'one-of'; events: ActivationEvent[] } =>\n 'type' in events && events.type === 'one-of';\n\n/**\n * Helper to check if an activation event is an all-of event.\n */\nexport const isAllOf = (events: Events): events is { type: 'all-of'; events: ActivationEvent[] } =>\n 'type' in events && events.type === 'all-of';\n\n/**\n * Helper to get the events from an activation event.\n */\nexport const getEvents = (events: Events) => ('type' in events ? events.events : [events]);\n"],
|
|
5
|
+
"mappings": ";;;;;;AAAA;;;;;;;;;;AAIA,SAASA,WAAW;AACpB,SAASC,oBAAoB;AAwBtB,IAAMC,OAKT,CAACC,MAAcC,eAAyC;EAC1DC,IAAIL,IAAIE,KAAKC,IAAAA;EACbC;AACF;AAKO,IAAME,WAAW,CAACC,UACvBA,MAAMH,YAAYH,aAAaM,MAAMF,IAAIE,MAAMH,SAAS,IAAIG,MAAMF;AAK7D,IAAMG,QAAQ,IAAIC,YAA+B;EAAEC,MAAM;EAAmBD;AAAO;AAKnF,IAAME,QAAQ,IAAIF,YAA+B;EAAEC,MAAM;EAAmBD;AAAO;AAKnF,IAAMG,UAAU,CAACH,WACtB,UAAUA,UAAUA,OAAOC,SAAS;AAK/B,IAAMG,UAAU,CAACJ,WACtB,UAAUA,UAAUA,OAAOC,SAAS;AAK/B,IAAMI,YAAY,CAACL,WAAoB,UAAUA,SAASA,OAAOA,SAAS;EAACA;;",
|
|
6
|
+
"names": ["DXN", "compositeKey", "make", "nsid", "specifier", "id", "eventKey", "event", "oneOf", "events", "type", "allOf", "isOneOf", "isAllOf", "getEvents"]
|
|
7
|
+
}
|