@dxos/app-framework 0.7.5-main.499c70c → 0.7.5-main.5ae2ba8
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/app-graph-builder-S4MYSHQA.mjs +137 -0
- package/dist/lib/browser/app-graph-builder-S4MYSHQA.mjs.map +7 -0
- package/dist/lib/browser/chunk-BCMEJONP.mjs +1432 -0
- package/dist/lib/browser/chunk-BCMEJONP.mjs.map +7 -0
- package/dist/lib/browser/chunk-QS4J6O47.mjs +285 -0
- package/dist/lib/browser/chunk-QS4J6O47.mjs.map +7 -0
- package/dist/lib/browser/chunk-SRZH2PQ2.mjs +32 -0
- package/dist/lib/browser/chunk-SRZH2PQ2.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +119 -642
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/intent-dispatcher-GFBH7T2J.mjs +11 -0
- package/dist/lib/browser/intent-resolver-KAFM7CQH.mjs +39 -0
- package/dist/lib/browser/intent-resolver-KAFM7CQH.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/store-L3VRR7II.mjs +29 -0
- package/dist/lib/browser/store-L3VRR7II.mjs.map +7 -0
- package/dist/lib/browser/testing/index.mjs +77 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/browser/worker.mjs +77 -0
- package/dist/lib/node/app-graph-builder-VMHWFCTP.cjs +146 -0
- package/dist/lib/node/app-graph-builder-VMHWFCTP.cjs.map +7 -0
- package/dist/lib/node/chunk-7Y6KJ3OK.cjs +1466 -0
- package/dist/lib/node/chunk-7Y6KJ3OK.cjs.map +7 -0
- package/dist/lib/node/chunk-B65NJEIJ.cjs +308 -0
- package/dist/lib/node/chunk-B65NJEIJ.cjs.map +7 -0
- package/dist/lib/node/{chunk-FCMHRU3M.cjs → chunk-VCIHQZSN.cjs} +23 -35
- package/dist/lib/node/chunk-VCIHQZSN.cjs.map +7 -0
- package/dist/lib/node/index.cjs +125 -665
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/{plugin-settings-W6UHMH5M.cjs → intent-dispatcher-PRCC4KZT.cjs} +10 -14
- package/dist/lib/node/intent-dispatcher-PRCC4KZT.cjs.map +7 -0
- package/dist/lib/node/intent-resolver-OZDKCHPW.cjs +46 -0
- package/dist/lib/node/intent-resolver-OZDKCHPW.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/store-BVUKNVKL.cjs +44 -0
- package/dist/lib/node/store-BVUKNVKL.cjs.map +7 -0
- package/dist/lib/node/testing/index.cjs +101 -0
- package/dist/lib/node/testing/index.cjs.map +7 -0
- package/dist/lib/node/worker.cjs +99 -0
- package/dist/lib/node/worker.cjs.map +7 -0
- package/dist/lib/node-esm/app-graph-builder-XHI5IIXQ.mjs +138 -0
- package/dist/lib/node-esm/app-graph-builder-XHI5IIXQ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-CBT75GCX.mjs +34 -0
- package/dist/lib/node-esm/chunk-CBT75GCX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-JDAHZRYQ.mjs +286 -0
- package/dist/lib/node-esm/chunk-JDAHZRYQ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-TVIR2PHY.mjs +1434 -0
- package/dist/lib/node-esm/chunk-TVIR2PHY.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +119 -642
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/intent-dispatcher-LGACN32C.mjs +12 -0
- package/dist/lib/node-esm/intent-resolver-RBNG76ZX.mjs +40 -0
- package/dist/lib/node-esm/intent-resolver-RBNG76ZX.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/store-PHTOEREN.mjs +30 -0
- package/dist/lib/node-esm/store-PHTOEREN.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +78 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/lib/node-esm/worker.mjs +78 -0
- package/dist/types/src/App.d.ts +22 -13
- package/dist/types/src/App.d.ts.map +1 -1
- package/dist/types/src/common/capabilities.d.ts +304 -0
- package/dist/types/src/common/capabilities.d.ts.map +1 -0
- package/dist/types/src/common/events.d.ts +52 -0
- package/dist/types/src/common/events.d.ts.map +1 -0
- package/dist/types/src/common/file.d.ts +14 -0
- package/dist/types/src/common/file.d.ts.map +1 -0
- package/dist/types/src/common/graph.d.ts +21 -0
- package/dist/types/src/common/graph.d.ts.map +1 -0
- package/dist/types/src/common/index.d.ts +8 -0
- package/dist/types/src/common/index.d.ts.map +1 -0
- package/dist/types/src/common/layout.d.ts +262 -0
- package/dist/types/src/common/layout.d.ts.map +1 -0
- package/dist/types/src/{plugins/plugin-surface/SurfaceContext.d.ts → common/surface.d.ts} +12 -29
- package/dist/types/src/common/surface.d.ts.map +1 -0
- package/dist/types/src/common/translations.d.ts +11 -0
- package/dist/types/src/common/translations.d.ts.map +1 -0
- package/dist/types/src/core/capabilities.d.ts +94 -0
- package/dist/types/src/core/capabilities.d.ts.map +1 -0
- package/dist/types/src/core/capabilities.test.d.ts +2 -0
- package/dist/types/src/core/capabilities.test.d.ts.map +1 -0
- package/dist/types/src/core/events.d.ts +58 -0
- package/dist/types/src/core/events.d.ts.map +1 -0
- package/dist/types/src/core/index.d.ts +5 -0
- package/dist/types/src/core/index.d.ts.map +1 -0
- package/dist/types/src/core/manager.d.ts +119 -0
- package/dist/types/src/core/manager.d.ts.map +1 -0
- package/dist/types/src/core/manager.test.d.ts +2 -0
- package/dist/types/src/core/manager.test.d.ts.map +1 -0
- package/dist/types/src/core/plugin.d.ts +97 -0
- package/dist/types/src/core/plugin.d.ts.map +1 -0
- package/dist/types/src/helpers.d.ts +10 -0
- package/dist/types/src/helpers.d.ts.map +1 -0
- package/dist/types/src/helpers.test.d.ts +2 -0
- package/dist/types/src/helpers.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +5 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/playground/debug/Debug.d.ts +5 -0
- package/dist/types/src/playground/debug/Debug.d.ts.map +1 -0
- package/dist/types/src/playground/debug/index.d.ts +2 -0
- package/dist/types/src/playground/debug/index.d.ts.map +1 -0
- package/dist/types/src/playground/debug/plugin.d.ts +2 -0
- package/dist/types/src/playground/debug/plugin.d.ts.map +1 -0
- package/dist/types/src/playground/generator/Main.d.ts +5 -0
- package/dist/types/src/playground/generator/Main.d.ts.map +1 -0
- package/dist/types/src/playground/generator/Toolbar.d.ts +5 -0
- package/dist/types/src/playground/generator/Toolbar.d.ts.map +1 -0
- package/dist/types/src/playground/generator/generator.d.ts +7 -0
- package/dist/types/src/playground/generator/generator.d.ts.map +1 -0
- package/dist/types/src/playground/generator/index.d.ts +3 -0
- package/dist/types/src/playground/generator/index.d.ts.map +1 -0
- package/dist/types/src/playground/generator/plugin.d.ts +2 -0
- package/dist/types/src/playground/generator/plugin.d.ts.map +1 -0
- package/dist/types/src/playground/layout/Layout.d.ts +8 -0
- package/dist/types/src/playground/layout/Layout.d.ts.map +1 -0
- package/dist/types/src/playground/layout/index.d.ts +2 -0
- package/dist/types/src/playground/layout/index.d.ts.map +1 -0
- package/dist/types/src/playground/layout/plugin.d.ts +2 -0
- package/dist/types/src/playground/layout/plugin.d.ts.map +1 -0
- package/dist/types/src/playground/logger/Toolbar.d.ts +5 -0
- package/dist/types/src/playground/logger/Toolbar.d.ts.map +1 -0
- package/dist/types/src/playground/logger/index.d.ts +2 -0
- package/dist/types/src/playground/logger/index.d.ts.map +1 -0
- package/dist/types/src/playground/logger/plugin.d.ts +2 -0
- package/dist/types/src/playground/logger/plugin.d.ts.map +1 -0
- package/dist/types/src/playground/logger/schema.d.ts +13 -0
- package/dist/types/src/playground/logger/schema.d.ts.map +1 -0
- package/dist/types/src/playground/playground.stories.d.ts +9 -0
- package/dist/types/src/playground/playground.stories.d.ts.map +1 -0
- package/dist/types/src/plugin-intent/IntentPlugin.d.ts +2 -0
- package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +1 -0
- package/dist/types/src/plugin-intent/actions.d.ts +23 -0
- package/dist/types/src/plugin-intent/actions.d.ts.map +1 -0
- package/dist/types/src/plugin-intent/errors.d.ts +16 -0
- package/dist/types/src/plugin-intent/errors.d.ts.map +1 -0
- package/dist/types/src/plugin-intent/index.d.ts +5 -0
- package/dist/types/src/plugin-intent/index.d.ts.map +1 -0
- package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +113 -0
- package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +1 -0
- package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts.map +1 -0
- package/dist/types/src/{plugins/plugin-intent → plugin-intent}/intent.d.ts +8 -28
- package/dist/types/src/plugin-intent/intent.d.ts.map +1 -0
- package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +2 -0
- package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +1 -0
- package/dist/types/src/plugin-settings/actions.d.ts +27 -0
- package/dist/types/src/plugin-settings/actions.d.ts.map +1 -0
- package/dist/types/src/plugin-settings/app-graph-builder.d.ts +197 -0
- package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/plugin-settings/index.d.ts +3 -0
- package/dist/types/src/plugin-settings/index.d.ts.map +1 -0
- package/dist/types/src/plugin-settings/intent-resolver.d.ts +4 -0
- package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/plugin-settings/store.d.ts +5 -0
- package/dist/types/src/plugin-settings/store.d.ts.map +1 -0
- package/dist/types/src/plugin-settings/translations.d.ts +11 -0
- package/dist/types/src/plugin-settings/translations.d.ts.map +1 -0
- package/dist/types/src/{plugins/plugin-surface → react}/ErrorBoundary.d.ts +1 -1
- package/dist/types/src/react/ErrorBoundary.d.ts.map +1 -0
- package/dist/types/src/{plugins/plugin-intent → react}/IntentContext.d.ts +2 -2
- package/dist/types/src/react/IntentContext.d.ts.map +1 -0
- package/dist/types/src/react/PluginManagerProvider.d.ts +10 -0
- package/dist/types/src/react/PluginManagerProvider.d.ts.map +1 -0
- package/dist/types/src/react/Surface.d.ts +12 -0
- package/dist/types/src/react/Surface.d.ts.map +1 -0
- package/dist/types/src/react/Surface.stories.d.ts +15 -0
- package/dist/types/src/react/Surface.stories.d.ts.map +1 -0
- package/dist/types/src/react/common.d.ts +13 -0
- package/dist/types/src/react/common.d.ts.map +1 -0
- package/dist/types/src/react/index.d.ts +7 -0
- package/dist/types/src/react/index.d.ts.map +1 -0
- package/dist/types/src/react/useCapabilities.d.ts +13 -0
- package/dist/types/src/react/useCapabilities.d.ts.map +1 -0
- package/dist/types/src/react/useIntentResolver.d.ts +3 -0
- package/dist/types/src/react/useIntentResolver.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/withPluginManager.d.ts +12 -0
- package/dist/types/src/testing/withPluginManager.d.ts.map +1 -0
- package/dist/types/src/testing/withPluginManager.stories.d.ts +5 -0
- package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -0
- package/dist/types/src/worker.d.ts +4 -0
- package/dist/types/src/worker.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +40 -19
- package/project.json +5 -3
- package/src/App.tsx +140 -34
- package/src/common/capabilities.ts +101 -0
- package/src/common/events.ts +77 -0
- package/src/common/file.ts +22 -0
- package/src/common/graph.ts +30 -0
- package/src/{plugins/common → common}/index.ts +3 -2
- package/src/common/layout.ts +238 -0
- package/src/{plugins/plugin-surface/SurfaceContext.ts → common/surface.ts} +6 -37
- package/src/common/translations.ts +17 -0
- package/src/core/capabilities.test.ts +116 -0
- package/src/core/capabilities.ts +222 -0
- package/src/core/events.ts +58 -0
- package/src/core/index.ts +8 -0
- package/src/core/manager.test.ts +516 -0
- package/src/core/manager.ts +511 -0
- package/src/core/plugin.ts +131 -0
- package/src/helpers.test.ts +97 -0
- package/src/helpers.ts +45 -0
- package/src/index.ts +6 -3
- package/src/playground/debug/Debug.tsx +39 -0
- package/src/playground/debug/index.ts +5 -0
- package/src/playground/debug/plugin.ts +17 -0
- package/src/playground/generator/Main.tsx +71 -0
- package/src/playground/generator/Toolbar.tsx +46 -0
- package/src/playground/generator/generator.ts +48 -0
- package/src/playground/generator/index.ts +6 -0
- package/src/playground/generator/plugin.ts +23 -0
- package/src/playground/layout/Layout.tsx +33 -0
- package/src/playground/layout/index.ts +5 -0
- package/src/playground/layout/plugin.ts +17 -0
- package/src/playground/logger/Toolbar.tsx +29 -0
- package/src/playground/logger/index.ts +5 -0
- package/src/playground/logger/plugin.ts +36 -0
- package/src/playground/logger/schema.ts +12 -0
- package/src/playground/playground.stories.tsx +34 -0
- package/src/plugin-intent/IntentPlugin.tsx +20 -0
- package/src/plugin-intent/actions.ts +22 -0
- package/src/plugin-intent/errors.ts +39 -0
- package/src/plugin-intent/index.ts +8 -0
- package/src/{plugins/plugin-intent → plugin-intent}/intent-dispatcher.test.ts +83 -63
- package/src/{plugins/plugin-intent → plugin-intent}/intent-dispatcher.ts +118 -95
- package/src/{plugins/plugin-intent → plugin-intent}/intent.ts +10 -26
- package/src/plugin-settings/SettingsPlugin.ts +35 -0
- package/src/plugin-settings/actions.ts +27 -0
- package/src/plugin-settings/app-graph-builder.ts +122 -0
- package/src/plugin-settings/index.ts +6 -0
- package/src/plugin-settings/intent-resolver.ts +34 -0
- package/src/plugin-settings/store.ts +30 -0
- package/src/plugin-settings/translations.ts +17 -0
- package/src/{plugins/plugin-intent → react}/IntentContext.tsx +13 -5
- package/src/react/PluginManagerProvider.ts +22 -0
- package/src/react/Surface.stories.tsx +96 -0
- package/src/react/Surface.tsx +75 -0
- package/src/react/common.ts +12 -0
- package/src/react/index.ts +10 -0
- package/src/react/useCapabilities.ts +40 -0
- package/src/react/useIntentResolver.ts +22 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/withPluginManager.stories.tsx +47 -0
- package/src/testing/withPluginManager.tsx +91 -0
- package/src/worker.ts +11 -0
- package/tsconfig.json +19 -13
- package/dist/lib/browser/chunk-3E7RY3CE.mjs +0 -72
- package/dist/lib/browser/chunk-3E7RY3CE.mjs.map +0 -7
- package/dist/lib/browser/chunk-QG25ZU2N.mjs +0 -320
- package/dist/lib/browser/chunk-QG25ZU2N.mjs.map +0 -7
- package/dist/lib/browser/chunk-SPDTXTOV.mjs +0 -163
- package/dist/lib/browser/chunk-SPDTXTOV.mjs.map +0 -7
- package/dist/lib/browser/chunk-WBOXEHBE.mjs +0 -51
- package/dist/lib/browser/chunk-WBOXEHBE.mjs.map +0 -7
- package/dist/lib/browser/plugin-intent-T7Y3MJ5C.mjs +0 -32
- package/dist/lib/browser/plugin-settings-5U2L2NRU.mjs +0 -15
- package/dist/lib/browser/plugin-surface-OKPF3EQI.mjs +0 -24
- package/dist/lib/node/chunk-BW3RNEVI.cjs +0 -185
- package/dist/lib/node/chunk-BW3RNEVI.cjs.map +0 -7
- package/dist/lib/node/chunk-FCMHRU3M.cjs.map +0 -7
- package/dist/lib/node/chunk-QBM42OQ6.cjs +0 -97
- package/dist/lib/node/chunk-QBM42OQ6.cjs.map +0 -7
- package/dist/lib/node/chunk-VWHAALIN.cjs +0 -344
- package/dist/lib/node/chunk-VWHAALIN.cjs.map +0 -7
- package/dist/lib/node/plugin-intent-F3TQZIUR.cjs +0 -53
- package/dist/lib/node/plugin-intent-F3TQZIUR.cjs.map +0 -7
- package/dist/lib/node/plugin-settings-W6UHMH5M.cjs.map +0 -7
- package/dist/lib/node/plugin-surface-CCSIONYW.cjs +0 -45
- package/dist/lib/node/plugin-surface-CCSIONYW.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-3T5UIJY3.mjs +0 -53
- package/dist/lib/node-esm/chunk-3T5UIJY3.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-4GX7V5ZE.mjs +0 -164
- package/dist/lib/node-esm/chunk-4GX7V5ZE.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-CFOUYXQ6.mjs +0 -321
- package/dist/lib/node-esm/chunk-CFOUYXQ6.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-EYCTSFEJ.mjs +0 -74
- package/dist/lib/node-esm/chunk-EYCTSFEJ.mjs.map +0 -7
- package/dist/lib/node-esm/plugin-intent-W2HQC6LC.mjs +0 -33
- package/dist/lib/node-esm/plugin-settings-H5RHNFVC.mjs +0 -16
- package/dist/lib/node-esm/plugin-settings-H5RHNFVC.mjs.map +0 -7
- package/dist/lib/node-esm/plugin-surface-V3YET3UL.mjs +0 -25
- package/dist/lib/node-esm/plugin-surface-V3YET3UL.mjs.map +0 -7
- package/dist/types/src/plugins/common/file.d.ts +0 -22
- package/dist/types/src/plugins/common/file.d.ts.map +0 -1
- package/dist/types/src/plugins/common/graph.d.ts +0 -51
- package/dist/types/src/plugins/common/graph.d.ts.map +0 -1
- package/dist/types/src/plugins/common/index.d.ts +0 -7
- package/dist/types/src/plugins/common/index.d.ts.map +0 -1
- package/dist/types/src/plugins/common/layout.d.ts +0 -176
- package/dist/types/src/plugins/common/layout.d.ts.map +0 -1
- package/dist/types/src/plugins/common/metadata.d.ts +0 -16
- package/dist/types/src/plugins/common/metadata.d.ts.map +0 -1
- package/dist/types/src/plugins/common/navigation.d.ts +0 -243
- package/dist/types/src/plugins/common/navigation.d.ts.map +0 -1
- package/dist/types/src/plugins/common/translations.d.ts +0 -22
- package/dist/types/src/plugins/common/translations.d.ts.map +0 -1
- package/dist/types/src/plugins/helpers.d.ts +0 -41
- package/dist/types/src/plugins/helpers.d.ts.map +0 -1
- package/dist/types/src/plugins/index.d.ts +0 -7
- package/dist/types/src/plugins/index.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts +0 -16
- package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-host/PluginContainer.d.ts +0 -14
- package/dist/types/src/plugins/plugin-host/PluginContainer.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-host/PluginContext.d.ts +0 -47
- package/dist/types/src/plugins/plugin-host/PluginContext.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-host/index.d.ts +0 -6
- package/dist/types/src/plugins/plugin-host/index.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-host/plugin.d.ts +0 -104
- package/dist/types/src/plugins/plugin-host/plugin.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-host/plugin.test.d.ts +0 -35
- package/dist/types/src/plugins/plugin-host/plugin.test.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-intent/IntentContext.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-intent/IntentPlugin.d.ts +0 -8
- package/dist/types/src/plugins/plugin-intent/IntentPlugin.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-intent/index.d.ts +0 -7
- package/dist/types/src/plugins/plugin-intent/index.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-intent/intent-dispatcher.d.ts +0 -107
- package/dist/types/src/plugins/plugin-intent/intent-dispatcher.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-intent/intent-dispatcher.test.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-intent/intent.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-intent/meta.d.ts +0 -6
- package/dist/types/src/plugins/plugin-intent/meta.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-intent/provides.d.ts +0 -16
- package/dist/types/src/plugins/plugin-intent/provides.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-settings/SettingsPlugin.d.ts +0 -4
- package/dist/types/src/plugins/plugin-settings/SettingsPlugin.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-settings/index.d.ts +0 -4
- package/dist/types/src/plugins/plugin-settings/index.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-settings/meta.d.ts +0 -5
- package/dist/types/src/plugins/plugin-settings/meta.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-settings/provides.d.ts +0 -26
- package/dist/types/src/plugins/plugin-settings/provides.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-surface/ErrorBoundary.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-surface/Surface.d.ts +0 -7
- package/dist/types/src/plugins/plugin-surface/Surface.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-surface/SurfaceContext.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts +0 -7
- package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-surface/helpers.d.ts +0 -21
- package/dist/types/src/plugins/plugin-surface/helpers.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-surface/index.d.ts +0 -8
- package/dist/types/src/plugins/plugin-surface/index.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-surface/meta.d.ts +0 -5
- package/dist/types/src/plugins/plugin-surface/meta.d.ts.map +0 -1
- package/dist/types/src/plugins/plugin-surface/provides.d.ts +0 -17
- package/dist/types/src/plugins/plugin-surface/provides.d.ts.map +0 -1
- package/src/plugins/common/file.ts +0 -36
- package/src/plugins/common/graph.ts +0 -70
- package/src/plugins/common/layout.ts +0 -173
- package/src/plugins/common/metadata.ts +0 -29
- package/src/plugins/common/navigation.ts +0 -214
- package/src/plugins/common/translations.ts +0 -36
- package/src/plugins/helpers.ts +0 -92
- package/src/plugins/index.ts +0 -11
- package/src/plugins/plugin-host/HostPlugin.tsx +0 -88
- package/src/plugins/plugin-host/PluginContainer.tsx +0 -120
- package/src/plugins/plugin-host/PluginContext.tsx +0 -79
- package/src/plugins/plugin-host/index.ts +0 -12
- package/src/plugins/plugin-host/plugin.test.ts +0 -158
- package/src/plugins/plugin-host/plugin.ts +0 -133
- package/src/plugins/plugin-intent/IntentPlugin.tsx +0 -75
- package/src/plugins/plugin-intent/index.ts +0 -13
- package/src/plugins/plugin-intent/meta.ts +0 -11
- package/src/plugins/plugin-intent/provides.ts +0 -26
- package/src/plugins/plugin-settings/SettingsPlugin.tsx +0 -22
- package/src/plugins/plugin-settings/index.ts +0 -9
- package/src/plugins/plugin-settings/meta.ts +0 -9
- package/src/plugins/plugin-settings/provides.ts +0 -34
- package/src/plugins/plugin-surface/Surface.tsx +0 -62
- package/src/plugins/plugin-surface/SurfacePlugin.tsx +0 -45
- package/src/plugins/plugin-surface/helpers.ts +0 -22
- package/src/plugins/plugin-surface/index.ts +0 -14
- package/src/plugins/plugin-surface/meta.ts +0 -9
- package/src/plugins/plugin-surface/provides.ts +0 -27
- /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
- /package/dist/lib/browser/{plugin-intent-T7Y3MJ5C.mjs.map → intent-dispatcher-GFBH7T2J.mjs.map} +0 -0
- /package/dist/lib/browser/{plugin-settings-5U2L2NRU.mjs.map → worker.mjs.map} +0 -0
- /package/dist/lib/{browser/plugin-surface-OKPF3EQI.mjs.map → node-esm/intent-dispatcher-LGACN32C.mjs.map} +0 -0
- /package/dist/lib/node-esm/{plugin-intent-W2HQC6LC.mjs.map → worker.mjs.map} +0 -0
- /package/dist/types/src/{plugins/plugin-intent → plugin-intent}/intent-dispatcher.test.d.ts +0 -0
- /package/src/{plugins/plugin-surface → react}/ErrorBoundary.tsx +0 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Schema as S } from '@effect/schema';
|
|
6
|
+
|
|
7
|
+
import { Label } from '../plugin-intent';
|
|
8
|
+
|
|
9
|
+
export const LAYOUT_PLUGIN = 'dxos.org/plugin/layout';
|
|
10
|
+
export const LAYOUT_ACTION = `${LAYOUT_PLUGIN}/action`;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Expected payload for layout actions.
|
|
14
|
+
*/
|
|
15
|
+
export namespace LayoutAction {
|
|
16
|
+
export const UPDATE_LAYOUT = `${LAYOUT_ACTION}/update-layout`;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generic layout action.
|
|
20
|
+
*/
|
|
21
|
+
export class UpdateLayout extends S.TaggedClass<UpdateLayout>()(UPDATE_LAYOUT, {
|
|
22
|
+
input: S.Struct({
|
|
23
|
+
part: S.String.annotations({ description: 'The part of the layout to mutate.' }),
|
|
24
|
+
subject: S.optional(S.Any.annotations({ description: 'The subject of the layout update.' })),
|
|
25
|
+
options: S.optional(
|
|
26
|
+
S.Record({ key: S.String, value: S.Any }).annotations({
|
|
27
|
+
description: 'Additional options for the layout action.',
|
|
28
|
+
}),
|
|
29
|
+
),
|
|
30
|
+
}),
|
|
31
|
+
output: S.Void,
|
|
32
|
+
}) {}
|
|
33
|
+
|
|
34
|
+
//
|
|
35
|
+
// Common layout actions.
|
|
36
|
+
//
|
|
37
|
+
|
|
38
|
+
// NOTE: These are layout actions which are currently in common use.
|
|
39
|
+
// They constrain the generic layout action types to provide additional type safety.
|
|
40
|
+
// However, they all follow the same generic structure and intent id.
|
|
41
|
+
// This allows for plugins to update the layout without depending on a specific layout plugin.
|
|
42
|
+
// The expectation is that other norms other than these will emerge over time.
|
|
43
|
+
|
|
44
|
+
export class SetLayoutMode extends S.TaggedClass<SetLayoutMode>()(UPDATE_LAYOUT, {
|
|
45
|
+
input: S.Struct({
|
|
46
|
+
part: S.Literal('mode').annotations({ description: 'Setting the layout mode.' }),
|
|
47
|
+
subject: S.optional(S.String.annotations({ description: 'Item which is the subject of the new layout mode.' })),
|
|
48
|
+
options: S.Union(
|
|
49
|
+
S.Struct({ mode: S.String.annotations({ description: 'The new layout mode.' }) }),
|
|
50
|
+
S.Struct({ revert: S.Boolean.annotations({ description: 'Revert to the previous layout mode.' }) }),
|
|
51
|
+
),
|
|
52
|
+
}),
|
|
53
|
+
output: S.Void,
|
|
54
|
+
}) {}
|
|
55
|
+
|
|
56
|
+
export class UpdateSidebar extends S.TaggedClass<UpdateSidebar>()(UPDATE_LAYOUT, {
|
|
57
|
+
input: S.Struct({
|
|
58
|
+
part: S.Literal('sidebar').annotations({ description: 'Updating the sidebar.' }),
|
|
59
|
+
subject: S.optional(S.String.annotations({ description: 'URI of the component to display in the sidebar.' })),
|
|
60
|
+
options: S.optional(
|
|
61
|
+
S.Struct({
|
|
62
|
+
state: S.Literal('closed', 'collapsed', 'expanded').annotations({
|
|
63
|
+
description: 'Whether the sidebar is closed, collapsed, or expanded.',
|
|
64
|
+
}),
|
|
65
|
+
}),
|
|
66
|
+
),
|
|
67
|
+
}),
|
|
68
|
+
output: S.Void,
|
|
69
|
+
}) {}
|
|
70
|
+
|
|
71
|
+
export class UpdateComplementary extends S.TaggedClass<UpdateComplementary>()(UPDATE_LAYOUT, {
|
|
72
|
+
input: S.Struct({
|
|
73
|
+
part: S.Literal('complementary').annotations({ description: 'Updating the complementary sidebar.' }),
|
|
74
|
+
subject: S.optional(
|
|
75
|
+
S.String.annotations({ description: 'URI of the component to display in the complementary area.' }),
|
|
76
|
+
),
|
|
77
|
+
options: S.optional(
|
|
78
|
+
S.Struct({
|
|
79
|
+
state: S.Literal('closed', 'collapsed', 'expanded').annotations({
|
|
80
|
+
description: 'Whether the complementary sidebar is closed, collapsed, or expanded.',
|
|
81
|
+
}),
|
|
82
|
+
}),
|
|
83
|
+
),
|
|
84
|
+
}),
|
|
85
|
+
output: S.Void,
|
|
86
|
+
}) {}
|
|
87
|
+
|
|
88
|
+
export class UpdateDialog extends S.TaggedClass<UpdateDialog>()(UPDATE_LAYOUT, {
|
|
89
|
+
input: S.Struct({
|
|
90
|
+
part: S.Literal('dialog').annotations({ description: 'Updating the dialog.' }),
|
|
91
|
+
subject: S.optional(S.String.annotations({ description: 'URI of the component to display in the dialog.' })),
|
|
92
|
+
options: S.Struct({
|
|
93
|
+
state: S.optional(S.Boolean.annotations({ description: 'Whether the dialog is open or closed.' })),
|
|
94
|
+
blockAlign: S.optional(
|
|
95
|
+
S.Literal('start', 'center', 'end').annotations({ description: 'The alignment of the dialog.' }),
|
|
96
|
+
),
|
|
97
|
+
type: S.optional(S.Literal('default', 'alert').annotations({ description: 'The type of dialog.' })),
|
|
98
|
+
props: S.optional(
|
|
99
|
+
S.Record({ key: S.String, value: S.Any }).annotations({
|
|
100
|
+
description: 'Additional props for the dialog.',
|
|
101
|
+
}),
|
|
102
|
+
),
|
|
103
|
+
}),
|
|
104
|
+
}),
|
|
105
|
+
output: S.Void,
|
|
106
|
+
}) {}
|
|
107
|
+
|
|
108
|
+
export class UpdatePopover extends S.TaggedClass<UpdatePopover>()(UPDATE_LAYOUT, {
|
|
109
|
+
input: S.Struct({
|
|
110
|
+
part: S.Literal('popover').annotations({ description: 'Updating the popover.' }),
|
|
111
|
+
subject: S.optional(S.String.annotations({ description: 'URI of the component to display in the popover.' })),
|
|
112
|
+
options: S.Struct({
|
|
113
|
+
anchorId: S.String.annotations({ description: 'The id of the element to anchor the popover to.' }),
|
|
114
|
+
side: S.optional(
|
|
115
|
+
S.Literal('top', 'right', 'bottom', 'left').annotations({ description: 'The side of the anchor.' }),
|
|
116
|
+
),
|
|
117
|
+
state: S.optional(S.Boolean.annotations({ description: 'Whether the popover is open or closed.' })),
|
|
118
|
+
props: S.optional(
|
|
119
|
+
S.Record({ key: S.String, value: S.Any }).annotations({
|
|
120
|
+
description: 'Additional props for the popover.',
|
|
121
|
+
}),
|
|
122
|
+
),
|
|
123
|
+
}),
|
|
124
|
+
}),
|
|
125
|
+
output: S.Void,
|
|
126
|
+
}) {}
|
|
127
|
+
|
|
128
|
+
export const Toast = S.Struct({
|
|
129
|
+
id: S.String.annotations({ description: 'The id of the toast.' }),
|
|
130
|
+
title: S.optional(Label.annotations({ description: 'The title of the toast.' })),
|
|
131
|
+
description: S.optional(Label.annotations({ description: 'The description of the toast.' })),
|
|
132
|
+
icon: S.optional(S.String.annotations({ description: 'The icon of the toast.' })),
|
|
133
|
+
duration: S.optional(S.Number.annotations({ description: 'The duration of the toast.' })),
|
|
134
|
+
closeLabel: S.optional(Label.annotations({ description: 'The label of the close button.' })),
|
|
135
|
+
actionLabel: S.optional(Label.annotations({ description: 'The label of the action button.' })),
|
|
136
|
+
actionAlt: S.optional(Label.annotations({ description: 'The alt text of the action button.' })),
|
|
137
|
+
onAction: S.optional(
|
|
138
|
+
S.Any.annotations({ description: 'The action to perform when the action button is clicked.' }),
|
|
139
|
+
),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
export interface Toast extends Omit<S.Schema.Type<typeof Toast>, 'onAction'> {
|
|
143
|
+
onAction?: () => void;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export class AddToast extends S.TaggedClass<AddToast>()(UPDATE_LAYOUT, {
|
|
147
|
+
input: S.Struct({
|
|
148
|
+
part: S.Literal('toast').annotations({ description: 'Adding a toast.' }),
|
|
149
|
+
subject: Toast.annotations({ description: 'The toast to add.' }),
|
|
150
|
+
}),
|
|
151
|
+
output: S.Void,
|
|
152
|
+
}) {}
|
|
153
|
+
|
|
154
|
+
export class SwitchWorkspace extends S.TaggedClass<SwitchWorkspace>()(UPDATE_LAYOUT, {
|
|
155
|
+
input: S.Struct({
|
|
156
|
+
part: S.Literal('workspace').annotations({ description: 'Switching the workspace.' }),
|
|
157
|
+
subject: S.String.annotations({ description: 'The id of the workspace to switch to.' }),
|
|
158
|
+
}),
|
|
159
|
+
output: S.Void,
|
|
160
|
+
}) {}
|
|
161
|
+
|
|
162
|
+
export class RevertWorkspace extends S.TaggedClass<RevertWorkspace>()(UPDATE_LAYOUT, {
|
|
163
|
+
input: S.Struct({
|
|
164
|
+
part: S.Literal('workspace').annotations({ description: 'Switching the workspace.' }),
|
|
165
|
+
options: S.Struct({
|
|
166
|
+
revert: S.Literal(true).annotations({ description: 'Revert to the previous workspace.' }),
|
|
167
|
+
}),
|
|
168
|
+
}),
|
|
169
|
+
output: S.Void,
|
|
170
|
+
}) {}
|
|
171
|
+
|
|
172
|
+
export class Open extends S.TaggedClass<Open>()(UPDATE_LAYOUT, {
|
|
173
|
+
input: S.Struct({
|
|
174
|
+
part: S.Literal('main').annotations({ description: 'Opening an item in the main content area.' }),
|
|
175
|
+
subject: S.Array(S.String.annotations({ description: 'Ids of the items to open.' })),
|
|
176
|
+
options: S.optional(
|
|
177
|
+
S.Struct({
|
|
178
|
+
state: S.optional(S.Literal(true).annotations({ description: 'The items are being added.' })),
|
|
179
|
+
key: S.optional(
|
|
180
|
+
S.String.annotations({ description: 'If provided, will replace item with a matching key (id prefix).' }),
|
|
181
|
+
),
|
|
182
|
+
scrollIntoView: S.optional(S.Boolean.annotations({ description: 'Scroll the items into view.' })),
|
|
183
|
+
pivotId: S.optional(S.String.annotations({ description: 'The id of the item to place new items next to.' })),
|
|
184
|
+
positioning: S.optional(
|
|
185
|
+
S.Union(
|
|
186
|
+
S.Literal('start').annotations({ description: 'The items are being added before the pivot item.' }),
|
|
187
|
+
S.Literal('end').annotations({ description: 'The items are being added after the pivot item.' }),
|
|
188
|
+
),
|
|
189
|
+
),
|
|
190
|
+
}),
|
|
191
|
+
),
|
|
192
|
+
}),
|
|
193
|
+
output: S.Void,
|
|
194
|
+
}) {}
|
|
195
|
+
|
|
196
|
+
export class Set extends S.TaggedClass<Set>()(UPDATE_LAYOUT, {
|
|
197
|
+
input: S.Struct({
|
|
198
|
+
part: S.Literal('main').annotations({ description: 'Setting items in the main content area.' }),
|
|
199
|
+
subject: S.Array(S.String.annotations({ description: 'Ids of the items to set.' })),
|
|
200
|
+
options: S.Struct({
|
|
201
|
+
override: S.Literal(true).annotations({ description: 'Override the current items in the main content area.' }),
|
|
202
|
+
}),
|
|
203
|
+
}),
|
|
204
|
+
output: S.Void,
|
|
205
|
+
}) {}
|
|
206
|
+
|
|
207
|
+
export class Close extends S.TaggedClass<Close>()(UPDATE_LAYOUT, {
|
|
208
|
+
input: S.Struct({
|
|
209
|
+
part: S.Literal('main').annotations({ description: 'Closing items in the main content area.' }),
|
|
210
|
+
subject: S.Array(S.String.annotations({ description: 'Ids of the items to close.' })),
|
|
211
|
+
options: S.Struct({
|
|
212
|
+
state: S.Literal(false).annotations({ description: 'The items are being removed.' }),
|
|
213
|
+
}),
|
|
214
|
+
}),
|
|
215
|
+
output: S.Void,
|
|
216
|
+
}) {}
|
|
217
|
+
|
|
218
|
+
export class ScrollIntoView extends S.TaggedClass<ScrollIntoView>()(UPDATE_LAYOUT, {
|
|
219
|
+
input: S.Struct({
|
|
220
|
+
part: S.Literal('current').annotations({ description: 'Setting the current item' }),
|
|
221
|
+
subject: S.optional(S.String.annotations({ description: 'The id of the item to set as current.' })),
|
|
222
|
+
options: S.optional(
|
|
223
|
+
S.Record({ key: S.String, value: S.Any }).annotations({
|
|
224
|
+
description: 'Additional options for the scroll into view.',
|
|
225
|
+
}),
|
|
226
|
+
),
|
|
227
|
+
}),
|
|
228
|
+
output: S.Void,
|
|
229
|
+
}) {}
|
|
230
|
+
|
|
231
|
+
export class Expose extends S.TaggedClass<Expose>()(UPDATE_LAYOUT, {
|
|
232
|
+
input: S.Struct({
|
|
233
|
+
part: S.Literal('navigation').annotations({ description: 'Exposing an item in the navigation area.' }),
|
|
234
|
+
subject: S.String.annotations({ description: 'The id of the item to expose.' }),
|
|
235
|
+
}),
|
|
236
|
+
output: S.Void,
|
|
237
|
+
}) {}
|
|
238
|
+
}
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type JSX, type ForwardedRef, type PropsWithChildren, type ReactNode } from 'react';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import { type GuardedType, type MakeOptional } from '@dxos/util';
|
|
7
|
+
import { type GuardedType, type MakeOptional, type Position } from '@dxos/util';
|
|
9
8
|
|
|
10
|
-
import { type ErrorBoundary } from '
|
|
9
|
+
import { type ErrorBoundary } from '../react';
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* SurfaceProps are the props that are passed to the Surface component.
|
|
@@ -68,45 +67,15 @@ export type SurfaceComponent<T extends Record<string, any> = Record<string, unkn
|
|
|
68
67
|
forwardedRef: ForwardedRef<HTMLElement>,
|
|
69
68
|
) => JSX.Element | null;
|
|
70
69
|
|
|
71
|
-
/**
|
|
72
|
-
* Determines the priority of the surface when multiple components are resolved.
|
|
73
|
-
*
|
|
74
|
-
* - `static` - The component is rendered in the order it was resolved.
|
|
75
|
-
* - `hoist` - The component is rendered before `static` components.
|
|
76
|
-
* - `fallback` - The component is rendered after `static` components.
|
|
77
|
-
*/
|
|
78
|
-
export type SurfaceDisposition = 'static' | 'hoist' | 'fallback';
|
|
79
|
-
|
|
80
70
|
/**
|
|
81
71
|
* Definition of when a SurfaceComponent should be rendered.
|
|
82
72
|
*/
|
|
83
|
-
export type SurfaceDefinition<T extends Record<string, any> = any> = {
|
|
73
|
+
export type SurfaceDefinition<T extends Record<string, any> = any> = Readonly<{
|
|
84
74
|
id: string;
|
|
85
75
|
role: string | string[];
|
|
86
|
-
|
|
76
|
+
position?: Position;
|
|
87
77
|
filter?: (data: Record<string, unknown>) => data is T;
|
|
88
78
|
component: SurfaceComponent<GuardedType<SurfaceDefinition<T>['filter']>>;
|
|
89
|
-
}
|
|
79
|
+
}>;
|
|
90
80
|
|
|
91
81
|
export const createSurface = <T extends Record<string, any> = any>(definition: SurfaceDefinition<T>) => definition;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Surface debug info.
|
|
95
|
-
* NOTE: Short-term measure to track perf issues.
|
|
96
|
-
*/
|
|
97
|
-
export type DebugInfo = {
|
|
98
|
-
id: string;
|
|
99
|
-
created: number;
|
|
100
|
-
renderCount: number;
|
|
101
|
-
} & Pick<SurfaceProps, 'role'>;
|
|
102
|
-
|
|
103
|
-
export type SurfaceContextValue = {
|
|
104
|
-
surfaces: Record<string, SurfaceDefinition>;
|
|
105
|
-
debugInfo?: Map<string, DebugInfo>;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const SurfaceContext = createContext<SurfaceContextValue | undefined>(undefined);
|
|
109
|
-
|
|
110
|
-
export const useSurfaceRoot = () => useContext(SurfaceContext) ?? raise(new Error('Missing SurfaceContext'));
|
|
111
|
-
|
|
112
|
-
export const SurfaceProvider = SurfaceContext.Provider;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Schema as S } from '@effect/schema';
|
|
6
|
+
|
|
7
|
+
export const ResourceKey = S.Union(S.String, S.Record({ key: S.String, value: S.Any }));
|
|
8
|
+
export type ResourceKey = S.Schema.Type<typeof ResourceKey>;
|
|
9
|
+
|
|
10
|
+
export const ResourceLanguage = S.Record({ key: S.String, value: ResourceKey });
|
|
11
|
+
export type ResourceLanguage = S.Schema.Type<typeof ResourceLanguage>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A resource is a collection of translations for a language.
|
|
15
|
+
*/
|
|
16
|
+
export const Resource = S.Record({ key: S.String, value: ResourceLanguage });
|
|
17
|
+
export type Resource = S.Schema.Type<typeof Resource>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { updateCounter } from '@dxos/echo-schema/testing';
|
|
8
|
+
import { registerSignalsRuntime } from '@dxos/echo-signals';
|
|
9
|
+
|
|
10
|
+
import { defineCapability, PluginsContext } from './capabilities';
|
|
11
|
+
|
|
12
|
+
registerSignalsRuntime();
|
|
13
|
+
|
|
14
|
+
const defaultOptions = {
|
|
15
|
+
activate: () => Promise.resolve(false),
|
|
16
|
+
reset: () => Promise.resolve(false),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('PluginsContext', () => {
|
|
20
|
+
it('should return empty array if no capabilities are contributed', () => {
|
|
21
|
+
const context = new PluginsContext(defaultOptions);
|
|
22
|
+
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
23
|
+
expect(context.requestCapabilities(interfaceDef)).toEqual([]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should be able to contribute and request capabilities', () => {
|
|
27
|
+
const context = new PluginsContext(defaultOptions);
|
|
28
|
+
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
29
|
+
const implementation = { example: 'identifier' };
|
|
30
|
+
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
31
|
+
expect(context.requestCapabilities(interfaceDef)).toEqual([implementation]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should be able to remove capabilities', () => {
|
|
35
|
+
const context = new PluginsContext(defaultOptions);
|
|
36
|
+
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
37
|
+
const implementation = { example: 'identifier' };
|
|
38
|
+
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
39
|
+
expect(context.requestCapabilities(interfaceDef)).toEqual([implementation]);
|
|
40
|
+
context.removeCapability(interfaceDef, implementation);
|
|
41
|
+
expect(context.requestCapabilities(interfaceDef)).toEqual([]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should be able to contribute and request multiple implementations', () => {
|
|
45
|
+
const context = new PluginsContext(defaultOptions);
|
|
46
|
+
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
47
|
+
const implementation1 = { example: 'first' };
|
|
48
|
+
const implementation2 = { example: 'second' };
|
|
49
|
+
context.contributeCapability({ interface: interfaceDef, implementation: implementation1, module: 'test' });
|
|
50
|
+
context.contributeCapability({ interface: interfaceDef, implementation: implementation2, module: 'test' });
|
|
51
|
+
expect(context.requestCapabilities(interfaceDef)).toEqual([implementation1, implementation2]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should be able to request multiple capabilities', () => {
|
|
55
|
+
const context = new PluginsContext(defaultOptions);
|
|
56
|
+
const interfaceDef1 = defineCapability<{ one: number }>('@dxos/app-framework/test/one');
|
|
57
|
+
const interfaceDef2 = defineCapability<{ two: number }>('@dxos/app-framework/test/two');
|
|
58
|
+
const implementation1 = { one: 1 };
|
|
59
|
+
const implementation2 = { two: 2 };
|
|
60
|
+
context.contributeCapability({ interface: interfaceDef1, implementation: implementation1, module: 'test' });
|
|
61
|
+
context.contributeCapability({ interface: interfaceDef2, implementation: implementation2, module: 'test' });
|
|
62
|
+
expect(context.requestCapabilities(interfaceDef1)).toEqual([implementation1]);
|
|
63
|
+
expect(context.requestCapabilities(interfaceDef2)).toEqual([implementation2]);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should be reactive', () => {
|
|
67
|
+
const context = new PluginsContext(defaultOptions);
|
|
68
|
+
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
69
|
+
|
|
70
|
+
using updates = updateCounter(() => {
|
|
71
|
+
context.requestCapabilities(interfaceDef);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(updates.count).toEqual(0);
|
|
75
|
+
|
|
76
|
+
const implementation = { example: 'identifier' };
|
|
77
|
+
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
78
|
+
expect(updates.count).toEqual(1);
|
|
79
|
+
|
|
80
|
+
context.removeCapability(interfaceDef, implementation);
|
|
81
|
+
expect(updates.count).toEqual(2);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should not be reactive to changes within the implementation', () => {
|
|
85
|
+
const context = new PluginsContext(defaultOptions);
|
|
86
|
+
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
87
|
+
|
|
88
|
+
using updates = updateCounter(() => {
|
|
89
|
+
context.requestCapabilities(interfaceDef);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(updates.count).toEqual(0);
|
|
93
|
+
|
|
94
|
+
const implementation = { example: 'identifier' };
|
|
95
|
+
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
96
|
+
expect(updates.count).toEqual(1);
|
|
97
|
+
|
|
98
|
+
implementation.example = 'updated';
|
|
99
|
+
expect(updates.count).toEqual(1);
|
|
100
|
+
|
|
101
|
+
const capabilities = context.requestCapabilities(interfaceDef);
|
|
102
|
+
expect(capabilities).toEqual([implementation]);
|
|
103
|
+
expect(capabilities[0].example).toEqual('updated');
|
|
104
|
+
expect(updates.count).toEqual(1);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should be able to wait for a capability', async () => {
|
|
108
|
+
const context = new PluginsContext(defaultOptions);
|
|
109
|
+
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
110
|
+
const implementation = { example: 'identifier' };
|
|
111
|
+
const promise = context.waitForCapability(interfaceDef);
|
|
112
|
+
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
113
|
+
const capability = await promise;
|
|
114
|
+
expect(capability).toEqual(implementation);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface definition for a capability.
|
|
3
|
+
*/
|
|
4
|
+
//
|
|
5
|
+
// Copyright 2025 DXOS.org
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import { effect, untracked } from '@preact/signals-core';
|
|
9
|
+
import { type Effect } from 'effect';
|
|
10
|
+
|
|
11
|
+
import { Trigger } from '@dxos/async';
|
|
12
|
+
import { invariant } from '@dxos/invariant';
|
|
13
|
+
import { create } from '@dxos/live-object';
|
|
14
|
+
import { log } from '@dxos/log';
|
|
15
|
+
import { type MaybePromise } from '@dxos/util';
|
|
16
|
+
|
|
17
|
+
import { type ActivationEvent } from './events';
|
|
18
|
+
|
|
19
|
+
const InterfaceDefTypeId: unique symbol = Symbol.for('InterfaceDefTypeId');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The interface definition of a capability.
|
|
23
|
+
*/
|
|
24
|
+
export type InterfaceDef<T> = {
|
|
25
|
+
[InterfaceDefTypeId]: T;
|
|
26
|
+
identifier: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Helper to define the interface of a capability.
|
|
31
|
+
*/
|
|
32
|
+
export const defineCapability = <T>(identifier: string) => {
|
|
33
|
+
return { identifier } as InterfaceDef<T>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Functionality contributed to the application by a plugin module.
|
|
38
|
+
*/
|
|
39
|
+
export type Capability<T> = {
|
|
40
|
+
/**
|
|
41
|
+
* The interface definition of the capability.
|
|
42
|
+
*/
|
|
43
|
+
interface: InterfaceDef<T>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The implementation of the capability.
|
|
47
|
+
*/
|
|
48
|
+
implementation: T;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Called when the capability is deactivated.
|
|
52
|
+
*/
|
|
53
|
+
deactivate?: () => MaybePromise<void> | Effect.Effect<void, Error>;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type AnyCapability = Capability<any>;
|
|
57
|
+
|
|
58
|
+
type PluginsContextOptions = {
|
|
59
|
+
activate: (event: ActivationEvent) => MaybePromise<boolean>;
|
|
60
|
+
reset: (event: ActivationEvent) => MaybePromise<boolean>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// NOTE: This is implemented as a class to prevent it from being proxied by PluginManager state.
|
|
64
|
+
class CapabilityImpl<T> {
|
|
65
|
+
constructor(
|
|
66
|
+
readonly moduleId: string,
|
|
67
|
+
readonly implementation: T,
|
|
68
|
+
) {}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Helper to define the implementation of a capability.
|
|
73
|
+
*/
|
|
74
|
+
export const contributes = <T>(
|
|
75
|
+
interfaceDef: Capability<T>['interface'],
|
|
76
|
+
implementation: Capability<T>['implementation'],
|
|
77
|
+
deactivate?: Capability<T>['deactivate'],
|
|
78
|
+
): Capability<T> => {
|
|
79
|
+
return { interface: interfaceDef, implementation, deactivate } satisfies Capability<T>;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
type LoadCapability<T, U> = () => Promise<{ default: (props: T) => MaybePromise<Capability<U>> }>;
|
|
83
|
+
type LoadCapabilities<T> = () => Promise<{ default: (props: T) => MaybePromise<AnyCapability[]> }>;
|
|
84
|
+
// TODO(wittjosiah): Not having the array be `any` causes type errors when using the lazy capability.
|
|
85
|
+
type LazyCapability<T, U> = (props?: T) => Promise<() => Promise<Capability<U> | AnyCapability[]>>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Helper to define a lazily loaded implementation of a capability.
|
|
89
|
+
*/
|
|
90
|
+
export const lazy =
|
|
91
|
+
<T, U>(c: LoadCapability<T, U> | LoadCapabilities<T>): LazyCapability<T, U> =>
|
|
92
|
+
async (props?: T) => {
|
|
93
|
+
const { default: getCapability } = await c();
|
|
94
|
+
return async () => getCapability(props as T);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Context which is passed to plugins, allowing them to interact with each other.
|
|
99
|
+
*/
|
|
100
|
+
export class PluginsContext {
|
|
101
|
+
private readonly _definedCapabilities = new Map<string, CapabilityImpl<unknown>[]>();
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Activates plugins based on the activation event.
|
|
105
|
+
* @param event The activation event.
|
|
106
|
+
* @returns Whether the activation was successful.
|
|
107
|
+
*/
|
|
108
|
+
readonly activate: PluginsContextOptions['activate'];
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Re-activates the modules that were activated by the event.
|
|
112
|
+
* @param event The activation event.
|
|
113
|
+
* @returns Whether the reset was successful.
|
|
114
|
+
*/
|
|
115
|
+
readonly reset: PluginsContextOptions['reset'];
|
|
116
|
+
|
|
117
|
+
constructor({ activate, reset }: PluginsContextOptions) {
|
|
118
|
+
this.activate = activate;
|
|
119
|
+
this.reset = reset;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @internal
|
|
124
|
+
*/
|
|
125
|
+
contributeCapability<T>({
|
|
126
|
+
module: moduleId,
|
|
127
|
+
interface: interfaceDef,
|
|
128
|
+
implementation,
|
|
129
|
+
}: {
|
|
130
|
+
module: string;
|
|
131
|
+
interface: InterfaceDef<T>;
|
|
132
|
+
implementation: T;
|
|
133
|
+
}) {
|
|
134
|
+
let current = this._definedCapabilities.get(interfaceDef.identifier);
|
|
135
|
+
if (!current) {
|
|
136
|
+
const object = create<{ value: CapabilityImpl<unknown>[] }>({ value: [] });
|
|
137
|
+
current = untracked(() => object.value);
|
|
138
|
+
this._definedCapabilities.set(interfaceDef.identifier, current);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
current.push(new CapabilityImpl(moduleId, implementation));
|
|
142
|
+
log('capability contributed', {
|
|
143
|
+
id: interfaceDef.identifier,
|
|
144
|
+
moduleId,
|
|
145
|
+
count: untracked(() => current.length),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @internal
|
|
151
|
+
*/
|
|
152
|
+
removeCapability<T>(interfaceDef: InterfaceDef<T>, implementation: T) {
|
|
153
|
+
const current = this._definedCapabilities.get(interfaceDef.identifier);
|
|
154
|
+
if (!current) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const index = current.findIndex((i) => i.implementation === implementation);
|
|
159
|
+
if (index !== -1) {
|
|
160
|
+
current.splice(index, 1);
|
|
161
|
+
log('capability removed', { id: interfaceDef.identifier, count: untracked(() => current.length) });
|
|
162
|
+
} else {
|
|
163
|
+
log.warn('capability not removed', { id: interfaceDef.identifier });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Requests capabilities from the plugin context.
|
|
169
|
+
* @returns An array of capabilities.
|
|
170
|
+
* @reactive
|
|
171
|
+
*/
|
|
172
|
+
requestCapabilities<T, U extends T = T>(
|
|
173
|
+
interfaceDef: InterfaceDef<T>,
|
|
174
|
+
filter?: (capability: T, moduleId: string) => capability is U,
|
|
175
|
+
): U[] {
|
|
176
|
+
let current = this._definedCapabilities.get(interfaceDef.identifier);
|
|
177
|
+
if (!current) {
|
|
178
|
+
const object = create<{ value: CapabilityImpl<unknown>[] }>({ value: [] });
|
|
179
|
+
current = untracked(() => object.value);
|
|
180
|
+
this._definedCapabilities.set(interfaceDef.identifier, current);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// NOTE: This the type-checking for capabilities is done at the time of contribution.
|
|
184
|
+
const capabilities = filter ? current.filter((c) => filter(c.implementation as T, c.moduleId)) : current;
|
|
185
|
+
return capabilities.map((c) => c.implementation) as U[];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Requests a single capability from the plugin context.
|
|
190
|
+
* @returns The capability.
|
|
191
|
+
* @throws If no capability is found.
|
|
192
|
+
* @reactive
|
|
193
|
+
*/
|
|
194
|
+
requestCapability<T, U extends T = T>(
|
|
195
|
+
interfaceDef: InterfaceDef<T>,
|
|
196
|
+
filter?: (capability: T, moduleId: string) => capability is U,
|
|
197
|
+
): U {
|
|
198
|
+
const capability = this.requestCapabilities(interfaceDef, filter)[0];
|
|
199
|
+
invariant(capability, `No capability found for ${interfaceDef.identifier}`);
|
|
200
|
+
return capability;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Waits for a capability to be contributed.
|
|
205
|
+
* @returns The capability.
|
|
206
|
+
*/
|
|
207
|
+
async waitForCapability<T, U extends T = T>(
|
|
208
|
+
interfaceDef: InterfaceDef<T>,
|
|
209
|
+
filter?: (capability: T) => capability is U,
|
|
210
|
+
): Promise<U> {
|
|
211
|
+
const trigger = new Trigger<U>();
|
|
212
|
+
const unsubscribe = effect(() => {
|
|
213
|
+
const capabilities = this.requestCapabilities(interfaceDef, filter);
|
|
214
|
+
if (capabilities[0]) {
|
|
215
|
+
trigger.wake(capabilities[0]);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
const capability = await trigger.wait();
|
|
219
|
+
unsubscribe();
|
|
220
|
+
return capability;
|
|
221
|
+
}
|
|
222
|
+
}
|