@dxos/app-framework 0.8.2-main.f11618f → 0.8.2-staging.42af850
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-DYEAGZPS.mjs} +23 -23
- package/dist/lib/browser/app-graph-builder-DYEAGZPS.mjs.map +7 -0
- package/dist/lib/browser/{chunk-DVNSCQJ5.mjs → chunk-5GE2ERNU.mjs} +314 -280
- 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-X2YC645Z.mjs → chunk-ZMXJV64L.mjs} +122 -62
- package/dist/lib/browser/chunk-ZMXJV64L.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +10 -10
- package/dist/lib/browser/{intent-dispatcher-J7QIFHLO.mjs → intent-dispatcher-ELZN5EM7.mjs} +2 -2
- package/dist/lib/browser/{intent-resolver-QV5MDMDV.mjs → intent-resolver-SGWLINTO.mjs} +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{store-XMPVLJOQ.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 +3 -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-I3CJYEBC.cjs → chunk-HIVITTZD.cjs} +156 -122
- package/dist/lib/node/chunk-HIVITTZD.cjs.map +7 -0
- package/dist/lib/node/{chunk-5UOVF3OR.cjs → chunk-Z2PMVDJ5.cjs} +155 -95
- package/dist/lib/node/chunk-Z2PMVDJ5.cjs.map +7 -0
- package/dist/lib/node/index.cjs +81 -81
- package/dist/lib/node/{intent-dispatcher-FQPJNKIZ.cjs → intent-dispatcher-LFXZJTAS.cjs} +8 -8
- package/dist/lib/node/{intent-dispatcher-FQPJNKIZ.cjs.map → intent-dispatcher-LFXZJTAS.cjs.map} +2 -2
- package/dist/lib/node/{intent-resolver-PBAOGJS6.cjs → intent-resolver-EPSFTHL6.cjs} +12 -12
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{store-N7JLYYDI.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 +39 -39
- package/dist/lib/node/worker.cjs.map +1 -1
- package/dist/lib/node-esm/{app-graph-builder-OMH534A4.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-QHXUTJHE.mjs → chunk-6IKYKERU.mjs} +122 -62
- 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-GSDBF2CK.mjs → chunk-Z2ZHH4HN.mjs} +314 -280
- package/dist/lib/node-esm/chunk-Z2ZHH4HN.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +10 -10
- package/dist/lib/node-esm/{intent-dispatcher-QDUGA7NT.mjs → intent-dispatcher-A2JCMWRD.mjs} +2 -2
- package/dist/lib/node-esm/{intent-resolver-P7TC5RBD.mjs → intent-resolver-5C4O43GK.mjs} +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{store-M2BYJL6K.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 +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 +40 -222
- package/dist/types/src/common/capabilities.d.ts.map +1 -1
- package/dist/types/src/common/collaboration.d.ts +8 -8
- 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 +165 -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/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 +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/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 +28 -21
- package/src/App.tsx +97 -47
- package/src/common/capabilities.ts +18 -7
- package/src/common/collaboration.ts +9 -9
- package/src/common/file.ts +7 -7
- package/src/common/layout.ts +156 -136
- package/src/common/translations.ts +7 -7
- package/src/core/capabilities.test.ts +55 -36
- package/src/core/capabilities.ts +79 -59
- package/src/core/manager.test.ts +19 -19
- package/src/core/manager.ts +24 -16
- 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 +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 +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/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/assets/navigation.js +1 -1
- package/typedoc/assets/search.js +1 -1
- package/typedoc/classes/CollaborationActions.InsertContent.html +280 -280
- 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 +865 -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/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/{createApp.html → useApp.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.AnchorSort.html +1 -0
- 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-ELZN5EM7.mjs.map} +0 -0
- /package/dist/lib/browser/{intent-resolver-QV5MDMDV.mjs.map → intent-resolver-SGWLINTO.mjs.map} +0 -0
- /package/dist/lib/node/{intent-resolver-PBAOGJS6.cjs.map → intent-resolver-EPSFTHL6.cjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-dispatcher-QDUGA7NT.mjs.map → intent-dispatcher-A2JCMWRD.mjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-resolver-P7TC5RBD.mjs.map → intent-resolver-5C4O43GK.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
|
}
|
|
@@ -134,94 +150,98 @@ export class PluginsContext {
|
|
|
134
150
|
module: string;
|
|
135
151
|
interface: InterfaceDef<T>;
|
|
136
152
|
implementation: T;
|
|
137
|
-
}) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
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;
|
|
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
|
|
|
153
168
|
/**
|
|
154
169
|
* @internal
|
|
155
170
|
*/
|
|
156
|
-
removeCapability<T>(interfaceDef: InterfaceDef<T>, implementation: T) {
|
|
157
|
-
const current = this.
|
|
158
|
-
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) {
|
|
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,
|
|
@@ -257,7 +265,7 @@ export class PluginManager {
|
|
|
257
265
|
return untracked(() => Effect.runPromise(this._reset(event)));
|
|
258
266
|
}
|
|
259
267
|
|
|
260
|
-
private _addPlugin(plugin: Plugin) {
|
|
268
|
+
private _addPlugin(plugin: Plugin): void {
|
|
261
269
|
untracked(() => {
|
|
262
270
|
log('add plugin', { id: plugin.meta.id });
|
|
263
271
|
if (!this._state.plugins.includes(plugin)) {
|
|
@@ -266,7 +274,7 @@ export class PluginManager {
|
|
|
266
274
|
});
|
|
267
275
|
}
|
|
268
276
|
|
|
269
|
-
private _removePlugin(id: string) {
|
|
277
|
+
private _removePlugin(id: string): void {
|
|
270
278
|
untracked(() => {
|
|
271
279
|
log('remove plugin', { id });
|
|
272
280
|
const pluginIndex = this._state.plugins.findIndex((plugin) => plugin.meta.id === id);
|
|
@@ -276,7 +284,7 @@ export class PluginManager {
|
|
|
276
284
|
});
|
|
277
285
|
}
|
|
278
286
|
|
|
279
|
-
private _addModule(module: PluginModule) {
|
|
287
|
+
private _addModule(module: PluginModule): void {
|
|
280
288
|
untracked(() => {
|
|
281
289
|
log('add module', { id: module.id });
|
|
282
290
|
if (!this._state.modules.includes(module)) {
|
|
@@ -285,7 +293,7 @@ export class PluginManager {
|
|
|
285
293
|
});
|
|
286
294
|
}
|
|
287
295
|
|
|
288
|
-
private _removeModule(id: string) {
|
|
296
|
+
private _removeModule(id: string): void {
|
|
289
297
|
untracked(() => {
|
|
290
298
|
log('remove module', { id });
|
|
291
299
|
const moduleIndex = this._state.modules.findIndex((module) => module.id === id);
|
|
@@ -295,27 +303,27 @@ export class PluginManager {
|
|
|
295
303
|
});
|
|
296
304
|
}
|
|
297
305
|
|
|
298
|
-
private _getPlugin(id: string) {
|
|
306
|
+
private _getPlugin(id: string): Plugin | undefined {
|
|
299
307
|
return this._state.plugins.find((plugin) => plugin.meta.id === id);
|
|
300
308
|
}
|
|
301
309
|
|
|
302
|
-
private _getActiveModules() {
|
|
310
|
+
private _getActiveModules(): PluginModule[] {
|
|
303
311
|
return this._state.modules.filter((module) => this._state.active.includes(module.id));
|
|
304
312
|
}
|
|
305
313
|
|
|
306
|
-
private _getInactiveModules() {
|
|
314
|
+
private _getInactiveModules(): PluginModule[] {
|
|
307
315
|
return this._state.modules.filter((module) => !this._state.active.includes(module.id));
|
|
308
316
|
}
|
|
309
317
|
|
|
310
|
-
private _getActiveModulesByEvent(key: string) {
|
|
318
|
+
private _getActiveModulesByEvent(key: string): PluginModule[] {
|
|
311
319
|
return this._getActiveModules().filter((module) => getEvents(module.activatesOn).map(eventKey).includes(key));
|
|
312
320
|
}
|
|
313
321
|
|
|
314
|
-
private _getInactiveModulesByEvent(key: string) {
|
|
322
|
+
private _getInactiveModulesByEvent(key: string): PluginModule[] {
|
|
315
323
|
return this._getInactiveModules().filter((module) => getEvents(module.activatesOn).map(eventKey).includes(key));
|
|
316
324
|
}
|
|
317
325
|
|
|
318
|
-
private _setPendingResetByModule(module: PluginModule) {
|
|
326
|
+
private _setPendingResetByModule(module: PluginModule): void {
|
|
319
327
|
return untracked(() => {
|
|
320
328
|
const activationEvents = getEvents(module.activatesOn)
|
|
321
329
|
.map(eventKey)
|
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
|
}) {}
|
|
@@ -12,7 +12,7 @@ import { DebugPlugin } from './debug';
|
|
|
12
12
|
import { createNumberPlugin, GeneratorPlugin } from './generator';
|
|
13
13
|
import { LayoutPlugin } from './layout';
|
|
14
14
|
import { LoggerPlugin } from './logger';
|
|
15
|
-
import {
|
|
15
|
+
import { useApp } from '../App';
|
|
16
16
|
import { IntentPlugin } from '../plugin-intent';
|
|
17
17
|
|
|
18
18
|
const plugins = [IntentPlugin(), LayoutPlugin(), DebugPlugin(), LoggerPlugin(), GeneratorPlugin()];
|
|
@@ -21,18 +21,22 @@ const Placeholder = () => {
|
|
|
21
21
|
return <div>Loading...</div>;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
const Story =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
const Story = () => {
|
|
25
|
+
const App = useApp({
|
|
26
|
+
pluginLoader: (id) => createNumberPlugin(id),
|
|
27
|
+
plugins,
|
|
28
|
+
core: plugins.map((plugin) => plugin.meta.id),
|
|
29
|
+
// Having a non-empty placeholder makes it clear if it's taking a while to load.
|
|
30
|
+
placeholder: Placeholder,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return <App />;
|
|
34
|
+
};
|
|
31
35
|
|
|
32
36
|
export const Playground = {};
|
|
33
37
|
|
|
34
38
|
export default {
|
|
35
39
|
title: 'sdk/app-framework/playground',
|
|
36
40
|
render: Story,
|
|
37
|
-
decorators: [withTheme, withLayout(
|
|
41
|
+
decorators: [withTheme, withLayout()],
|
|
38
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 { 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
|
}
|