@dxos/app-framework 0.8.2-main.f11618f → 0.8.2-main.fbd8ed0
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-OHM2Z6YQ.mjs → app-graph-builder-6E7NCZ77.mjs} +23 -23
- package/dist/lib/browser/app-graph-builder-6E7NCZ77.mjs.map +7 -0
- package/dist/lib/browser/{chunk-DVNSCQJ5.mjs → chunk-2KSDY3EZ.mjs} +297 -270
- package/dist/lib/browser/chunk-2KSDY3EZ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-X2YC645Z.mjs → chunk-K3HOLGVH.mjs} +38 -26
- package/dist/lib/browser/chunk-K3HOLGVH.mjs.map +7 -0
- package/dist/lib/browser/{chunk-SFPT4Z2C.mjs → chunk-KPRHX73H.mjs} +9 -9
- package/dist/lib/browser/chunk-KPRHX73H.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +8 -8
- package/dist/lib/browser/{intent-dispatcher-J7QIFHLO.mjs → intent-dispatcher-VGUJBPPN.mjs} +2 -2
- package/dist/lib/browser/{intent-resolver-QV5MDMDV.mjs → intent-resolver-QLFZY5R5.mjs} +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{store-XMPVLJOQ.mjs → store-QGVXOY4T.mjs} +7 -6
- package/dist/lib/browser/store-QGVXOY4T.mjs.map +7 -0
- package/dist/lib/browser/testing/index.mjs +7 -3
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/worker.mjs +3 -3
- package/dist/lib/node/app-graph-builder-4IWMG67O.cjs +146 -0
- package/dist/lib/node/app-graph-builder-4IWMG67O.cjs.map +7 -0
- package/dist/lib/node/{chunk-I3CJYEBC.cjs → chunk-2EBZ2ICH.cjs} +137 -110
- package/dist/lib/node/chunk-2EBZ2ICH.cjs.map +7 -0
- package/dist/lib/node/{chunk-5UOVF3OR.cjs → chunk-7J66KH2T.cjs} +78 -66
- package/dist/lib/node/chunk-7J66KH2T.cjs.map +7 -0
- package/dist/lib/node/{chunk-JUSEAFDU.cjs → chunk-JQMNABMK.cjs} +4 -4
- package/dist/lib/node/chunk-JQMNABMK.cjs.map +7 -0
- package/dist/lib/node/index.cjs +80 -80
- package/dist/lib/node/{intent-dispatcher-FQPJNKIZ.cjs → intent-dispatcher-TASJBG5M.cjs} +8 -8
- package/dist/lib/node/{intent-dispatcher-FQPJNKIZ.cjs.map → intent-dispatcher-TASJBG5M.cjs.map} +2 -2
- package/dist/lib/node/{intent-resolver-PBAOGJS6.cjs → intent-resolver-5CG5NIJY.cjs} +12 -12
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{store-N7JLYYDI.cjs → store-IF3UR2KA.cjs} +10 -9
- package/dist/lib/node/store-IF3UR2KA.cjs.map +7 -0
- package/dist/lib/node/testing/index.cjs +14 -9
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/lib/node/worker.cjs +39 -39
- package/dist/lib/node/worker.cjs.map +1 -1
- package/dist/lib/node-esm/{app-graph-builder-OMH534A4.mjs → app-graph-builder-LYCG5CO3.mjs} +23 -23
- package/dist/lib/node-esm/app-graph-builder-LYCG5CO3.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-GSDBF2CK.mjs → chunk-BOEJMAVK.mjs} +297 -270
- package/dist/lib/node-esm/chunk-BOEJMAVK.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-QHXUTJHE.mjs → chunk-ISNBS46Y.mjs} +38 -26
- package/dist/lib/node-esm/chunk-ISNBS46Y.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-PHOUQACM.mjs → chunk-JUJF5L4G.mjs} +9 -9
- package/dist/lib/node-esm/chunk-JUJF5L4G.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +8 -8
- package/dist/lib/node-esm/{intent-dispatcher-QDUGA7NT.mjs → intent-dispatcher-ZUSNX2OY.mjs} +2 -2
- package/dist/lib/node-esm/{intent-resolver-P7TC5RBD.mjs → intent-resolver-NGDHUKDD.mjs} +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{store-M2BYJL6K.mjs → store-NCRSE25X.mjs} +7 -6
- package/dist/lib/node-esm/store-NCRSE25X.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +7 -3
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/worker.mjs +3 -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 +6 -196
- package/dist/types/src/common/capabilities.d.ts.map +1 -1
- package/dist/types/src/common/collaboration.d.ts +14 -7
- package/dist/types/src/common/collaboration.d.ts.map +1 -1
- 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/layout.d.ts +163 -163
- 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 +28 -13
- package/dist/types/src/core/capabilities.d.ts.map +1 -1
- package/dist/types/src/core/events.d.ts.map +1 -1
- package/dist/types/src/core/manager.d.ts +6 -3
- package/dist/types/src/core/manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin.d.ts +2 -2
- 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/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 +3 -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/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 +5 -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 +25 -20
- package/src/App.tsx +14 -2
- package/src/common/capabilities.ts +7 -4
- package/src/common/collaboration.ts +11 -8
- package/src/common/file.ts +7 -7
- package/src/common/layout.ts +148 -136
- package/src/common/translations.ts +7 -7
- package/src/core/capabilities.test.ts +55 -36
- package/src/core/capabilities.ts +77 -57
- package/src/core/manager.test.ts +19 -19
- package/src/core/manager.ts +14 -6
- package/src/core/plugin.ts +2 -2
- package/src/playground/generator/generator.ts +4 -4
- package/src/playground/logger/schema.ts +5 -5
- package/src/playground/playground.stories.tsx +1 -1
- 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 +7 -11
- 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/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 +11 -3
- package/tsconfig.json +3 -0
- package/typedoc/assets/navigation.js +1 -1
- package/typedoc/assets/search.js +1 -1
- package/typedoc/classes/CollaborationActions.InsertContent.html +280 -241
- package/typedoc/classes/ErrorBoundary.html +6 -6
- package/typedoc/classes/IntentAction.ShowUndo.html +125 -125
- package/typedoc/classes/IntentAction.Track.html +239 -239
- package/typedoc/classes/LayoutAction.AddToast.html +163 -163
- package/typedoc/classes/LayoutAction.Close.html +352 -352
- package/typedoc/classes/LayoutAction.Expose.html +238 -238
- package/typedoc/classes/LayoutAction.Open.html +904 -748
- package/typedoc/classes/LayoutAction.RevertWorkspace.html +241 -241
- package/typedoc/classes/LayoutAction.ScrollIntoView.html +280 -280
- package/typedoc/classes/LayoutAction.Set.html +436 -358
- package/typedoc/classes/LayoutAction.SetLayoutMode.html +469 -391
- package/typedoc/classes/LayoutAction.SwitchWorkspace.html +238 -238
- package/typedoc/classes/LayoutAction.UpdateComplementary.html +358 -358
- package/typedoc/classes/LayoutAction.UpdateDialog.html +553 -475
- package/typedoc/classes/LayoutAction.UpdateLayout.html +281 -281
- package/typedoc/classes/LayoutAction.UpdatePopover.html +826 -826
- package/typedoc/classes/LayoutAction.UpdateSidebar.html +397 -319
- package/typedoc/classes/Plugin.html +3 -3
- package/typedoc/classes/PluginContext.html +38 -0
- package/typedoc/classes/PluginManager.html +17 -16
- package/typedoc/classes/PluginModule.html +9 -9
- package/typedoc/classes/SettingsAction.Open.html +199 -199
- package/typedoc/classes/SettingsAction.OpenPluginRegistry.html +124 -124
- package/typedoc/functions/Events.createStateEvent.html +2 -2
- package/typedoc/functions/IntentPlugin.html +1 -1
- package/typedoc/functions/SettingsPlugin.html +1 -1
- package/typedoc/functions/allOf.html +2 -2
- package/typedoc/functions/chain.html +2 -2
- package/typedoc/functions/contributes.html +2 -2
- package/typedoc/functions/createApp.html +2 -2
- package/typedoc/functions/createDispatcher.html +3 -3
- package/typedoc/functions/createIntent.html +3 -3
- package/typedoc/functions/createResolver.html +2 -2
- package/typedoc/functions/createSurface.html +2 -2
- package/typedoc/functions/defineCapability.html +2 -2
- package/typedoc/functions/defineEvent.html +2 -2
- package/typedoc/functions/defineModule.html +2 -2
- package/typedoc/functions/definePlugin.html +2 -2
- package/typedoc/functions/eventKey.html +2 -2
- package/typedoc/functions/getEvents.html +2 -2
- package/typedoc/functions/isAllOf.html +2 -2
- package/typedoc/functions/isOneOf.html +2 -2
- package/typedoc/functions/isSurfaceAvailable.html +2 -2
- package/typedoc/functions/lazy.html +2 -2
- package/typedoc/functions/oneOf.html +2 -2
- package/typedoc/functions/useAppGraph.html +1 -1
- package/typedoc/functions/useCapabilities.html +3 -3
- package/typedoc/functions/useCapability.html +3 -3
- package/typedoc/functions/useIntentDispatcher.html +1 -1
- package/typedoc/functions/useIntentResolver.html +1 -1
- package/typedoc/functions/useLayout.html +1 -1
- package/typedoc/functions/usePluginManager.html +2 -2
- package/typedoc/hierarchy.html +1 -1
- package/typedoc/index.html +2 -2
- package/typedoc/interfaces/LayoutAction.Toast.html +2 -2
- package/typedoc/modules/Capabilities.html +1 -1
- package/typedoc/modules/CollaborationActions.html +1 -1
- package/typedoc/modules/Events.html +1 -1
- package/typedoc/modules/IntentAction.html +1 -1
- package/typedoc/modules/LayoutAction.html +2 -2
- package/typedoc/modules/SettingsAction.html +1 -1
- package/typedoc/modules.html +1 -1
- package/typedoc/types/ActivationEvent.html +3 -3
- package/typedoc/types/ActivationEvents.html +2 -2
- package/typedoc/types/AnyCapability.html +1 -1
- package/typedoc/types/AnyIntent.html +1 -1
- package/typedoc/types/AnyIntentChain.html +1 -1
- package/typedoc/types/AnyIntentEffectResult.html +1 -1
- package/typedoc/types/AnyIntentResolver.html +1 -1
- package/typedoc/types/AnyIntentResult.html +1 -1
- package/typedoc/types/Capabilities.FileUploader.html +1 -1
- package/typedoc/types/Capabilities.IntentResolver.html +1 -1
- package/typedoc/types/Capabilities.Layout.html +1 -1
- package/typedoc/types/Capabilities.Metadata.html +1 -1
- package/typedoc/types/Capabilities.ReactContext.html +1 -1
- package/typedoc/types/Capabilities.ReactRoot.html +1 -1
- package/typedoc/types/Capabilities.ReactSurface.html +1 -1
- package/typedoc/types/Capabilities.Settings.html +2 -2
- package/typedoc/types/Capability.html +5 -5
- package/typedoc/types/CreateAppOptions.html +3 -2
- package/typedoc/types/FileInfo.html +1 -1
- package/typedoc/types/Intent.html +6 -10
- package/typedoc/types/IntentChain.html +3 -3
- package/typedoc/types/IntentContext.html +2 -2
- package/typedoc/types/IntentData.html +1 -1
- package/typedoc/types/IntentDispatcher.html +2 -2
- package/typedoc/types/IntentDispatcherResult.html +2 -2
- package/typedoc/types/IntentEffectDefinition.html +2 -2
- package/typedoc/types/IntentEffectResult.html +6 -6
- package/typedoc/types/IntentParams.html +2 -2
- package/typedoc/types/IntentResolver.html +2 -2
- package/typedoc/types/IntentResultData.html +1 -1
- package/typedoc/types/IntentSchema.html +1 -1
- package/typedoc/types/IntentUndo.html +2 -2
- package/typedoc/types/InterfaceDef.html +3 -3
- package/typedoc/types/Label.html +1 -1
- package/typedoc/types/NodeSerializer.html +3 -3
- package/typedoc/types/PluginManagerOptions.html +3 -2
- package/typedoc/types/PluginMeta.html +9 -9
- package/typedoc/types/PromiseIntentDispatcher.html +2 -2
- package/typedoc/types/PromiseIntentUndo.html +2 -2
- package/typedoc/types/Resource.html +1 -1
- package/typedoc/types/ResourceKey.html +1 -1
- package/typedoc/types/ResourceLanguage.html +1 -1
- package/typedoc/types/SerializedNode.html +2 -2
- package/typedoc/types/SurfaceComponent.html +2 -2
- package/typedoc/types/SurfaceDefinition.html +2 -2
- package/typedoc/types/SurfaceProps.html +2 -2
- package/typedoc/variables/Capabilities.AppGraph.html +1 -1
- package/typedoc/variables/Capabilities.AppGraphBuilder.html +1 -1
- package/typedoc/variables/Capabilities.AppGraphSerializer.html +1 -1
- package/typedoc/variables/Capabilities.ArtifactDefinition.html +1 -1
- package/typedoc/variables/Capabilities.FileUploader.html +1 -1
- package/typedoc/variables/Capabilities.IntentDispatcher.html +1 -1
- package/typedoc/variables/Capabilities.IntentResolver.html +1 -1
- package/typedoc/variables/Capabilities.Layout.html +1 -1
- package/typedoc/variables/Capabilities.Metadata.html +1 -1
- package/typedoc/variables/Capabilities.Null.html +1 -1
- package/typedoc/variables/Capabilities.PluginManager.html +1 -1
- package/typedoc/variables/Capabilities.ReactContext.html +1 -1
- package/typedoc/variables/Capabilities.ReactRoot.html +1 -1
- package/typedoc/variables/Capabilities.ReactSurface.html +1 -1
- package/typedoc/variables/Capabilities.RxRegistry.html +1 -0
- package/typedoc/variables/Capabilities.Settings.html +1 -1
- package/typedoc/variables/Capabilities.SettingsStore.html +1 -1
- package/typedoc/variables/Capabilities.Tools.html +1 -1
- package/typedoc/variables/Capabilities.Translations.html +1 -1
- package/typedoc/variables/Events.AppGraphReady.html +2 -2
- package/typedoc/variables/Events.DispatcherReady.html +2 -2
- package/typedoc/variables/Events.LayoutReady.html +1 -1
- package/typedoc/variables/Events.SettingsReady.html +2 -2
- package/typedoc/variables/Events.SetupAppGraph.html +2 -2
- package/typedoc/variables/Events.SetupArtifactDefinition.html +2 -2
- package/typedoc/variables/Events.SetupIntentResolver.html +2 -2
- package/typedoc/variables/Events.SetupMetadata.html +2 -2
- package/typedoc/variables/Events.SetupReactSurface.html +2 -2
- package/typedoc/variables/Events.SetupSettings.html +2 -2
- package/typedoc/variables/Events.SetupTranslations.html +2 -2
- package/typedoc/variables/Events.Startup.html +2 -2
- package/typedoc/variables/FileInfoSchema.html +1 -1
- package/typedoc/variables/INTENT_ACTION.html +1 -1
- package/typedoc/variables/INTENT_PLUGIN.html +1 -1
- package/typedoc/variables/LAYOUT_ACTION.html +1 -1
- package/typedoc/variables/LAYOUT_PLUGIN.html +1 -1
- package/typedoc/variables/Label.html +1 -1
- package/typedoc/variables/LayoutAction.Toast.html +1 -1
- package/typedoc/variables/LayoutAction.UPDATE_LAYOUT.html +1 -1
- package/typedoc/variables/PluginManagerProvider.html +2 -2
- package/typedoc/variables/Resource.html +2 -2
- package/typedoc/variables/ResourceKey.html +1 -1
- package/typedoc/variables/ResourceLanguage.html +1 -1
- package/typedoc/variables/SETTINGS_ACTION.html +1 -1
- package/typedoc/variables/SETTINGS_ID.html +1 -1
- package/typedoc/variables/SETTINGS_KEY.html +1 -1
- package/typedoc/variables/SETTINGS_PLUGIN.html +1 -1
- package/typedoc/variables/Surface.html +2 -2
- package/typedoc/variables/defaultFileTypes.html +1 -1
- package/dist/lib/browser/app-graph-builder-OHM2Z6YQ.mjs.map +0 -7
- package/dist/lib/browser/chunk-DVNSCQJ5.mjs.map +0 -7
- package/dist/lib/browser/chunk-SFPT4Z2C.mjs.map +0 -7
- package/dist/lib/browser/chunk-X2YC645Z.mjs.map +0 -7
- package/dist/lib/browser/store-XMPVLJOQ.mjs.map +0 -7
- package/dist/lib/node/app-graph-builder-Z45FKS52.cjs +0 -146
- package/dist/lib/node/app-graph-builder-Z45FKS52.cjs.map +0 -7
- package/dist/lib/node/chunk-5UOVF3OR.cjs.map +0 -7
- package/dist/lib/node/chunk-I3CJYEBC.cjs.map +0 -7
- package/dist/lib/node/chunk-JUSEAFDU.cjs.map +0 -7
- package/dist/lib/node/store-N7JLYYDI.cjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-OMH534A4.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GSDBF2CK.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PHOUQACM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-QHXUTJHE.mjs.map +0 -7
- package/dist/lib/node-esm/store-M2BYJL6K.mjs.map +0 -7
- package/typedoc/classes/PluginsContext.html +0 -25
- /package/dist/lib/browser/{intent-dispatcher-J7QIFHLO.mjs.map → intent-dispatcher-VGUJBPPN.mjs.map} +0 -0
- /package/dist/lib/browser/{intent-resolver-QV5MDMDV.mjs.map → intent-resolver-QLFZY5R5.mjs.map} +0 -0
- /package/dist/lib/node/{intent-resolver-PBAOGJS6.cjs.map → intent-resolver-5CG5NIJY.cjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-dispatcher-QDUGA7NT.mjs.map → intent-dispatcher-ZUSNX2OY.mjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-resolver-P7TC5RBD.mjs.map → intent-resolver-NGDHUKDD.mjs.map} +0 -0
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 { live } from '@dxos/live-object';
|
|
14
10
|
import { log } from '@dxos/log';
|
|
15
11
|
import { type MaybePromise } from '@dxos/util';
|
|
16
12
|
|
|
@@ -57,6 +53,7 @@ export type Capability<T> = {
|
|
|
57
53
|
export type AnyCapability = Capability<any>;
|
|
58
54
|
|
|
59
55
|
type PluginsContextOptions = {
|
|
56
|
+
registry: Registry.Registry;
|
|
60
57
|
activate: (event: ActivationEvent) => Effect.Effect<boolean, Error>;
|
|
61
58
|
reset: (event: ActivationEvent) => Effect.Effect<boolean, Error>;
|
|
62
59
|
};
|
|
@@ -100,9 +97,27 @@ export const lazy =
|
|
|
100
97
|
* It tracks the capabilities that are contributed in an in-memory live object.
|
|
101
98
|
* This allows the application to subscribe to this state and incorporate plugins which are added dynamically.
|
|
102
99
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
+
});
|
|
106
121
|
|
|
107
122
|
/**
|
|
108
123
|
* Activates plugins based on the activation event.
|
|
@@ -118,7 +133,8 @@ export class PluginsContext {
|
|
|
118
133
|
*/
|
|
119
134
|
readonly reset: PluginsContextOptions['reset'];
|
|
120
135
|
|
|
121
|
-
constructor({ activate, reset }: PluginsContextOptions) {
|
|
136
|
+
constructor({ registry, activate, reset }: PluginsContextOptions) {
|
|
137
|
+
this._registry = registry;
|
|
122
138
|
this.activate = activate;
|
|
123
139
|
this.reset = reset;
|
|
124
140
|
}
|
|
@@ -135,18 +151,17 @@ export class PluginsContext {
|
|
|
135
151
|
interface: InterfaceDef<T>;
|
|
136
152
|
implementation: T;
|
|
137
153
|
}) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
this._definedCapabilities.set(interfaceDef.identifier, current);
|
|
154
|
+
const current = this._registry.get(this._capabilityImpls(interfaceDef.identifier));
|
|
155
|
+
const capability = new CapabilityImpl(moduleId, implementation);
|
|
156
|
+
if (current.includes(capability)) {
|
|
157
|
+
return;
|
|
143
158
|
}
|
|
144
159
|
|
|
145
|
-
|
|
160
|
+
this._registry.set(this._capabilityImpls(interfaceDef.identifier), [...current, capability]);
|
|
146
161
|
log('capability contributed', {
|
|
147
162
|
id: interfaceDef.identifier,
|
|
148
163
|
moduleId,
|
|
149
|
-
count:
|
|
164
|
+
count: current.length,
|
|
150
165
|
});
|
|
151
166
|
}
|
|
152
167
|
|
|
@@ -154,74 +169,79 @@ export class PluginsContext {
|
|
|
154
169
|
* @internal
|
|
155
170
|
*/
|
|
156
171
|
removeCapability<T>(interfaceDef: InterfaceDef<T>, implementation: T) {
|
|
157
|
-
const current = this.
|
|
158
|
-
if (
|
|
172
|
+
const current = this._registry.get(this._capabilityImpls(interfaceDef.identifier));
|
|
173
|
+
if (current.length === 0) {
|
|
159
174
|
return;
|
|
160
175
|
}
|
|
161
176
|
|
|
162
|
-
const
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
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 });
|
|
166
181
|
} else {
|
|
167
182
|
log.warn('capability not removed', { id: interfaceDef.identifier });
|
|
168
183
|
}
|
|
169
184
|
}
|
|
170
185
|
|
|
171
186
|
/**
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
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.
|
|
175
191
|
*/
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
let current = this._definedCapabilities.get(interfaceDef.identifier);
|
|
181
|
-
if (!current) {
|
|
182
|
-
const object = live<{ value: CapabilityImpl<unknown>[] }>({ value: [] });
|
|
183
|
-
current = untracked(() => object.value);
|
|
184
|
-
this._definedCapabilities.set(interfaceDef.identifier, current);
|
|
185
|
-
}
|
|
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
|
+
}
|
|
186
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> {
|
|
187
205
|
// NOTE: This the type-checking for capabilities is done at the time of contribution.
|
|
188
|
-
|
|
189
|
-
|
|
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));
|
|
190
215
|
}
|
|
191
216
|
|
|
192
217
|
/**
|
|
193
218
|
* Requests a single capability from the plugin context.
|
|
194
219
|
* @returns The capability.
|
|
195
220
|
* @throws If no capability is found.
|
|
196
|
-
* @reactive
|
|
197
221
|
*/
|
|
198
|
-
|
|
199
|
-
interfaceDef
|
|
200
|
-
filter?: (capability: T, moduleId: string) => capability is U,
|
|
201
|
-
): U {
|
|
202
|
-
const capability = this.requestCapabilities(interfaceDef, filter)[0];
|
|
203
|
-
invariant(capability, `No capability found for ${interfaceDef.identifier}`);
|
|
204
|
-
return capability;
|
|
222
|
+
getCapability<T>(interfaceDef: InterfaceDef<T>): T {
|
|
223
|
+
return this._registry.get(this.capability(interfaceDef));
|
|
205
224
|
}
|
|
206
225
|
|
|
207
226
|
/**
|
|
208
|
-
* Waits for a capability to be
|
|
227
|
+
* Waits for a capability to be available.
|
|
209
228
|
* @returns The capability.
|
|
210
229
|
*/
|
|
211
|
-
async waitForCapability<T
|
|
212
|
-
interfaceDef
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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) {
|
|
219
239
|
trigger.wake(capabilities[0]);
|
|
220
240
|
}
|
|
221
241
|
});
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
return
|
|
242
|
+
const result = await trigger.wait();
|
|
243
|
+
cancel();
|
|
244
|
+
return result;
|
|
225
245
|
}
|
|
226
246
|
|
|
227
247
|
async activatePromise(event: ActivationEvent): Promise<boolean> {
|
package/src/core/manager.test.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { registerSignalsRuntime } from '@dxos/echo-signals';
|
|
|
13
13
|
import { invariant } from '@dxos/invariant';
|
|
14
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
|
}
|
|
@@ -364,7 +364,7 @@ describe('PluginManager', () => {
|
|
|
364
364
|
id: 'dxos.org/test/doubler',
|
|
365
365
|
activatesOn: stateEvent,
|
|
366
366
|
activate: (context) => {
|
|
367
|
-
const counter = context.
|
|
367
|
+
const counter = context.getCapability(Number);
|
|
368
368
|
const state = live({ total: counter.number * 2 });
|
|
369
369
|
const unsubscribe = effect(() => {
|
|
370
370
|
state.total = counter.number * 2;
|
|
@@ -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
|
|
package/src/core/manager.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Registry } from '@effect-rx/rx-react';
|
|
5
6
|
import { untracked } from '@preact/signals-core';
|
|
6
7
|
import { Array as A, Effect, Either, Match, pipe } from 'effect';
|
|
7
8
|
|
|
@@ -10,7 +11,7 @@ import { live, type Live } from '@dxos/live-object';
|
|
|
10
11
|
import { log } from '@dxos/log';
|
|
11
12
|
import { type MaybePromise } from '@dxos/util';
|
|
12
13
|
|
|
13
|
-
import { type AnyCapability,
|
|
14
|
+
import { type AnyCapability, PluginContext } from './capabilities';
|
|
14
15
|
import { type ActivationEvent, eventKey, getEvents, isAllOf } from './events';
|
|
15
16
|
import { type PluginModule, type Plugin } from './plugin';
|
|
16
17
|
|
|
@@ -24,6 +25,7 @@ export type PluginManagerOptions = {
|
|
|
24
25
|
plugins?: Plugin[];
|
|
25
26
|
core?: string[];
|
|
26
27
|
enabled?: string[];
|
|
28
|
+
registry?: Registry.Registry;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
type PluginManagerState = {
|
|
@@ -43,12 +45,10 @@ type PluginManagerState = {
|
|
|
43
45
|
|
|
44
46
|
export class PluginManager {
|
|
45
47
|
readonly activation = new Event<{ event: string; state: 'activating' | 'activated' | 'error'; error?: any }>();
|
|
48
|
+
readonly context: PluginContext;
|
|
49
|
+
readonly registry: Registry.Registry;
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
activate: (event) => this._activate(event),
|
|
49
|
-
reset: (id) => this._reset(id),
|
|
50
|
-
});
|
|
51
|
-
|
|
51
|
+
// TODO(wittjosiah): Replace with Rx.
|
|
52
52
|
private readonly _state: Live<PluginManagerState>;
|
|
53
53
|
private readonly _pluginLoader: PluginManagerOptions['pluginLoader'];
|
|
54
54
|
private readonly _capabilities = new Map<string, AnyCapability[]>();
|
|
@@ -58,7 +58,15 @@ export class PluginManager {
|
|
|
58
58
|
plugins = [],
|
|
59
59
|
core = plugins.map(({ meta }) => meta.id),
|
|
60
60
|
enabled = [],
|
|
61
|
+
registry,
|
|
61
62
|
}: PluginManagerOptions) {
|
|
63
|
+
this.registry = registry ?? Registry.make();
|
|
64
|
+
this.context = new PluginContext({
|
|
65
|
+
registry: this.registry,
|
|
66
|
+
activate: (event) => this._activate(event),
|
|
67
|
+
reset: (id) => this._reset(id),
|
|
68
|
+
});
|
|
69
|
+
|
|
62
70
|
this._pluginLoader = pluginLoader;
|
|
63
71
|
this._state = live({
|
|
64
72
|
plugins,
|
package/src/core/plugin.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type MaybePromise } from '@dxos/util';
|
|
6
6
|
|
|
7
|
-
import { type AnyCapability, type
|
|
7
|
+
import { type AnyCapability, type PluginContext } from './capabilities';
|
|
8
8
|
import { type ActivationEvent, type ActivationEvents } from './events';
|
|
9
9
|
|
|
10
10
|
interface PluginModuleInterface {
|
|
@@ -36,7 +36,7 @@ interface PluginModuleInterface {
|
|
|
36
36
|
* @returns The capabilities of the module.
|
|
37
37
|
*/
|
|
38
38
|
activate: (
|
|
39
|
-
context:
|
|
39
|
+
context: PluginContext,
|
|
40
40
|
) => MaybePromise<AnyCapability | AnyCapability[]> | Promise<() => Promise<AnyCapability | AnyCapability[]>>;
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Schema
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
6
|
|
|
7
7
|
import { Capabilities, Events } from '../../common';
|
|
8
8
|
import { contributes, defineEvent, defineCapability, defineModule, definePlugin } from '../../core';
|
|
@@ -15,9 +15,9 @@ export const CountEvent = defineEvent('dxos.org/test/generator/count');
|
|
|
15
15
|
export const createPluginId = (id: string) => `dxos.org/test/generator/${id}`;
|
|
16
16
|
|
|
17
17
|
export const createGeneratorIntent = (id: string) => {
|
|
18
|
-
class Alert extends
|
|
19
|
-
input:
|
|
20
|
-
output:
|
|
18
|
+
class Alert extends Schema.TaggedClass<Alert>()(`${createPluginId(id)}/action/alert`, {
|
|
19
|
+
input: Schema.Void,
|
|
20
|
+
output: Schema.Void,
|
|
21
21
|
}) {}
|
|
22
22
|
|
|
23
23
|
return Alert as unknown as IntentSchema<any, any>;
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Schema
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
6
|
|
|
7
|
-
export class Log extends
|
|
8
|
-
input:
|
|
9
|
-
message:
|
|
7
|
+
export class Log extends Schema.TaggedClass<Log>()('dxos.org/test/logger/log', {
|
|
8
|
+
input: Schema.Struct({
|
|
9
|
+
message: Schema.String,
|
|
10
10
|
}),
|
|
11
|
-
output:
|
|
11
|
+
output: Schema.Void,
|
|
12
12
|
}) {}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Schema
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
6
|
|
|
7
7
|
import { Label } from './intent';
|
|
8
8
|
|
|
@@ -13,21 +13,21 @@ export namespace IntentAction {
|
|
|
13
13
|
/**
|
|
14
14
|
* Log an intent.
|
|
15
15
|
*/
|
|
16
|
-
export class Track extends
|
|
17
|
-
input:
|
|
18
|
-
intents:
|
|
19
|
-
error:
|
|
16
|
+
export class Track extends Schema.TaggedClass<Track>()(`${INTENT_ACTION}/track`, {
|
|
17
|
+
input: Schema.Struct({
|
|
18
|
+
intents: Schema.Array(Schema.String),
|
|
19
|
+
error: Schema.optional(Schema.String),
|
|
20
20
|
}),
|
|
21
|
-
output:
|
|
21
|
+
output: Schema.Void,
|
|
22
22
|
}) {}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Fired after an intent is dispatched if the intent is undoable.
|
|
26
26
|
*/
|
|
27
|
-
export class ShowUndo extends
|
|
28
|
-
input:
|
|
27
|
+
export class ShowUndo extends Schema.TaggedClass<ShowUndo>()(`${INTENT_ACTION}/show-undo`, {
|
|
28
|
+
input: Schema.Struct({
|
|
29
29
|
message: Label,
|
|
30
30
|
}),
|
|
31
|
-
output:
|
|
31
|
+
output: Schema.Void,
|
|
32
32
|
}) {}
|
|
33
33
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Schema
|
|
5
|
+
import { Schema, Effect, Fiber, pipe } from 'effect';
|
|
6
6
|
import { describe, expect, test } from 'vitest';
|
|
7
7
|
|
|
8
8
|
import { chain, createIntent } from './intent';
|
|
@@ -134,25 +134,6 @@ describe('Intent dispatcher', () => {
|
|
|
134
134
|
await Effect.runPromise(program);
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
test('filter resolvers by plugin', async () => {
|
|
138
|
-
const otherComputeResolver = createResolver({
|
|
139
|
-
intent: Compute,
|
|
140
|
-
resolve: async (data) => ({ data: { value: data?.value * 3 } }),
|
|
141
|
-
});
|
|
142
|
-
const { dispatch } = createDispatcher((module) => (module === 'test' ? [computeResolver] : [otherComputeResolver]));
|
|
143
|
-
const program = Effect.gen(function* () {
|
|
144
|
-
const a = yield* dispatch(createIntent(Compute, { value: 1 }));
|
|
145
|
-
|
|
146
|
-
expect(a.value).toBe(3);
|
|
147
|
-
|
|
148
|
-
const b = yield* dispatch(createIntent(Compute, { value: 1 }, { module: 'test' }));
|
|
149
|
-
|
|
150
|
-
expect(b.value).toBe(2);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
await Effect.runPromise(program);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
137
|
test('filter resolvers by predicate', async () => {
|
|
157
138
|
const conditionalComputeResolver = createResolver({
|
|
158
139
|
intent: Compute,
|
|
@@ -224,12 +205,12 @@ describe('Intent dispatcher', () => {
|
|
|
224
205
|
test.todo('follow up intents');
|
|
225
206
|
});
|
|
226
207
|
|
|
227
|
-
class ToString extends
|
|
228
|
-
input:
|
|
229
|
-
value:
|
|
208
|
+
class ToString extends Schema.TaggedClass<ToString>()('ToString', {
|
|
209
|
+
input: Schema.Struct({
|
|
210
|
+
value: Schema.Number,
|
|
230
211
|
}),
|
|
231
|
-
output:
|
|
232
|
-
string:
|
|
212
|
+
output: Schema.Struct({
|
|
213
|
+
string: Schema.String,
|
|
233
214
|
}),
|
|
234
215
|
}) {}
|
|
235
216
|
|
|
@@ -238,12 +219,12 @@ const toStringResolver = createResolver({
|
|
|
238
219
|
resolve: async (data) => ({ data: { string: data.value.toString() } }),
|
|
239
220
|
});
|
|
240
221
|
|
|
241
|
-
class Compute extends
|
|
242
|
-
input:
|
|
243
|
-
value:
|
|
222
|
+
class Compute extends Schema.TaggedClass<Compute>()('Compute', {
|
|
223
|
+
input: Schema.Struct({
|
|
224
|
+
value: Schema.Number,
|
|
244
225
|
}),
|
|
245
|
-
output:
|
|
246
|
-
value:
|
|
226
|
+
output: Schema.Struct({
|
|
227
|
+
value: Schema.Number,
|
|
247
228
|
}),
|
|
248
229
|
}) {}
|
|
249
230
|
|
|
@@ -262,13 +243,13 @@ const computeResolver = createResolver({
|
|
|
262
243
|
},
|
|
263
244
|
});
|
|
264
245
|
|
|
265
|
-
class Concat extends
|
|
266
|
-
input:
|
|
267
|
-
string:
|
|
268
|
-
plus:
|
|
246
|
+
class Concat extends Schema.TaggedClass<Concat>()('Concat', {
|
|
247
|
+
input: Schema.Struct({
|
|
248
|
+
string: Schema.String,
|
|
249
|
+
plus: Schema.String,
|
|
269
250
|
}),
|
|
270
|
-
output:
|
|
271
|
-
string:
|
|
251
|
+
output: Schema.Struct({
|
|
252
|
+
string: Schema.String,
|
|
272
253
|
}),
|
|
273
254
|
}) {}
|
|
274
255
|
|
|
@@ -277,9 +258,9 @@ const concatResolver = createResolver({
|
|
|
277
258
|
resolve: async (data) => ({ data: { string: data.string + data.plus } }),
|
|
278
259
|
});
|
|
279
260
|
|
|
280
|
-
class Add extends
|
|
281
|
-
input:
|
|
282
|
-
output:
|
|
261
|
+
class Add extends Schema.TaggedClass<Add>()('Add', {
|
|
262
|
+
input: Schema.Tuple(Schema.Number, Schema.Number),
|
|
263
|
+
output: Schema.Number,
|
|
283
264
|
}) {}
|
|
284
265
|
|
|
285
266
|
const addResolver = createResolver({
|
|
@@ -287,9 +268,9 @@ const addResolver = createResolver({
|
|
|
287
268
|
resolve: async (data) => ({ data: data[0] + data[1] }),
|
|
288
269
|
});
|
|
289
270
|
|
|
290
|
-
class SideEffect extends
|
|
291
|
-
input:
|
|
292
|
-
output:
|
|
271
|
+
class SideEffect extends Schema.TaggedClass<SideEffect>()('SideEffect', {
|
|
272
|
+
input: Schema.Void,
|
|
273
|
+
output: Schema.Void,
|
|
293
274
|
}) {}
|
|
294
275
|
|
|
295
276
|
const sideEffectResolver = createResolver({
|