@dxos/app-framework 0.8.2-staging.7ac8446 → 0.8.2
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-576BHZC7.mjs → app-graph-builder-DYEAGZPS.mjs} +23 -23
- package/dist/lib/browser/app-graph-builder-DYEAGZPS.mjs.map +7 -0
- package/dist/lib/browser/{chunk-6AVTZPMT.mjs → chunk-5GE2ERNU.mjs} +340 -275
- package/dist/lib/browser/chunk-5GE2ERNU.mjs.map +7 -0
- package/dist/lib/browser/{chunk-SFPT4Z2C.mjs → chunk-WWEJRWFX.mjs} +10 -10
- package/dist/lib/browser/chunk-WWEJRWFX.mjs.map +7 -0
- package/dist/lib/browser/{chunk-PPIBZ5N4.mjs → chunk-ZMXJV64L.mjs} +123 -63
- package/dist/lib/browser/chunk-ZMXJV64L.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +12 -10
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/{intent-dispatcher-3Q67MHZZ.mjs → intent-dispatcher-ELZN5EM7.mjs} +2 -2
- package/dist/lib/browser/{intent-resolver-O763LCLG.mjs → intent-resolver-SGWLINTO.mjs} +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{store-URSN7DZI.mjs → store-YIU6IPZ2.mjs} +7 -6
- package/dist/lib/browser/store-YIU6IPZ2.mjs.map +7 -0
- package/dist/lib/browser/testing/index.mjs +30 -14
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/worker.mjs +5 -3
- package/dist/lib/node/app-graph-builder-GBLISL7L.cjs +146 -0
- package/dist/lib/node/app-graph-builder-GBLISL7L.cjs.map +7 -0
- package/dist/lib/node/{chunk-JUSEAFDU.cjs → chunk-G774ASXO.cjs} +5 -5
- package/dist/lib/node/chunk-G774ASXO.cjs.map +7 -0
- package/dist/lib/node/{chunk-YIFTVCOR.cjs → chunk-HIVITTZD.cjs} +319 -255
- package/dist/lib/node/chunk-HIVITTZD.cjs.map +7 -0
- package/dist/lib/node/{chunk-YNTKVTVX.cjs → chunk-Z2PMVDJ5.cjs} +155 -95
- package/dist/lib/node/chunk-Z2PMVDJ5.cjs.map +7 -0
- package/dist/lib/node/index.cjs +82 -80
- package/dist/lib/node/index.cjs.map +1 -1
- package/dist/lib/node/{intent-dispatcher-H334XLFD.cjs → intent-dispatcher-LFXZJTAS.cjs} +8 -8
- package/dist/lib/node/{intent-dispatcher-H334XLFD.cjs.map → intent-dispatcher-LFXZJTAS.cjs.map} +2 -2
- package/dist/lib/node/{intent-resolver-3F4POWAM.cjs → intent-resolver-EPSFTHL6.cjs} +12 -12
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{store-OFDHTDCB.cjs → store-CVVRXUTH.cjs} +10 -9
- package/dist/lib/node/store-CVVRXUTH.cjs.map +7 -0
- package/dist/lib/node/testing/index.cjs +34 -17
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/lib/node/worker.cjs +40 -38
- package/dist/lib/node/worker.cjs.map +2 -2
- package/dist/lib/node-esm/{app-graph-builder-VYKLSMSZ.mjs → app-graph-builder-LUBDEIT6.mjs} +23 -23
- package/dist/lib/node-esm/app-graph-builder-LUBDEIT6.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-R6A7Z4LU.mjs → chunk-6IKYKERU.mjs} +123 -63
- package/dist/lib/node-esm/chunk-6IKYKERU.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-PHOUQACM.mjs → chunk-I6BVZMAH.mjs} +10 -10
- package/dist/lib/node-esm/chunk-I6BVZMAH.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-AHKIPS2L.mjs → chunk-Z2ZHH4HN.mjs} +340 -275
- package/dist/lib/node-esm/chunk-Z2ZHH4HN.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +12 -10
- package/dist/lib/node-esm/index.mjs.map +1 -1
- package/dist/lib/node-esm/{intent-dispatcher-YDE2ONZA.mjs → intent-dispatcher-A2JCMWRD.mjs} +2 -2
- package/dist/lib/node-esm/{intent-resolver-LAGJ7LXM.mjs → intent-resolver-5C4O43GK.mjs} +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{store-EYSUVNCS.mjs → store-HRZXZ2D2.mjs} +7 -6
- package/dist/lib/node-esm/store-HRZXZ2D2.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +30 -14
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/worker.mjs +5 -3
- package/dist/types/src/App.d.ts +3 -1
- package/dist/types/src/App.d.ts.map +1 -1
- package/dist/types/src/common/capabilities.d.ts +40 -222
- package/dist/types/src/common/capabilities.d.ts.map +1 -1
- package/dist/types/src/common/collaboration.d.ts +19 -0
- package/dist/types/src/common/collaboration.d.ts.map +1 -0
- package/dist/types/src/common/events.d.ts.map +1 -1
- package/dist/types/src/common/file.d.ts +7 -7
- package/dist/types/src/common/file.d.ts.map +1 -1
- package/dist/types/src/common/index.d.ts +1 -0
- package/dist/types/src/common/index.d.ts.map +1 -1
- package/dist/types/src/common/layout.d.ts +166 -158
- package/dist/types/src/common/layout.d.ts.map +1 -1
- package/dist/types/src/common/surface.d.ts.map +1 -1
- package/dist/types/src/common/translations.d.ts +7 -7
- package/dist/types/src/common/translations.d.ts.map +1 -1
- package/dist/types/src/core/capabilities.d.ts +33 -15
- package/dist/types/src/core/capabilities.d.ts.map +1 -1
- package/dist/types/src/core/events.d.ts +4 -1
- package/dist/types/src/core/events.d.ts.map +1 -1
- package/dist/types/src/core/manager.d.ts +14 -11
- package/dist/types/src/core/manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin.d.ts +4 -3
- package/dist/types/src/core/plugin.d.ts.map +1 -1
- package/dist/types/src/helpers.d.ts.map +1 -1
- package/dist/types/src/playground/generator/generator.d.ts.map +1 -1
- package/dist/types/src/playground/logger/schema.d.ts +6 -6
- package/dist/types/src/playground/logger/schema.d.ts.map +1 -1
- package/dist/types/src/playground/playground.stories.d.ts.map +1 -1
- package/dist/types/src/plugin-intent/actions.d.ts +14 -14
- package/dist/types/src/plugin-intent/actions.d.ts.map +1 -1
- package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +29 -3
- package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +1 -1
- package/dist/types/src/plugin-intent/intent.d.ts +14 -20
- package/dist/types/src/plugin-intent/intent.d.ts.map +1 -1
- package/dist/types/src/plugin-settings/actions.d.ts +10 -10
- package/dist/types/src/plugin-settings/actions.d.ts.map +1 -1
- package/dist/types/src/plugin-settings/app-graph-builder.d.ts +2 -195
- package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/plugin-settings/store.d.ts +2 -2
- package/dist/types/src/plugin-settings/store.d.ts.map +1 -1
- package/dist/types/src/react/ErrorBoundary.d.ts +1 -1
- package/dist/types/src/react/ErrorBoundary.d.ts.map +1 -1
- package/dist/types/src/react/IntentContext.d.ts.map +1 -1
- package/dist/types/src/react/Surface.d.ts +2 -2
- package/dist/types/src/react/Surface.d.ts.map +1 -1
- package/dist/types/src/react/useCapabilities.d.ts +2 -2
- package/dist/types/src/react/useCapabilities.d.ts.map +1 -1
- package/dist/types/src/react/useIntentResolver.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.d.ts +6 -2
- 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/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -21
- package/project.json +2 -1
- package/src/App.tsx +98 -48
- package/src/common/capabilities.ts +18 -7
- package/src/common/collaboration.ts +21 -0
- package/src/common/file.ts +7 -7
- package/src/common/index.ts +1 -0
- package/src/common/layout.ts +167 -128
- package/src/common/translations.ts +7 -7
- package/src/core/capabilities.test.ts +55 -36
- package/src/core/capabilities.ts +84 -60
- package/src/core/events.ts +4 -1
- package/src/core/manager.test.ts +22 -22
- package/src/core/manager.ts +34 -26
- package/src/core/plugin.ts +4 -3
- package/src/playground/generator/generator.ts +4 -4
- package/src/playground/logger/schema.ts +5 -5
- package/src/playground/playground.stories.tsx +13 -9
- package/src/plugin-intent/actions.ts +9 -9
- package/src/plugin-intent/intent-dispatcher.test.ts +23 -42
- package/src/plugin-intent/intent-dispatcher.ts +25 -13
- package/src/plugin-intent/intent.ts +22 -20
- package/src/plugin-settings/actions.ts +8 -8
- package/src/plugin-settings/app-graph-builder.ts +129 -94
- package/src/plugin-settings/store.ts +20 -17
- package/src/react/ErrorBoundary.tsx +3 -3
- package/src/react/Surface.stories.tsx +1 -1
- package/src/react/Surface.tsx +3 -3
- package/src/react/useCapabilities.ts +9 -19
- package/src/testing/withPluginManager.stories.tsx +0 -1
- package/src/testing/withPluginManager.tsx +35 -16
- package/tsconfig.json +1 -53
- package/typedoc/.nojekyll +1 -0
- package/typedoc/assets/hierarchy.js +1 -0
- package/typedoc/assets/highlight.css +106 -0
- package/typedoc/assets/icons.js +18 -0
- package/typedoc/assets/icons.svg +1 -0
- package/typedoc/assets/main.js +60 -0
- package/typedoc/assets/navigation.js +1 -0
- package/typedoc/assets/search.js +1 -0
- package/typedoc/assets/style.css +1640 -0
- package/typedoc/classes/CollaborationActions.InsertContent.html +421 -0
- package/typedoc/classes/ErrorBoundary.html +125 -0
- package/typedoc/classes/IntentAction.ShowUndo.html +227 -0
- package/typedoc/classes/IntentAction.Track.html +266 -0
- package/typedoc/classes/LayoutAction.AddToast.html +265 -0
- package/typedoc/classes/LayoutAction.Close.html +382 -0
- package/typedoc/classes/LayoutAction.Expose.html +265 -0
- package/typedoc/classes/LayoutAction.Open.html +1123 -0
- package/typedoc/classes/LayoutAction.RevertWorkspace.html +343 -0
- package/typedoc/classes/LayoutAction.ScrollIntoView.html +460 -0
- package/typedoc/classes/LayoutAction.Set.html +460 -0
- package/typedoc/classes/LayoutAction.SetLayoutMode.html +499 -0
- package/typedoc/classes/LayoutAction.SwitchWorkspace.html +265 -0
- package/typedoc/classes/LayoutAction.UpdateComplementary.html +616 -0
- package/typedoc/classes/LayoutAction.UpdateDialog.html +1123 -0
- package/typedoc/classes/LayoutAction.UpdateLayout.html +461 -0
- package/typedoc/classes/LayoutAction.UpdatePopover.html +1435 -0
- package/typedoc/classes/LayoutAction.UpdateSidebar.html +616 -0
- package/typedoc/classes/Plugin.html +6 -0
- package/typedoc/classes/PluginContext.html +38 -0
- package/typedoc/classes/PluginManager.html +43 -0
- package/typedoc/classes/PluginModule.html +18 -0
- package/typedoc/classes/SettingsAction.Open.html +226 -0
- package/typedoc/classes/SettingsAction.OpenPluginRegistry.html +265 -0
- package/typedoc/functions/Events.createStateEvent.html +2 -0
- package/typedoc/functions/IntentPlugin.html +1 -0
- package/typedoc/functions/SettingsPlugin.html +1 -0
- package/typedoc/functions/allOf.html +2 -0
- package/typedoc/functions/chain.html +3 -0
- package/typedoc/functions/contributes.html +2 -0
- package/typedoc/functions/createDispatcher.html +3 -0
- package/typedoc/functions/createIntent.html +6 -0
- package/typedoc/functions/createResolver.html +2 -0
- package/typedoc/functions/createSurface.html +2 -0
- package/typedoc/functions/defineCapability.html +2 -0
- package/typedoc/functions/defineEvent.html +2 -0
- package/typedoc/functions/defineModule.html +2 -0
- package/typedoc/functions/definePlugin.html +2 -0
- package/typedoc/functions/eventKey.html +2 -0
- package/typedoc/functions/getEvents.html +2 -0
- package/typedoc/functions/isAllOf.html +2 -0
- package/typedoc/functions/isOneOf.html +2 -0
- package/typedoc/functions/isSurfaceAvailable.html +2 -0
- package/typedoc/functions/lazy.html +2 -0
- package/typedoc/functions/oneOf.html +2 -0
- package/typedoc/functions/useApp.html +6 -0
- package/typedoc/functions/useAppGraph.html +1 -0
- package/typedoc/functions/useCapabilities.html +3 -0
- package/typedoc/functions/useCapability.html +4 -0
- package/typedoc/functions/useIntentDispatcher.html +1 -0
- package/typedoc/functions/useIntentResolver.html +1 -0
- package/typedoc/functions/useLayout.html +1 -0
- package/typedoc/functions/usePluginManager.html +2 -0
- package/typedoc/hierarchy.html +1 -0
- package/typedoc/index.html +16 -0
- package/typedoc/interfaces/LayoutAction.Toast.html +10 -0
- package/typedoc/media/LICENSE +8 -0
- package/typedoc/modules/Capabilities.html +1 -0
- package/typedoc/modules/CollaborationActions.html +1 -0
- package/typedoc/modules/Events.html +1 -0
- package/typedoc/modules/IntentAction.html +1 -0
- package/typedoc/modules/LayoutAction.html +2 -0
- package/typedoc/modules/SettingsAction.html +1 -0
- package/typedoc/modules.html +1 -0
- package/typedoc/types/ActivationEvent.html +8 -0
- package/typedoc/types/ActivationEvents.html +2 -0
- package/typedoc/types/AnyCapability.html +1 -0
- package/typedoc/types/AnyIntent.html +1 -0
- package/typedoc/types/AnyIntentChain.html +1 -0
- package/typedoc/types/AnyIntentEffectResult.html +1 -0
- package/typedoc/types/AnyIntentResolver.html +1 -0
- package/typedoc/types/AnyIntentResult.html +1 -0
- package/typedoc/types/Capabilities.FileUploader.html +1 -0
- package/typedoc/types/Capabilities.IntentResolver.html +1 -0
- package/typedoc/types/Capabilities.Layout.html +1 -0
- package/typedoc/types/Capabilities.Metadata.html +1 -0
- package/typedoc/types/Capabilities.ReactContext.html +1 -0
- package/typedoc/types/Capabilities.ReactRoot.html +1 -0
- package/typedoc/types/Capabilities.ReactSurface.html +1 -0
- package/typedoc/types/Capabilities.Settings.html +4 -0
- package/typedoc/types/Capability.html +9 -0
- package/typedoc/types/CreateAppOptions.html +10 -0
- package/typedoc/types/FileInfo.html +1 -0
- package/typedoc/types/Intent.html +10 -0
- package/typedoc/types/IntentChain.html +6 -0
- package/typedoc/types/IntentContext.html +5 -0
- package/typedoc/types/IntentData.html +1 -0
- package/typedoc/types/IntentDispatcher.html +2 -0
- package/typedoc/types/IntentDispatcherResult.html +2 -0
- package/typedoc/types/IntentEffectDefinition.html +2 -0
- package/typedoc/types/IntentEffectResult.html +15 -0
- package/typedoc/types/IntentParams.html +3 -0
- package/typedoc/types/IntentResolver.html +2 -0
- package/typedoc/types/IntentResultData.html +1 -0
- package/typedoc/types/IntentSchema.html +1 -0
- package/typedoc/types/IntentUndo.html +2 -0
- package/typedoc/types/InterfaceDef.html +4 -0
- package/typedoc/types/Label.html +1 -0
- package/typedoc/types/NodeSerializer.html +8 -0
- package/typedoc/types/PluginManagerOptions.html +6 -0
- package/typedoc/types/PluginMeta.html +21 -0
- package/typedoc/types/PromiseIntentDispatcher.html +2 -0
- package/typedoc/types/PromiseIntentUndo.html +2 -0
- package/typedoc/types/Resource.html +1 -0
- package/typedoc/types/ResourceKey.html +1 -0
- package/typedoc/types/ResourceLanguage.html +1 -0
- package/typedoc/types/SerializedNode.html +4 -0
- package/typedoc/types/SurfaceComponent.html +2 -0
- package/typedoc/types/SurfaceDefinition.html +2 -0
- package/typedoc/types/SurfaceProps.html +4 -0
- package/typedoc/variables/Capabilities.AnchorSort.html +1 -0
- package/typedoc/variables/Capabilities.AppGraph.html +1 -0
- package/typedoc/variables/Capabilities.AppGraphBuilder.html +1 -0
- package/typedoc/variables/Capabilities.AppGraphSerializer.html +1 -0
- package/typedoc/variables/Capabilities.ArtifactDefinition.html +1 -0
- package/typedoc/variables/Capabilities.FileUploader.html +1 -0
- package/typedoc/variables/Capabilities.IntentDispatcher.html +1 -0
- package/typedoc/variables/Capabilities.IntentResolver.html +1 -0
- package/typedoc/variables/Capabilities.Layout.html +1 -0
- package/typedoc/variables/Capabilities.Metadata.html +1 -0
- package/typedoc/variables/Capabilities.Null.html +1 -0
- package/typedoc/variables/Capabilities.PluginManager.html +1 -0
- package/typedoc/variables/Capabilities.ReactContext.html +1 -0
- package/typedoc/variables/Capabilities.ReactRoot.html +1 -0
- package/typedoc/variables/Capabilities.ReactSurface.html +1 -0
- package/typedoc/variables/Capabilities.RxRegistry.html +1 -0
- package/typedoc/variables/Capabilities.Settings.html +1 -0
- package/typedoc/variables/Capabilities.SettingsStore.html +1 -0
- package/typedoc/variables/Capabilities.Tools.html +1 -0
- package/typedoc/variables/Capabilities.Translations.html +1 -0
- package/typedoc/variables/Events.AppGraphReady.html +2 -0
- package/typedoc/variables/Events.DispatcherReady.html +2 -0
- package/typedoc/variables/Events.LayoutReady.html +1 -0
- package/typedoc/variables/Events.SettingsReady.html +2 -0
- package/typedoc/variables/Events.SetupAppGraph.html +2 -0
- package/typedoc/variables/Events.SetupArtifactDefinition.html +2 -0
- package/typedoc/variables/Events.SetupIntentResolver.html +2 -0
- package/typedoc/variables/Events.SetupMetadata.html +2 -0
- package/typedoc/variables/Events.SetupReactSurface.html +2 -0
- package/typedoc/variables/Events.SetupSettings.html +2 -0
- package/typedoc/variables/Events.SetupTranslations.html +2 -0
- package/typedoc/variables/Events.Startup.html +2 -0
- package/typedoc/variables/FileInfoSchema.html +1 -0
- package/typedoc/variables/INTENT_ACTION.html +1 -0
- package/typedoc/variables/INTENT_PLUGIN.html +1 -0
- package/typedoc/variables/LAYOUT_ACTION.html +1 -0
- package/typedoc/variables/LAYOUT_PLUGIN.html +1 -0
- package/typedoc/variables/Label.html +1 -0
- package/typedoc/variables/LayoutAction.Toast.html +1 -0
- package/typedoc/variables/LayoutAction.UPDATE_LAYOUT.html +1 -0
- package/typedoc/variables/PluginManagerProvider.html +2 -0
- package/typedoc/variables/Resource.html +2 -0
- package/typedoc/variables/ResourceKey.html +1 -0
- package/typedoc/variables/ResourceLanguage.html +1 -0
- package/typedoc/variables/SETTINGS_ACTION.html +1 -0
- package/typedoc/variables/SETTINGS_ID.html +1 -0
- package/typedoc/variables/SETTINGS_KEY.html +1 -0
- package/typedoc/variables/SETTINGS_PLUGIN.html +1 -0
- package/typedoc/variables/Surface.html +2 -0
- package/typedoc/variables/defaultFileTypes.html +1 -0
- package/dist/lib/browser/app-graph-builder-576BHZC7.mjs.map +0 -7
- package/dist/lib/browser/chunk-6AVTZPMT.mjs.map +0 -7
- package/dist/lib/browser/chunk-PPIBZ5N4.mjs.map +0 -7
- package/dist/lib/browser/chunk-SFPT4Z2C.mjs.map +0 -7
- package/dist/lib/browser/store-URSN7DZI.mjs.map +0 -7
- package/dist/lib/node/app-graph-builder-JZCSKYPY.cjs +0 -146
- package/dist/lib/node/app-graph-builder-JZCSKYPY.cjs.map +0 -7
- package/dist/lib/node/chunk-JUSEAFDU.cjs.map +0 -7
- package/dist/lib/node/chunk-YIFTVCOR.cjs.map +0 -7
- package/dist/lib/node/chunk-YNTKVTVX.cjs.map +0 -7
- package/dist/lib/node/store-OFDHTDCB.cjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-VYKLSMSZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-AHKIPS2L.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PHOUQACM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-R6A7Z4LU.mjs.map +0 -7
- package/dist/lib/node-esm/store-EYSUVNCS.mjs.map +0 -7
- /package/dist/lib/browser/{intent-dispatcher-3Q67MHZZ.mjs.map → intent-dispatcher-ELZN5EM7.mjs.map} +0 -0
- /package/dist/lib/browser/{intent-resolver-O763LCLG.mjs.map → intent-resolver-SGWLINTO.mjs.map} +0 -0
- /package/dist/lib/node/{intent-resolver-3F4POWAM.cjs.map → intent-resolver-EPSFTHL6.cjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-dispatcher-YDE2ONZA.mjs.map → intent-dispatcher-A2JCMWRD.mjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-resolver-LAGJ7LXM.mjs.map → intent-resolver-5C4O43GK.mjs.map} +0 -0
|
@@ -2,15 +2,11 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Registry } from '@effect-rx/rx-react';
|
|
5
6
|
import { Effect } from 'effect';
|
|
6
|
-
import { describe, expect, it } from 'vitest';
|
|
7
|
+
import { describe, expect, it, onTestFinished } from 'vitest';
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
-
import { registerSignalsRuntime } from '@dxos/echo-signals';
|
|
10
|
-
|
|
11
|
-
import { defineCapability, PluginsContext } from './capabilities';
|
|
12
|
-
|
|
13
|
-
registerSignalsRuntime();
|
|
9
|
+
import { defineCapability, PluginContext } from './capabilities';
|
|
14
10
|
|
|
15
11
|
const defaultOptions = {
|
|
16
12
|
activate: () => Effect.succeed(false),
|
|
@@ -19,99 +15,122 @@ const defaultOptions = {
|
|
|
19
15
|
|
|
20
16
|
describe('PluginsContext', () => {
|
|
21
17
|
it('should return empty array if no capabilities are contributed', () => {
|
|
22
|
-
const
|
|
18
|
+
const registry = Registry.make();
|
|
19
|
+
const context = new PluginContext({ registry, ...defaultOptions });
|
|
23
20
|
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
24
|
-
expect(context.
|
|
21
|
+
expect(context.getCapabilities(interfaceDef)).toEqual([]);
|
|
25
22
|
});
|
|
26
23
|
|
|
27
24
|
it('should be able to contribute and request capabilities', () => {
|
|
28
|
-
const
|
|
25
|
+
const registry = Registry.make();
|
|
26
|
+
const context = new PluginContext({ registry, ...defaultOptions });
|
|
29
27
|
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
30
28
|
const implementation = { example: 'identifier' };
|
|
31
29
|
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
32
|
-
expect(context.
|
|
30
|
+
expect(context.getCapabilities(interfaceDef)).toEqual([implementation]);
|
|
33
31
|
});
|
|
34
32
|
|
|
35
33
|
it('should be able to remove capabilities', () => {
|
|
36
|
-
const
|
|
34
|
+
const registry = Registry.make();
|
|
35
|
+
const context = new PluginContext({ registry, ...defaultOptions });
|
|
37
36
|
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
38
37
|
const implementation = { example: 'identifier' };
|
|
39
38
|
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
40
|
-
expect(context.
|
|
39
|
+
expect(context.getCapabilities(interfaceDef)).toEqual([implementation]);
|
|
41
40
|
context.removeCapability(interfaceDef, implementation);
|
|
42
|
-
expect(context.
|
|
41
|
+
expect(context.getCapabilities(interfaceDef)).toEqual([]);
|
|
43
42
|
});
|
|
44
43
|
|
|
45
44
|
it('should be able to contribute and request multiple implementations', () => {
|
|
46
|
-
const
|
|
45
|
+
const registry = Registry.make();
|
|
46
|
+
const context = new PluginContext({ registry, ...defaultOptions });
|
|
47
47
|
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
48
48
|
const implementation1 = { example: 'first' };
|
|
49
49
|
const implementation2 = { example: 'second' };
|
|
50
50
|
context.contributeCapability({ interface: interfaceDef, implementation: implementation1, module: 'test' });
|
|
51
51
|
context.contributeCapability({ interface: interfaceDef, implementation: implementation2, module: 'test' });
|
|
52
|
-
expect(context.
|
|
52
|
+
expect(context.getCapabilities(interfaceDef)).toEqual([implementation1, implementation2]);
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
it('should be able to request multiple capabilities', () => {
|
|
56
|
-
const
|
|
56
|
+
const registry = Registry.make();
|
|
57
|
+
const context = new PluginContext({ registry, ...defaultOptions });
|
|
57
58
|
const interfaceDef1 = defineCapability<{ one: number }>('@dxos/app-framework/test/one');
|
|
58
59
|
const interfaceDef2 = defineCapability<{ two: number }>('@dxos/app-framework/test/two');
|
|
59
60
|
const implementation1 = { one: 1 };
|
|
60
61
|
const implementation2 = { two: 2 };
|
|
61
62
|
context.contributeCapability({ interface: interfaceDef1, implementation: implementation1, module: 'test' });
|
|
62
63
|
context.contributeCapability({ interface: interfaceDef2, implementation: implementation2, module: 'test' });
|
|
63
|
-
expect(context.
|
|
64
|
-
expect(context.
|
|
64
|
+
expect(context.getCapabilities(interfaceDef1)).toEqual([implementation1]);
|
|
65
|
+
expect(context.getCapabilities(interfaceDef2)).toEqual([implementation2]);
|
|
65
66
|
});
|
|
66
67
|
|
|
67
68
|
it('should be reactive', () => {
|
|
68
|
-
const
|
|
69
|
+
const registry = Registry.make();
|
|
70
|
+
const context = new PluginContext({ registry, ...defaultOptions });
|
|
69
71
|
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
let count = 0;
|
|
74
|
+
const cancel = registry.subscribe(context.capabilities(interfaceDef), () => {
|
|
75
|
+
count++;
|
|
73
76
|
});
|
|
77
|
+
onTestFinished(() => cancel());
|
|
78
|
+
expect(count).toEqual(0);
|
|
74
79
|
|
|
75
|
-
|
|
80
|
+
registry.get(context.capabilities(interfaceDef));
|
|
81
|
+
expect(count).toEqual(1);
|
|
76
82
|
|
|
77
83
|
const implementation = { example: 'identifier' };
|
|
78
84
|
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
79
|
-
expect(
|
|
85
|
+
expect(count).toEqual(2);
|
|
80
86
|
|
|
81
87
|
context.removeCapability(interfaceDef, implementation);
|
|
82
|
-
expect(
|
|
88
|
+
expect(count).toEqual(3);
|
|
83
89
|
});
|
|
84
90
|
|
|
85
91
|
it('should not be reactive to changes within the implementation', () => {
|
|
86
|
-
const
|
|
92
|
+
const registry = Registry.make();
|
|
93
|
+
const context = new PluginContext({ registry, ...defaultOptions });
|
|
87
94
|
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
88
95
|
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
let count = 0;
|
|
97
|
+
const cancel = registry.subscribe(context.capabilities(interfaceDef), () => {
|
|
98
|
+
count++;
|
|
91
99
|
});
|
|
100
|
+
onTestFinished(() => cancel());
|
|
101
|
+
expect(count).toEqual(0);
|
|
92
102
|
|
|
93
|
-
|
|
103
|
+
registry.get(context.capabilities(interfaceDef));
|
|
104
|
+
expect(count).toEqual(1);
|
|
94
105
|
|
|
95
106
|
const implementation = { example: 'identifier' };
|
|
96
107
|
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
97
|
-
expect(
|
|
108
|
+
expect(count).toEqual(2);
|
|
98
109
|
|
|
99
110
|
implementation.example = 'updated';
|
|
100
|
-
expect(
|
|
111
|
+
expect(count).toEqual(2);
|
|
101
112
|
|
|
102
|
-
const capabilities = context.
|
|
113
|
+
const capabilities = context.getCapabilities(interfaceDef);
|
|
103
114
|
expect(capabilities).toEqual([implementation]);
|
|
104
115
|
expect(capabilities[0].example).toEqual('updated');
|
|
105
|
-
expect(
|
|
116
|
+
expect(count).toEqual(2);
|
|
106
117
|
});
|
|
107
118
|
|
|
108
119
|
it('should be able to wait for a capability', async () => {
|
|
109
|
-
const
|
|
120
|
+
const registry = Registry.make();
|
|
121
|
+
const context = new PluginContext({ registry, ...defaultOptions });
|
|
110
122
|
const interfaceDef = defineCapability<{ example: string }>('@dxos/app-framework/test/example');
|
|
123
|
+
|
|
124
|
+
let capability: { example: string } | undefined;
|
|
125
|
+
const cancel = registry.subscribe(context.capabilities(interfaceDef), (capabilities) => {
|
|
126
|
+
capability = capabilities[0];
|
|
127
|
+
});
|
|
128
|
+
onTestFinished(() => cancel());
|
|
129
|
+
registry.get(context.capabilities(interfaceDef));
|
|
130
|
+
expect(capability).toBeUndefined();
|
|
131
|
+
|
|
111
132
|
const implementation = { example: 'identifier' };
|
|
112
|
-
const promise = context.waitForCapability(interfaceDef);
|
|
113
133
|
context.contributeCapability({ interface: interfaceDef, implementation, module: 'test' });
|
|
114
|
-
const capability = await promise;
|
|
115
134
|
expect(capability).toEqual(implementation);
|
|
116
135
|
});
|
|
117
136
|
});
|
package/src/core/capabilities.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interface definition for a capability.
|
|
3
|
-
*/
|
|
4
1
|
//
|
|
5
2
|
// Copyright 2025 DXOS.org
|
|
6
3
|
//
|
|
7
4
|
|
|
8
|
-
import {
|
|
5
|
+
import { type Registry, Rx } from '@effect-rx/rx-react';
|
|
9
6
|
import { Effect } from 'effect';
|
|
10
7
|
|
|
11
8
|
import { Trigger } from '@dxos/async';
|
|
12
9
|
import { invariant } from '@dxos/invariant';
|
|
13
|
-
import { create } from '@dxos/live-object';
|
|
14
10
|
import { log } from '@dxos/log';
|
|
15
11
|
import { type MaybePromise } from '@dxos/util';
|
|
16
12
|
|
|
@@ -34,7 +30,8 @@ export const defineCapability = <T>(identifier: string) => {
|
|
|
34
30
|
};
|
|
35
31
|
|
|
36
32
|
/**
|
|
37
|
-
*
|
|
33
|
+
* A unique string identifier with a Typescript type associated with it.
|
|
34
|
+
* When a capability is contributed to the application an implementation of the interface is provided.
|
|
38
35
|
*/
|
|
39
36
|
export type Capability<T> = {
|
|
40
37
|
/**
|
|
@@ -56,6 +53,7 @@ export type Capability<T> = {
|
|
|
56
53
|
export type AnyCapability = Capability<any>;
|
|
57
54
|
|
|
58
55
|
type PluginsContextOptions = {
|
|
56
|
+
registry: Registry.Registry;
|
|
59
57
|
activate: (event: ActivationEvent) => Effect.Effect<boolean, Error>;
|
|
60
58
|
reset: (event: ActivationEvent) => Effect.Effect<boolean, Error>;
|
|
61
59
|
};
|
|
@@ -95,10 +93,31 @@ export const lazy =
|
|
|
95
93
|
};
|
|
96
94
|
|
|
97
95
|
/**
|
|
98
|
-
*
|
|
96
|
+
* Facilitates the dependency injection between [plugin modules](#pluginmodule) by allowing them contribute and request capabilities from each other.
|
|
97
|
+
* It tracks the capabilities that are contributed in an in-memory live object.
|
|
98
|
+
* This allows the application to subscribe to this state and incorporate plugins which are added dynamically.
|
|
99
99
|
*/
|
|
100
|
-
export class
|
|
101
|
-
private readonly
|
|
100
|
+
export class PluginContext {
|
|
101
|
+
private readonly _registry: Registry.Registry;
|
|
102
|
+
|
|
103
|
+
private readonly _capabilityImpls = Rx.family<string, Rx.Writable<CapabilityImpl<unknown>[]>>(() => {
|
|
104
|
+
return Rx.make<CapabilityImpl<unknown>[]>([]).pipe(Rx.keepAlive);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
readonly _capabilities = Rx.family<string, Rx.Rx<unknown[]>>((id: string) => {
|
|
108
|
+
return Rx.make((get) => {
|
|
109
|
+
const current = get(this._capabilityImpls(id));
|
|
110
|
+
return current.map((c) => c.implementation);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
readonly _capability = Rx.family<string, Rx.Rx<unknown>>((id: string) => {
|
|
115
|
+
return Rx.make((get) => {
|
|
116
|
+
const current = get(this._capabilities(id));
|
|
117
|
+
invariant(current.length > 0, `No capability found for ${id}`);
|
|
118
|
+
return current[0];
|
|
119
|
+
});
|
|
120
|
+
});
|
|
102
121
|
|
|
103
122
|
/**
|
|
104
123
|
* Activates plugins based on the activation event.
|
|
@@ -114,7 +133,8 @@ export class PluginsContext {
|
|
|
114
133
|
*/
|
|
115
134
|
readonly reset: PluginsContextOptions['reset'];
|
|
116
135
|
|
|
117
|
-
constructor({ activate, reset }: PluginsContextOptions) {
|
|
136
|
+
constructor({ registry, activate, reset }: PluginsContextOptions) {
|
|
137
|
+
this._registry = registry;
|
|
118
138
|
this.activate = activate;
|
|
119
139
|
this.reset = reset;
|
|
120
140
|
}
|
|
@@ -130,94 +150,98 @@ export class PluginsContext {
|
|
|
130
150
|
module: string;
|
|
131
151
|
interface: InterfaceDef<T>;
|
|
132
152
|
implementation: T;
|
|
133
|
-
}) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
this._definedCapabilities.set(interfaceDef.identifier, current);
|
|
153
|
+
}): void {
|
|
154
|
+
const current = this._registry.get(this._capabilityImpls(interfaceDef.identifier));
|
|
155
|
+
const capability = new CapabilityImpl(moduleId, implementation);
|
|
156
|
+
if (current.includes(capability)) {
|
|
157
|
+
return;
|
|
139
158
|
}
|
|
140
159
|
|
|
141
|
-
|
|
160
|
+
this._registry.set(this._capabilityImpls(interfaceDef.identifier), [...current, capability]);
|
|
142
161
|
log('capability contributed', {
|
|
143
162
|
id: interfaceDef.identifier,
|
|
144
163
|
moduleId,
|
|
145
|
-
count:
|
|
164
|
+
count: current.length,
|
|
146
165
|
});
|
|
147
166
|
}
|
|
148
167
|
|
|
149
168
|
/**
|
|
150
169
|
* @internal
|
|
151
170
|
*/
|
|
152
|
-
removeCapability<T>(interfaceDef: InterfaceDef<T>, implementation: T) {
|
|
153
|
-
const current = this.
|
|
154
|
-
if (
|
|
171
|
+
removeCapability<T>(interfaceDef: InterfaceDef<T>, implementation: T): void {
|
|
172
|
+
const current = this._registry.get(this._capabilityImpls(interfaceDef.identifier));
|
|
173
|
+
if (current.length === 0) {
|
|
155
174
|
return;
|
|
156
175
|
}
|
|
157
176
|
|
|
158
|
-
const
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
log('capability removed', { id: interfaceDef.identifier, count:
|
|
177
|
+
const next = current.filter((c) => c.implementation !== implementation);
|
|
178
|
+
if (next.length !== current.length) {
|
|
179
|
+
this._registry.set(this._capabilityImpls(interfaceDef.identifier), next);
|
|
180
|
+
log('capability removed', { id: interfaceDef.identifier, count: current.length });
|
|
162
181
|
} else {
|
|
163
182
|
log.warn('capability not removed', { id: interfaceDef.identifier });
|
|
164
183
|
}
|
|
165
184
|
}
|
|
166
185
|
|
|
167
186
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
187
|
+
* Get the Rx reference to the available capabilities for a given interface.
|
|
188
|
+
* Primarily useful for deriving other Rx values based on the capabilities or
|
|
189
|
+
* for subscribing to changes in the capabilities.
|
|
190
|
+
* @returns An Rx reference to the available capabilities.
|
|
171
191
|
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
}
|
|
192
|
+
capabilities<T>(interfaceDef: InterfaceDef<T>): Rx.Rx<T[]> {
|
|
193
|
+
// NOTE: This the type-checking for capabilities is done at the time of contribution.
|
|
194
|
+
return this._capabilities(interfaceDef.identifier) as Rx.Rx<T[]>;
|
|
195
|
+
}
|
|
182
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Get the Rx reference to the available capabilities for a given interface.
|
|
199
|
+
* Primarily useful for deriving other Rx values based on the capability or
|
|
200
|
+
* for subscribing to changes in the capability.
|
|
201
|
+
* @returns An Rx reference to the available capability.
|
|
202
|
+
* @throws If no capability is found.
|
|
203
|
+
*/
|
|
204
|
+
capability<T>(interfaceDef: InterfaceDef<T>): Rx.Rx<T> {
|
|
183
205
|
// NOTE: This the type-checking for capabilities is done at the time of contribution.
|
|
184
|
-
|
|
185
|
-
|
|
206
|
+
return this._capability(interfaceDef.identifier) as Rx.Rx<T>;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get capabilities from the plugin context.
|
|
211
|
+
* @returns An array of capabilities.
|
|
212
|
+
*/
|
|
213
|
+
getCapabilities<T>(interfaceDef: InterfaceDef<T>): T[] {
|
|
214
|
+
return this._registry.get(this.capabilities(interfaceDef));
|
|
186
215
|
}
|
|
187
216
|
|
|
188
217
|
/**
|
|
189
218
|
* Requests a single capability from the plugin context.
|
|
190
219
|
* @returns The capability.
|
|
191
220
|
* @throws If no capability is found.
|
|
192
|
-
* @reactive
|
|
193
221
|
*/
|
|
194
|
-
|
|
195
|
-
interfaceDef
|
|
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;
|
|
222
|
+
getCapability<T>(interfaceDef: InterfaceDef<T>): T {
|
|
223
|
+
return this._registry.get(this.capability(interfaceDef));
|
|
201
224
|
}
|
|
202
225
|
|
|
203
226
|
/**
|
|
204
|
-
* Waits for a capability to be
|
|
227
|
+
* Waits for a capability to be available.
|
|
205
228
|
* @returns The capability.
|
|
206
229
|
*/
|
|
207
|
-
async waitForCapability<T
|
|
208
|
-
interfaceDef
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
async waitForCapability<T>(interfaceDef: InterfaceDef<T>): Promise<T> {
|
|
231
|
+
const [capability] = this.getCapabilities(interfaceDef);
|
|
232
|
+
if (capability) {
|
|
233
|
+
return capability;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const trigger = new Trigger<T>();
|
|
237
|
+
const cancel = this._registry.subscribe(this.capabilities(interfaceDef), (capabilities) => {
|
|
238
|
+
if (capabilities.length > 0) {
|
|
215
239
|
trigger.wake(capabilities[0]);
|
|
216
240
|
}
|
|
217
241
|
});
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
return
|
|
242
|
+
const result = await trigger.wait();
|
|
243
|
+
cancel();
|
|
244
|
+
return result;
|
|
221
245
|
}
|
|
222
246
|
|
|
223
247
|
async activatePromise(event: ActivationEvent): Promise<boolean> {
|
package/src/core/events.ts
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* A unique string identifier representing an event.
|
|
7
|
+
* This is expected to be a URI, where initial parts are often the id of the plugin whose package defines the event.
|
|
8
|
+
*
|
|
9
|
+
* @example dxos.org/plugin/example/event/ready
|
|
7
10
|
*/
|
|
8
11
|
export type ActivationEvent = {
|
|
9
12
|
id: string;
|
package/src/core/manager.test.ts
CHANGED
|
@@ -11,9 +11,9 @@ import { raise } from '@dxos/debug';
|
|
|
11
11
|
import { updateCounter } from '@dxos/echo-schema/testing';
|
|
12
12
|
import { registerSignalsRuntime } from '@dxos/echo-signals';
|
|
13
13
|
import { invariant } from '@dxos/invariant';
|
|
14
|
-
import {
|
|
14
|
+
import { live } from '@dxos/live-object';
|
|
15
15
|
|
|
16
|
-
import { contributes, defineCapability, type
|
|
16
|
+
import { contributes, defineCapability, type PluginContext } from './capabilities';
|
|
17
17
|
import { allOf, defineEvent, oneOf } from './events';
|
|
18
18
|
import { PluginManager } from './manager';
|
|
19
19
|
import { definePlugin, defineModule, type Plugin } from './plugin';
|
|
@@ -205,22 +205,22 @@ describe('PluginManager', () => {
|
|
|
205
205
|
|
|
206
206
|
const manager = new PluginManager({ pluginLoader });
|
|
207
207
|
expect(manager.active).toEqual([]);
|
|
208
|
-
expect(manager.context.
|
|
208
|
+
expect(manager.context.getCapabilities(Number)).toHaveLength(0);
|
|
209
209
|
|
|
210
210
|
await manager.add(Plugin1.meta.id);
|
|
211
211
|
await manager.activate(CountEvent);
|
|
212
212
|
expect(manager.active).toEqual([Plugin1.meta.id]);
|
|
213
|
-
expect(manager.context.
|
|
213
|
+
expect(manager.context.getCapabilities(Number)).toHaveLength(1);
|
|
214
214
|
|
|
215
215
|
await manager.add(Plugin2.meta.id);
|
|
216
216
|
await manager.activate(CountEvent);
|
|
217
217
|
expect(manager.active).toEqual([Plugin1.meta.id, Plugin2.meta.id]);
|
|
218
|
-
expect(manager.context.
|
|
218
|
+
expect(manager.context.getCapabilities(Number)).toHaveLength(2);
|
|
219
219
|
|
|
220
220
|
await manager.add(Plugin3.meta.id);
|
|
221
221
|
await manager.activate(CountEvent);
|
|
222
222
|
expect(manager.active).toEqual([Plugin1.meta.id, Plugin2.meta.id, Plugin3.meta.id]);
|
|
223
|
-
expect(manager.context.
|
|
223
|
+
expect(manager.context.getCapabilities(Number)).toHaveLength(3);
|
|
224
224
|
});
|
|
225
225
|
|
|
226
226
|
it('should only activate modules after all activatation events have been fired', async () => {
|
|
@@ -235,16 +235,16 @@ describe('PluginManager', () => {
|
|
|
235
235
|
|
|
236
236
|
const manager = new PluginManager({ pluginLoader });
|
|
237
237
|
expect(manager.active).toEqual([]);
|
|
238
|
-
expect(manager.context.
|
|
238
|
+
expect(manager.context.getCapabilities(String)).toHaveLength(0);
|
|
239
239
|
|
|
240
240
|
await manager.add(testMeta.id);
|
|
241
241
|
await manager.activate(Events.Startup);
|
|
242
242
|
expect(manager.active).toEqual([]);
|
|
243
|
-
expect(manager.context.
|
|
243
|
+
expect(manager.context.getCapabilities(String)).toHaveLength(0);
|
|
244
244
|
|
|
245
245
|
await manager.activate(CountEvent);
|
|
246
246
|
expect(manager.active).toEqual([Hello.id]);
|
|
247
|
-
expect(manager.context.
|
|
247
|
+
expect(manager.context.getCapabilities(String)).toHaveLength(1);
|
|
248
248
|
});
|
|
249
249
|
|
|
250
250
|
it('should only activate modules once when multiple activatation events have been fired', async () => {
|
|
@@ -261,25 +261,25 @@ describe('PluginManager', () => {
|
|
|
261
261
|
|
|
262
262
|
const manager = new PluginManager({ pluginLoader });
|
|
263
263
|
expect(manager.active).toEqual([]);
|
|
264
|
-
expect(manager.context.
|
|
264
|
+
expect(manager.context.getCapabilities(String)).toHaveLength(0);
|
|
265
265
|
expect(count).toEqual(0);
|
|
266
266
|
|
|
267
267
|
await manager.add(testMeta.id);
|
|
268
268
|
await manager.activate(CountEvent);
|
|
269
269
|
expect(manager.active).toEqual([Hello.id]);
|
|
270
|
-
expect(manager.context.
|
|
270
|
+
expect(manager.context.getCapabilities(String)).toHaveLength(1);
|
|
271
271
|
expect(count).toEqual(1);
|
|
272
272
|
|
|
273
273
|
await manager.activate(Events.Startup);
|
|
274
274
|
expect(manager.active).toEqual([Hello.id]);
|
|
275
|
-
expect(manager.context.
|
|
275
|
+
expect(manager.context.getCapabilities(String)).toHaveLength(1);
|
|
276
276
|
expect(count).toEqual(1);
|
|
277
277
|
});
|
|
278
278
|
|
|
279
279
|
it('should be able to disable and re-enable an active plugin', async () => {
|
|
280
280
|
const state = { total: 0 };
|
|
281
|
-
const computeTotal = (context:
|
|
282
|
-
const numbers = context.
|
|
281
|
+
const computeTotal = (context: PluginContext) => {
|
|
282
|
+
const numbers = context.getCapabilities(Number);
|
|
283
283
|
state.total = numbers.reduce((acc, n) => acc + n.number, 0);
|
|
284
284
|
};
|
|
285
285
|
|
|
@@ -322,7 +322,7 @@ describe('PluginManager', () => {
|
|
|
322
322
|
expect(manager.active).toEqual([...Test.modules.map((m) => m.id), Count.meta.id]);
|
|
323
323
|
expect(manager.pendingReset).toEqual([]);
|
|
324
324
|
|
|
325
|
-
const totals = manager.context.
|
|
325
|
+
const totals = manager.context.getCapabilities(Total);
|
|
326
326
|
expect(totals).toHaveLength(1);
|
|
327
327
|
expect(totals[0].total).toEqual(6);
|
|
328
328
|
}
|
|
@@ -332,7 +332,7 @@ describe('PluginManager', () => {
|
|
|
332
332
|
expect(manager.active).toEqual([Count.meta.id]);
|
|
333
333
|
expect(manager.pendingReset).toEqual([]);
|
|
334
334
|
|
|
335
|
-
const totals = manager.context.
|
|
335
|
+
const totals = manager.context.getCapabilities(Total);
|
|
336
336
|
expect(totals).toHaveLength(1);
|
|
337
337
|
// Total doesn't change because it is not reactive.
|
|
338
338
|
expect(totals[0].total).toEqual(6);
|
|
@@ -343,7 +343,7 @@ describe('PluginManager', () => {
|
|
|
343
343
|
expect(manager.active).toEqual([Count.meta.id, ...Test.modules.map((m) => m.id)]);
|
|
344
344
|
expect(manager.pendingReset).toEqual([]);
|
|
345
345
|
|
|
346
|
-
const totals = manager.context.
|
|
346
|
+
const totals = manager.context.getCapabilities(Total);
|
|
347
347
|
expect(totals).toHaveLength(1);
|
|
348
348
|
expect(totals[0].total).toEqual(6);
|
|
349
349
|
}
|
|
@@ -358,14 +358,14 @@ describe('PluginManager', () => {
|
|
|
358
358
|
id,
|
|
359
359
|
activatesOn: Events.Startup,
|
|
360
360
|
activatesAfter: [stateEvent],
|
|
361
|
-
activate: () => contributes(Number,
|
|
361
|
+
activate: () => contributes(Number, live({ number: 1 })),
|
|
362
362
|
}),
|
|
363
363
|
defineModule({
|
|
364
364
|
id: 'dxos.org/test/doubler',
|
|
365
365
|
activatesOn: stateEvent,
|
|
366
366
|
activate: (context) => {
|
|
367
|
-
const counter = context.
|
|
368
|
-
const state =
|
|
367
|
+
const counter = context.getCapability(Number);
|
|
368
|
+
const state = live({ total: counter.number * 2 });
|
|
369
369
|
const unsubscribe = effect(() => {
|
|
370
370
|
state.total = counter.number * 2;
|
|
371
371
|
});
|
|
@@ -380,8 +380,8 @@ describe('PluginManager', () => {
|
|
|
380
380
|
await manager.activate(Events.Startup);
|
|
381
381
|
expect(manager.active).toEqual(Test.modules.map((m) => m.id));
|
|
382
382
|
|
|
383
|
-
const counter = manager.context.
|
|
384
|
-
const doubler = manager.context.
|
|
383
|
+
const counter = manager.context.getCapability(Number);
|
|
384
|
+
const doubler = manager.context.getCapability(Total);
|
|
385
385
|
expect(counter.number).toEqual(1);
|
|
386
386
|
expect(doubler.total).toEqual(2);
|
|
387
387
|
|