@dxos/app-framework 0.7.5-labs.e27f9b9 → 0.7.5-main.2567c87

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.
Files changed (184) hide show
  1. package/dist/lib/browser/{chunk-G3HBVVT5.mjs → chunk-GNLU3GAU.mjs} +819 -627
  2. package/dist/lib/browser/chunk-GNLU3GAU.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +74 -57
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +3 -10
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/chunk-FBA4BB3J.cjs +1639 -0
  9. package/dist/lib/node/chunk-FBA4BB3J.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +118 -106
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +8 -15
  14. package/dist/lib/node/testing/index.cjs.map +3 -3
  15. package/dist/lib/node-esm/{chunk-ZTB4TA6Q.mjs → chunk-KPMTPXQI.mjs} +819 -627
  16. package/dist/lib/node-esm/chunk-KPMTPXQI.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +74 -57
  18. package/dist/lib/node-esm/index.mjs.map +4 -4
  19. package/dist/lib/node-esm/meta.json +1 -1
  20. package/dist/lib/node-esm/testing/index.mjs +3 -10
  21. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  22. package/dist/types/src/App.d.ts.map +1 -1
  23. package/dist/types/src/common/capabilities.d.ts +110 -66
  24. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  25. package/dist/types/src/common/events.d.ts +1 -8
  26. package/dist/types/src/common/events.d.ts.map +1 -1
  27. package/dist/types/src/common/file.d.ts +1 -1
  28. package/dist/types/src/common/file.d.ts.map +1 -1
  29. package/dist/types/src/common/graph.d.ts +2 -2
  30. package/dist/types/src/common/graph.d.ts.map +1 -1
  31. package/dist/types/src/common/index.d.ts +1 -0
  32. package/dist/types/src/common/index.d.ts.map +1 -1
  33. package/dist/types/src/common/layout.d.ts +121 -204
  34. package/dist/types/src/common/layout.d.ts.map +1 -1
  35. package/dist/types/src/common/navigation.d.ts +241 -0
  36. package/dist/types/src/common/navigation.d.ts.map +1 -0
  37. package/dist/types/src/common/surface.d.ts +3 -3
  38. package/dist/types/src/common/surface.d.ts.map +1 -1
  39. package/dist/types/src/common/translations.d.ts +7 -7
  40. package/dist/types/src/common/translations.d.ts.map +1 -1
  41. package/dist/types/src/core/capabilities.d.ts +2 -6
  42. package/dist/types/src/core/capabilities.d.ts.map +1 -1
  43. package/dist/types/src/core/manager.d.ts +9 -2
  44. package/dist/types/src/core/manager.d.ts.map +1 -1
  45. package/dist/types/src/core/plugin.d.ts +2 -5
  46. package/dist/types/src/core/plugin.d.ts.map +1 -1
  47. package/dist/types/src/playground/generator/Toolbar.d.ts.map +1 -1
  48. package/dist/types/src/playground/generator/generator.d.ts +0 -2
  49. package/dist/types/src/playground/generator/generator.d.ts.map +1 -1
  50. package/dist/types/src/playground/generator/plugin.d.ts.map +1 -1
  51. package/dist/types/src/playground/logger/Toolbar.d.ts.map +1 -1
  52. package/dist/types/src/playground/logger/plugin.d.ts.map +1 -1
  53. package/dist/types/src/playground/logger/schema.d.ts +1 -1
  54. package/dist/types/src/playground/logger/schema.d.ts.map +1 -1
  55. package/dist/types/src/{react → plugin-intent}/IntentContext.d.ts +1 -1
  56. package/dist/types/src/plugin-intent/IntentContext.d.ts.map +1 -0
  57. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +1 -1
  58. package/dist/types/src/plugin-intent/actions.d.ts +1 -1
  59. package/dist/types/src/plugin-intent/actions.d.ts.map +1 -1
  60. package/dist/types/src/plugin-intent/index.d.ts +1 -0
  61. package/dist/types/src/plugin-intent/index.d.ts.map +1 -1
  62. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +20 -27
  63. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +1 -1
  64. package/dist/types/src/plugin-intent/intent.d.ts +3 -3
  65. package/dist/types/src/plugin-intent/intent.d.ts.map +1 -1
  66. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +1 -1
  67. package/dist/types/src/plugin-settings/actions.d.ts +1 -11
  68. package/dist/types/src/plugin-settings/actions.d.ts.map +1 -1
  69. package/dist/types/src/react/Surface.d.ts.map +1 -1
  70. package/dist/types/src/react/index.d.ts +0 -2
  71. package/dist/types/src/react/index.d.ts.map +1 -1
  72. package/dist/types/src/react/useCapabilities.d.ts.map +1 -1
  73. package/dist/types/src/testing/withPluginManager.d.ts +1 -1
  74. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  75. package/package.json +21 -28
  76. package/project.json +3 -3
  77. package/src/App.tsx +14 -15
  78. package/src/common/capabilities.ts +11 -26
  79. package/src/common/events.ts +1 -10
  80. package/src/common/file.ts +1 -1
  81. package/src/common/graph.ts +2 -2
  82. package/src/common/index.ts +1 -0
  83. package/src/common/layout.ts +126 -194
  84. package/src/common/navigation.ts +199 -0
  85. package/src/common/surface.ts +2 -2
  86. package/src/common/translations.ts +8 -7
  87. package/src/core/capabilities.ts +7 -16
  88. package/src/core/manager.test.ts +73 -22
  89. package/src/core/manager.ts +91 -105
  90. package/src/core/plugin.ts +3 -6
  91. package/src/playground/debug/plugin.ts +1 -1
  92. package/src/playground/generator/Toolbar.tsx +11 -11
  93. package/src/playground/generator/generator.ts +0 -25
  94. package/src/playground/generator/plugin.ts +1 -6
  95. package/src/playground/layout/plugin.ts +1 -1
  96. package/src/playground/logger/Toolbar.tsx +1 -2
  97. package/src/playground/logger/plugin.ts +3 -6
  98. package/src/playground/logger/schema.ts +1 -1
  99. package/src/{react → plugin-intent}/IntentContext.tsx +2 -2
  100. package/src/plugin-intent/IntentPlugin.tsx +43 -3
  101. package/src/plugin-intent/actions.ts +1 -1
  102. package/src/plugin-intent/errors.ts +1 -1
  103. package/src/plugin-intent/index.ts +1 -0
  104. package/src/plugin-intent/intent-dispatcher.test.ts +29 -48
  105. package/src/plugin-intent/intent-dispatcher.ts +41 -76
  106. package/src/plugin-intent/intent.ts +5 -5
  107. package/src/plugin-settings/SettingsPlugin.ts +13 -19
  108. package/src/plugin-settings/actions.ts +1 -11
  109. package/src/react/Surface.tsx +8 -11
  110. package/src/react/index.ts +0 -2
  111. package/src/react/useCapabilities.ts +0 -1
  112. package/src/testing/withPluginManager.tsx +3 -11
  113. package/tsconfig.json +3 -6
  114. package/dist/lib/browser/app-graph-builder-MOLT4EHG.mjs +0 -137
  115. package/dist/lib/browser/app-graph-builder-MOLT4EHG.mjs.map +0 -7
  116. package/dist/lib/browser/chunk-G3HBVVT5.mjs.map +0 -7
  117. package/dist/lib/browser/chunk-LDJ3T4V3.mjs +0 -32
  118. package/dist/lib/browser/chunk-LDJ3T4V3.mjs.map +0 -7
  119. package/dist/lib/browser/chunk-TGOF2WQZ.mjs +0 -285
  120. package/dist/lib/browser/chunk-TGOF2WQZ.mjs.map +0 -7
  121. package/dist/lib/browser/intent-dispatcher-LJKNIGAM.mjs +0 -11
  122. package/dist/lib/browser/intent-dispatcher-LJKNIGAM.mjs.map +0 -7
  123. package/dist/lib/browser/intent-resolver-Z724VAMC.mjs +0 -38
  124. package/dist/lib/browser/intent-resolver-Z724VAMC.mjs.map +0 -7
  125. package/dist/lib/browser/store-NWCY7LAP.mjs +0 -19
  126. package/dist/lib/browser/store-NWCY7LAP.mjs.map +0 -7
  127. package/dist/lib/browser/worker.mjs +0 -77
  128. package/dist/lib/browser/worker.mjs.map +0 -7
  129. package/dist/lib/node/app-graph-builder-G7SRXDFD.cjs +0 -146
  130. package/dist/lib/node/app-graph-builder-G7SRXDFD.cjs.map +0 -7
  131. package/dist/lib/node/chunk-55KIQ6YK.cjs +0 -1437
  132. package/dist/lib/node/chunk-55KIQ6YK.cjs.map +0 -7
  133. package/dist/lib/node/chunk-5GABBW2Q.cjs +0 -308
  134. package/dist/lib/node/chunk-5GABBW2Q.cjs.map +0 -7
  135. package/dist/lib/node/chunk-QLVQ6PND.cjs +0 -58
  136. package/dist/lib/node/chunk-QLVQ6PND.cjs.map +0 -7
  137. package/dist/lib/node/intent-dispatcher-CGUK3BCJ.cjs +0 -32
  138. package/dist/lib/node/intent-dispatcher-CGUK3BCJ.cjs.map +0 -7
  139. package/dist/lib/node/intent-resolver-7GNKPRWT.cjs +0 -45
  140. package/dist/lib/node/intent-resolver-7GNKPRWT.cjs.map +0 -7
  141. package/dist/lib/node/store-WMJSEQPC.cjs +0 -34
  142. package/dist/lib/node/store-WMJSEQPC.cjs.map +0 -7
  143. package/dist/lib/node/worker.cjs +0 -99
  144. package/dist/lib/node/worker.cjs.map +0 -7
  145. package/dist/lib/node-esm/app-graph-builder-MKLYH3NE.mjs +0 -138
  146. package/dist/lib/node-esm/app-graph-builder-MKLYH3NE.mjs.map +0 -7
  147. package/dist/lib/node-esm/chunk-47FG42II.mjs +0 -286
  148. package/dist/lib/node-esm/chunk-47FG42II.mjs.map +0 -7
  149. package/dist/lib/node-esm/chunk-CNJYZNSL.mjs +0 -34
  150. package/dist/lib/node-esm/chunk-CNJYZNSL.mjs.map +0 -7
  151. package/dist/lib/node-esm/chunk-ZTB4TA6Q.mjs.map +0 -7
  152. package/dist/lib/node-esm/intent-dispatcher-RZAWA4XD.mjs +0 -12
  153. package/dist/lib/node-esm/intent-dispatcher-RZAWA4XD.mjs.map +0 -7
  154. package/dist/lib/node-esm/intent-resolver-UIU37CKJ.mjs +0 -39
  155. package/dist/lib/node-esm/intent-resolver-UIU37CKJ.mjs.map +0 -7
  156. package/dist/lib/node-esm/store-YUWINFBN.mjs +0 -20
  157. package/dist/lib/node-esm/store-YUWINFBN.mjs.map +0 -7
  158. package/dist/lib/node-esm/worker.mjs +0 -78
  159. package/dist/lib/node-esm/worker.mjs.map +0 -7
  160. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -197
  161. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  162. package/dist/types/src/plugin-settings/intent-resolver.d.ts +0 -4
  163. package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +0 -1
  164. package/dist/types/src/plugin-settings/store.d.ts +0 -5
  165. package/dist/types/src/plugin-settings/store.d.ts.map +0 -1
  166. package/dist/types/src/plugin-settings/translations.d.ts +0 -11
  167. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  168. package/dist/types/src/react/IntentContext.d.ts.map +0 -1
  169. package/dist/types/src/react/Surface.stories.d.ts +0 -16
  170. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  171. package/dist/types/src/react/common.d.ts +0 -12
  172. package/dist/types/src/react/common.d.ts.map +0 -1
  173. package/dist/types/src/react/useIntentResolver.d.ts +0 -3
  174. package/dist/types/src/react/useIntentResolver.d.ts.map +0 -1
  175. package/dist/types/src/worker.d.ts +0 -4
  176. package/dist/types/src/worker.d.ts.map +0 -1
  177. package/src/plugin-settings/app-graph-builder.ts +0 -122
  178. package/src/plugin-settings/intent-resolver.ts +0 -28
  179. package/src/plugin-settings/store.ts +0 -20
  180. package/src/plugin-settings/translations.ts +0 -17
  181. package/src/react/Surface.stories.tsx +0 -96
  182. package/src/react/common.ts +0 -12
  183. package/src/react/useIntentResolver.ts +0 -22
  184. package/src/worker.ts +0 -11
@@ -2,10 +2,11 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema as S } from '@effect/schema';
6
5
  import { Effect, Fiber, pipe } from 'effect';
7
6
  import { describe, expect, test } from 'vitest';
8
7
 
8
+ import { S } from '@dxos/echo-schema';
9
+
9
10
  import { chain, createIntent } from './intent';
10
11
  import { type AnyIntentResolver, createDispatcher, createResolver } from './intent-dispatcher';
11
12
 
@@ -107,8 +108,8 @@ describe('Intent dispatcher', () => {
107
108
  const { dispatch } = createDispatcher(() => [computeResolver, toStringResolver, concatResolver]);
108
109
  const intent = pipe(createIntent(Compute, { value: 1 }), chain(ToString, {}), chain(Concat, { plus: '!' }));
109
110
 
110
- expect(intent.first.id).toBe(Compute._tag);
111
- expect(intent.last.id).toBe(Concat._tag);
111
+ expect(intent.first.action).toBe(Compute._tag);
112
+ expect(intent.last.action).toBe(Concat._tag);
112
113
  expect(intent.all.length).toBe(3);
113
114
 
114
115
  const program = Effect.gen(function* () {
@@ -136,10 +137,7 @@ describe('Intent dispatcher', () => {
136
137
  });
137
138
 
138
139
  test('filter resolvers by plugin', async () => {
139
- const otherComputeResolver = createResolver({
140
- intent: Compute,
141
- resolve: async (data) => ({ data: { value: data?.value * 3 } }),
142
- });
140
+ const otherComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 3 } }));
143
141
  const { dispatch } = createDispatcher((module) => (module === 'test' ? [computeResolver] : [otherComputeResolver]));
144
142
  const program = Effect.gen(function* () {
145
143
  const a = yield* dispatch(createIntent(Compute, { value: 1 }));
@@ -155,10 +153,8 @@ describe('Intent dispatcher', () => {
155
153
  });
156
154
 
157
155
  test('filter resolvers by predicate', async () => {
158
- const conditionalComputeResolver = createResolver({
159
- intent: Compute,
156
+ const conditionalComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 3 } }), {
160
157
  filter: (data): data is { value: number } => data?.value > 1,
161
- resolve: async (data) => ({ data: { value: data?.value * 3 } }),
162
158
  });
163
159
  const { dispatch } = createDispatcher(() => [conditionalComputeResolver, computeResolver]);
164
160
  const program = Effect.gen(function* () {
@@ -175,10 +171,8 @@ describe('Intent dispatcher', () => {
175
171
  });
176
172
 
177
173
  test('hoist resolvers', async () => {
178
- const hoistedComputeResolver = createResolver({
179
- intent: Compute,
180
- position: 'hoist',
181
- resolve: async (data) => ({ data: { value: data?.value * 3 } }),
174
+ const hoistedComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 3 } }), {
175
+ disposition: 'hoist',
182
176
  });
183
177
  const { dispatchPromise } = createDispatcher(() => [computeResolver, hoistedComputeResolver]);
184
178
  const { data } = await dispatchPromise(createIntent(Compute, { value: 1 }));
@@ -186,17 +180,13 @@ describe('Intent dispatcher', () => {
186
180
  });
187
181
 
188
182
  test('fallback resolvers', async () => {
189
- const conditionalComputeResolver = createResolver({
190
- intent: Compute,
183
+ const conditionalComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 2 } }), {
191
184
  filter: (data): data is { value: number } => data?.value === 1,
192
- resolve: async (data) => ({ data: { value: data?.value * 2 } }),
193
185
  });
194
- const fallbackComputeResolver = createResolver({
195
- intent: Compute,
196
- position: 'fallback',
197
- resolve: async (data) => ({ data: { value: data?.value * 3 } }),
186
+ const fallbackComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 3 } }), {
187
+ disposition: 'fallback',
198
188
  });
199
- const { dispatch } = createDispatcher(() => [conditionalComputeResolver, fallbackComputeResolver]);
189
+ const { dispatch } = createDispatcher(() => [fallbackComputeResolver, conditionalComputeResolver]);
200
190
  const program = Effect.gen(function* () {
201
191
  const a = yield* dispatch(createIntent(Compute, { value: 1 }));
202
192
 
@@ -234,9 +224,8 @@ class ToString extends S.TaggedClass<ToString>()('ToString', {
234
224
  }),
235
225
  }) {}
236
226
 
237
- const toStringResolver = createResolver({
238
- intent: ToString,
239
- resolve: async (data) => ({ data: { string: data.value.toString() } }),
227
+ const toStringResolver = createResolver(ToString, async (data) => {
228
+ return { data: { string: data.value.toString() } };
240
229
  });
241
230
 
242
231
  class Compute extends S.TaggedClass<Compute>()('Compute', {
@@ -248,19 +237,16 @@ class Compute extends S.TaggedClass<Compute>()('Compute', {
248
237
  }),
249
238
  }) {}
250
239
 
251
- const computeResolver = createResolver({
252
- intent: Compute,
253
- resolve: (data, undo) => {
254
- return Effect.gen(function* () {
255
- if (undo) {
256
- return { data: { value: data.value / 2 } };
257
- }
258
-
259
- yield* Effect.sleep(data.value * 10);
260
- const value = data.value * 2;
261
- return { data: { value }, undoable: { message: 'test', data: { value } } };
262
- });
263
- },
240
+ const computeResolver = createResolver(Compute, (data, undo) => {
241
+ return Effect.gen(function* () {
242
+ if (undo) {
243
+ return { data: { value: data.value / 2 } };
244
+ }
245
+
246
+ yield* Effect.sleep(data.value * 10);
247
+ const value = data.value * 2;
248
+ return { data: { value }, undoable: { message: 'test', data: { value } } };
249
+ });
264
250
  });
265
251
 
266
252
  class Concat extends S.TaggedClass<Concat>()('Concat', {
@@ -273,9 +259,8 @@ class Concat extends S.TaggedClass<Concat>()('Concat', {
273
259
  }),
274
260
  }) {}
275
261
 
276
- const concatResolver = createResolver({
277
- intent: Concat,
278
- resolve: async (data) => ({ data: { string: data.string + data.plus } }),
262
+ const concatResolver = createResolver(Concat, async (data) => {
263
+ return { data: { string: data.string + data.plus } };
279
264
  });
280
265
 
281
266
  class Add extends S.TaggedClass<Add>()('Add', {
@@ -283,9 +268,8 @@ class Add extends S.TaggedClass<Add>()('Add', {
283
268
  output: S.Number,
284
269
  }) {}
285
270
 
286
- const addResolver = createResolver({
287
- intent: Add,
288
- resolve: async (data) => ({ data: data[0] + data[1] }),
271
+ const addResolver = createResolver(Add, async (data) => {
272
+ return { data: data[0] + data[1] };
289
273
  });
290
274
 
291
275
  class SideEffect extends S.TaggedClass<SideEffect>()('SideEffect', {
@@ -293,7 +277,4 @@ class SideEffect extends S.TaggedClass<SideEffect>()('SideEffect', {
293
277
  output: S.Void,
294
278
  }) {}
295
279
 
296
- const sideEffectResolver = createResolver({
297
- intent: SideEffect,
298
- resolve: async () => {},
299
- });
280
+ const sideEffectResolver = createResolver(SideEffect, async () => {});
@@ -5,8 +5,7 @@
5
5
  import { Effect, Option, pipe, Ref } from 'effect';
6
6
  import { type Simplify } from 'effect/Types';
7
7
 
8
- import { create } from '@dxos/live-object';
9
- import { byPosition, type MaybePromise, type Position, type GuardedType } from '@dxos/util';
8
+ import { type MaybePromise, byDisposition, type Disposition } from '@dxos/util';
10
9
 
11
10
  import { IntentAction } from './actions';
12
11
  import { CycleDetectedError, NoResolversError } from './errors';
@@ -22,8 +21,6 @@ import {
22
21
  type IntentSchema,
23
22
  type Label,
24
23
  } from './intent';
25
- import { Events, Capabilities } from '../common';
26
- import { contributes, type PluginsContext } from '../core';
27
24
 
28
25
  const EXECUTION_LIMIT = 100;
29
26
  const HISTORY_LIMIT = 100;
@@ -31,13 +28,13 @@ const HISTORY_LIMIT = 100;
31
28
  /**
32
29
  * The return value of an intent effect.
33
30
  */
34
- export type IntentEffectResult<Input, Output> = {
31
+ export type IntentEffectResult<Fields extends IntentParams> = {
35
32
  /**
36
33
  * The output of the action that was performed.
37
34
  *
38
35
  * If the intent is apart of a chain of intents, the data will be passed to the next intent.
39
36
  */
40
- data?: Output;
37
+ data?: IntentResultData<Fields>;
41
38
 
42
39
  /**
43
40
  * If provided, the action will be undoable.
@@ -51,7 +48,7 @@ export type IntentEffectResult<Input, Output> = {
51
48
  /**
52
49
  * Will be merged with the original intent data when firing the undo intent.
53
50
  */
54
- data?: Partial<Input>;
51
+ data?: Partial<IntentData<Fields>>;
55
52
  };
56
53
 
57
54
  /**
@@ -69,32 +66,33 @@ export type IntentEffectResult<Input, Output> = {
69
66
  intents?: AnyIntentChain[];
70
67
  };
71
68
 
72
- export type AnyIntentEffectResult = IntentEffectResult<any, any>;
69
+ export type AnyIntentEffectResult = IntentEffectResult<any>;
73
70
 
74
71
  /**
75
72
  * The result of an intent dispatcher.
76
73
  */
77
- export type IntentDispatcherResult<Input, Output> = Pick<IntentEffectResult<Input, Output>, 'data' | 'error'>;
74
+ export type IntentDispatcherResult<Fields extends IntentParams> = Pick<IntentEffectResult<Fields>, 'data' | 'error'>;
78
75
 
79
76
  /**
80
77
  * The implementation of an intent effect.
81
78
  */
82
- export type IntentEffectDefinition<Input, Output> = (
83
- data: Input,
79
+ export type IntentEffectDefinition<Fields extends IntentParams> = (
80
+ data: IntentData<Fields>,
84
81
  undo: boolean,
85
- ) => MaybePromise<IntentEffectResult<Input, Output> | void> | Effect.Effect<IntentEffectResult<Input, Output> | void>;
82
+ ) => MaybePromise<IntentEffectResult<Fields> | void> | Effect.Effect<IntentEffectResult<Fields> | void>;
86
83
 
87
84
  /**
88
85
  * Intent resolver to match intents to their effects.
89
86
  */
90
- export type IntentResolver<Tag extends string, Fields extends IntentParams, Data = IntentData<Fields>> = Readonly<{
91
- intent: IntentSchema<Tag, Fields>;
92
- position?: Position;
93
- filter?: (data: IntentData<Fields>) => data is Data;
94
- resolve: IntentEffectDefinition<GuardedType<IntentResolver<Tag, Fields, Data>['filter']>, IntentResultData<Fields>>;
87
+ export type IntentResolver<Tag extends string, Fields extends IntentParams> = Readonly<{
88
+ action: Tag;
89
+ disposition?: Disposition;
90
+ // TODO(wittjosiah): Would be nice to make this a guard for intents with optional data.
91
+ filter?: (data: IntentData<Fields>) => boolean;
92
+ effect: IntentEffectDefinition<Fields>;
95
93
  }>;
96
94
 
97
- export type AnyIntentResolver = IntentResolver<any, any, any>;
95
+ export type AnyIntentResolver = IntentResolver<any, any>;
98
96
 
99
97
  /**
100
98
  * Creates an intent resolver to match intents to their effects.
@@ -103,16 +101,22 @@ export type AnyIntentResolver = IntentResolver<any, any, any>;
103
101
  * @param params.disposition Determines the priority of the resolver when multiple are resolved.
104
102
  * @param params.filter Optional filter to determine if the resolver should be used.
105
103
  */
106
- export const createResolver = <Tag extends string, Fields extends IntentParams, Data = IntentData<Fields>>(
107
- resolver: IntentResolver<Tag, Fields, Data>,
108
- ) => resolver;
104
+ export const createResolver = <Tag extends string, Fields extends IntentParams>(
105
+ schema: IntentSchema<Tag, Fields>,
106
+ effect: IntentEffectDefinition<Fields>,
107
+ params: Pick<IntentResolver<Tag, Fields>, 'disposition' | 'filter'> = {},
108
+ ): IntentResolver<Tag, Fields> => ({
109
+ action: schema._tag,
110
+ effect,
111
+ ...params,
112
+ });
109
113
 
110
114
  /**
111
115
  * Invokes intents and returns the result.
112
116
  */
113
117
  export type PromiseIntentDispatcher = <Fields extends IntentParams>(
114
118
  intent: IntentChain<any, any, any, Fields>,
115
- ) => Promise<Simplify<IntentDispatcherResult<IntentData<Fields>, IntentResultData<Fields>>>>;
119
+ ) => Promise<Simplify<IntentDispatcherResult<Fields>>>;
116
120
 
117
121
  /**
118
122
  * Creates an effect for intents.
@@ -120,15 +124,9 @@ export type PromiseIntentDispatcher = <Fields extends IntentParams>(
120
124
  export type IntentDispatcher = <Fields extends IntentParams>(
121
125
  intent: IntentChain<any, any, any, Fields>,
122
126
  depth?: number,
123
- ) => Effect.Effect<
124
- Simplify<Required<IntentDispatcherResult<IntentData<Fields>, IntentResultData<Fields>>>['data']>,
125
- Error
126
- >;
127
-
128
- type IntentResult<Tag extends string, Fields extends IntentParams> = IntentEffectResult<
129
- IntentData<Fields>,
130
- IntentResultData<Fields>
131
- > & {
127
+ ) => Effect.Effect<Simplify<Required<IntentDispatcherResult<Fields>>['data']>, Error>;
128
+
129
+ type IntentResult<Tag extends string, Fields extends IntentParams> = IntentEffectResult<Fields> & {
132
130
  _intent: Intent<Tag, Fields>;
133
131
  };
134
132
 
@@ -137,7 +135,7 @@ export type AnyIntentResult = IntentResult<any, any>;
137
135
  /**
138
136
  * Invokes the most recent undoable intent with undo flags.
139
137
  */
140
- export type PromiseIntentUndo = () => Promise<IntentDispatcherResult<any, any>>;
138
+ export type PromiseIntentUndo = () => Promise<IntentDispatcherResult<any>>;
141
139
 
142
140
  /**
143
141
  * Creates an effect which undoes the last intent.
@@ -160,7 +158,7 @@ export type IntentContext = {
160
158
  /**
161
159
  * Sets of an intent dispatcher.
162
160
  *
163
- * @param getResolvers A function that returns an array of available intent resolvers.
161
+ * @param resolvers An array of available intent resolvers.
164
162
  * @param params.historyLimit The maximum number of intent results to keep in history.
165
163
  * @param params.executionLimit The maximum recursion depth of intent chains.
166
164
  */
@@ -170,20 +168,24 @@ export const createDispatcher = (
170
168
  ): IntentContext => {
171
169
  const historyRef = Effect.runSync(Ref.make<AnyIntentResult[][]>([]));
172
170
 
173
- const handleIntent = (intent: AnyIntent) =>
174
- Effect.gen(function* () {
171
+ const handleIntent = (intent: AnyIntent) => {
172
+ return Effect.gen(function* () {
175
173
  const candidates = getResolvers(intent.module)
176
- .filter((r) => r.intent._tag === intent.id)
174
+ .filter((r) => r.action === intent.action)
177
175
  .filter((r) => !r.filter || r.filter(intent.data))
178
- .toSorted(byPosition);
176
+ .toSorted(byDisposition);
179
177
  if (candidates.length === 0) {
180
- yield* Effect.fail(new NoResolversError(intent.id));
178
+ return {
179
+ _intent: intent,
180
+ error: new NoResolversError(intent.action),
181
+ } as AnyIntentResult;
181
182
  }
182
183
 
183
- const effect = candidates[0].resolve(intent.data, intent.undo ?? false);
184
+ const effect = candidates[0].effect(intent.data, intent.undo ?? false);
184
185
  const result = Effect.isEffect(effect) ? yield* effect : yield* Effect.promise(async () => effect);
185
186
  return { _intent: intent, ...result } as AnyIntentResult;
186
187
  });
188
+ };
187
189
 
188
190
  const dispatch: IntentDispatcher = (intentChain, depth = 0) => {
189
191
  return Effect.gen(function* () {
@@ -265,40 +267,3 @@ export const createDispatcher = (
265
267
 
266
268
  return { dispatch, dispatchPromise, undo, undoPromise };
267
269
  };
268
-
269
- const defaultEffect = () => Effect.fail(new Error('Intent runtime not ready'));
270
- const defaultPromise = () => Effect.runPromise(defaultEffect());
271
-
272
- export default (context: PluginsContext) => {
273
- const state = create<IntentContext>({
274
- dispatch: defaultEffect,
275
- dispatchPromise: defaultPromise,
276
- undo: defaultEffect,
277
- undoPromise: defaultPromise,
278
- });
279
-
280
- // TODO(wittjosiah): Make getResolver callback async and allow resolvers to be requested on demand.
281
- const { dispatch, dispatchPromise, undo, undoPromise } = createDispatcher((module) =>
282
- context
283
- .requestCapabilities(Capabilities.IntentResolver, (c, moduleId): c is AnyIntentResolver => {
284
- return module ? moduleId === module : true;
285
- })
286
- .flat(),
287
- );
288
-
289
- const manager = context.requestCapability(Capabilities.PluginManager);
290
- state.dispatch = (intentChain, depth) => {
291
- return Effect.gen(function* () {
292
- yield* manager._activate(Events.SetupIntents);
293
- return yield* dispatch(intentChain, depth);
294
- });
295
- };
296
- state.dispatchPromise = async (intentChain) => {
297
- await manager.activate(Events.SetupIntents);
298
- return await dispatchPromise(intentChain);
299
- };
300
- state.undo = undo;
301
- state.undoPromise = undoPromise;
302
-
303
- return contributes(Capabilities.IntentDispatcher, state);
304
- };
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Schema as S } from '@effect/schema';
5
+ import { S } from '@dxos/echo-schema';
6
6
 
7
7
  export type IntentParams = {
8
8
  readonly input: S.Schema.All;
@@ -25,9 +25,9 @@ export type Intent<Tag extends string, Fields extends IntentParams> = {
25
25
  _schema: IntentSchema<Tag, Fields>;
26
26
 
27
27
  /**
28
- * The id of the intent.
28
+ * The action to perform.
29
29
  */
30
- id: Tag;
30
+ action: Tag;
31
31
 
32
32
  /**
33
33
  * Any data needed to perform the desired action.
@@ -84,7 +84,7 @@ export const createIntent = <Tag extends string, Fields extends IntentParams>(
84
84
  const intent = {
85
85
  ...params,
86
86
  _schema: schema,
87
- id: schema._tag,
87
+ action: schema._tag,
88
88
  data,
89
89
  } satisfies Intent<Tag, Fields>;
90
90
 
@@ -122,7 +122,7 @@ export const chain =
122
122
  const last = {
123
123
  ...params,
124
124
  _schema: schema,
125
- id: schema._tag,
125
+ action: schema._tag,
126
126
  data,
127
127
  } satisfies Intent<NextTag, NextFields>;
128
128
 
@@ -2,12 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { RootSettingsStore } from '@dxos/local-storage';
6
+
5
7
  import { SETTINGS_PLUGIN } from './actions';
6
- import translations from './translations';
7
8
  import { Capabilities, Events } from '../common';
8
- import { contributes, defineModule, definePlugin, lazy } from '../core';
9
+ import { contributes, defineModule, definePlugin } from '../core';
9
10
 
10
- // TODO(wittjosiah): Add options to exclude some modules.
11
11
  export const SettingsPlugin = () =>
12
12
  definePlugin({ id: SETTINGS_PLUGIN }, [
13
13
  defineModule({
@@ -15,21 +15,15 @@ export const SettingsPlugin = () =>
15
15
  activatesOn: Events.Startup,
16
16
  activatesBefore: [Events.SetupSettings],
17
17
  activatesAfter: [Events.SettingsReady],
18
- activate: lazy(() => import('./store')),
19
- }),
20
- defineModule({
21
- id: `${SETTINGS_PLUGIN}/module/translations`,
22
- activatesOn: Events.SetupTranslations,
23
- activate: () => contributes(Capabilities.Translations, translations),
24
- }),
25
- defineModule({
26
- id: `${SETTINGS_PLUGIN}/module/intent-resolver`,
27
- activatesOn: Events.SetupIntents,
28
- activate: lazy(() => import('./intent-resolver')),
29
- }),
30
- defineModule({
31
- id: `${SETTINGS_PLUGIN}/module/app-graph-builder`,
32
- activatesOn: Events.SetupAppGraph,
33
- activate: lazy(() => import('./app-graph-builder')),
18
+ activate: (context) => {
19
+ const allSettings = context.requestCapabilities(Capabilities.Settings);
20
+ const settingsStore = new RootSettingsStore();
21
+
22
+ allSettings.forEach((setting) => {
23
+ settingsStore.createStore(setting as any);
24
+ });
25
+
26
+ return contributes(Capabilities.SettingsStore, settingsStore);
27
+ },
34
28
  }),
35
29
  ]);
@@ -2,12 +2,10 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Schema as S } from '@effect/schema';
5
+ import { S } from '@dxos/echo-schema';
6
6
 
7
7
  export const SETTINGS_PLUGIN = 'dxos.org/plugin/settings';
8
8
  export const SETTINGS_ACTION = `${SETTINGS_PLUGIN}/action`;
9
- export const SETTINGS_ID = 'dxos:settings';
10
- export const SETTINGS_KEY = 'settings';
11
9
 
12
10
  export namespace SettingsAction {
13
11
  export class Open extends S.TaggedClass<Open>()(`${SETTINGS_ACTION}/open`, {
@@ -16,12 +14,4 @@ export namespace SettingsAction {
16
14
  }),
17
15
  output: S.Void,
18
16
  }) {}
19
-
20
- export class OpenPluginRegistry extends S.TaggedClass<OpenPluginRegistry>()(
21
- `${SETTINGS_ACTION}/open-plugin-registry`,
22
- {
23
- input: S.Void,
24
- output: S.Void,
25
- },
26
- ) {}
27
17
  }
@@ -5,17 +5,14 @@
5
5
  import React, { memo, forwardRef, Suspense, useMemo } from 'react';
6
6
 
7
7
  import { useDefaultValue } from '@dxos/react-hooks';
8
- import { byPosition } from '@dxos/util';
8
+ import { byDisposition } from '@dxos/util';
9
9
 
10
10
  import { ErrorBoundary } from './ErrorBoundary';
11
11
  import { useCapabilities } from './useCapabilities';
12
12
  import { Capabilities, type SurfaceDefinition, type SurfaceProps } from '../common';
13
13
  import { type PluginsContext } from '../core';
14
14
 
15
- /**
16
- * @internal
17
- */
18
- export const useSurfaces = () => {
15
+ const useSurfaces = () => {
19
16
  const surfaces = useCapabilities(Capabilities.ReactSurface);
20
17
  return useMemo(() => surfaces.flat(), [surfaces]);
21
18
  };
@@ -26,7 +23,7 @@ const findCandidates = (surfaces: SurfaceDefinition[], { role, data }: Pick<Surf
26
23
  Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,
27
24
  )
28
25
  .filter(({ filter }) => (filter ? filter(data ?? {}) : true))
29
- .toSorted(byPosition);
26
+ .toSorted(byDisposition);
30
27
  };
31
28
 
32
29
  /**
@@ -52,9 +49,11 @@ export const Surface = memo(
52
49
  const surfaces = useSurfaces();
53
50
  const data = useDefaultValue(_data, () => ({}));
54
51
 
55
- // NOTE: Memoizing the candidates makes the surface not re-render based on reactivity within data.
56
- const definitions = findCandidates(surfaces, { role, data });
57
- const candidates = limit ? definitions.slice(0, limit) : definitions;
52
+ const candidates = useMemo(() => {
53
+ const definitions = findCandidates(surfaces, { role, data });
54
+ return limit ? definitions.slice(0, limit) : definitions;
55
+ }, [surfaces, role, data, limit]);
56
+
58
57
  const nodes = candidates.map(({ component: Component, id }) => (
59
58
  <Component ref={forwardedRef} key={id} id={id} role={role} data={data} limit={limit} {...rest} />
60
59
  ));
@@ -71,5 +70,3 @@ export const Surface = memo(
71
70
  },
72
71
  ),
73
72
  );
74
-
75
- Surface.displayName = 'Surface';
@@ -2,9 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export * from './common';
6
5
  export * from './ErrorBoundary';
7
6
  export * from './PluginManagerProvider';
8
7
  export * from './Surface';
9
8
  export * from './useCapabilities';
10
- export * from './useIntentResolver';
@@ -21,7 +21,6 @@ export const useCapabilities = <T, U extends T = T>(
21
21
  () => computed(() => manager.context.requestCapabilities(interfaceDef, filter)),
22
22
  [interfaceDef],
23
23
  );
24
-
25
24
  return signal.value;
26
25
  };
27
26
 
@@ -12,14 +12,14 @@ import { Capabilities, Events } from '../common';
12
12
  import { type AnyCapability, contributes, defineModule, definePlugin, PluginManager } from '../core';
13
13
 
14
14
  /**
15
- * @internal
15
+ * Wraps a story with a plugin manager.
16
16
  */
17
- export const setupPluginManager = ({
17
+ export const withPluginManager = ({
18
18
  capabilities,
19
19
  plugins = [],
20
20
  core = plugins.map(({ meta }) => meta.id),
21
21
  ...options
22
- }: CreateAppOptions & { capabilities?: AnyCapability[] } = {}) => {
22
+ }: CreateAppOptions & { capabilities?: AnyCapability[] } = {}): Decorator => {
23
23
  const pluginManager = new PluginManager({
24
24
  pluginLoader: () => raise(new Error('Not implemented')),
25
25
  plugins: [StoryPlugin(), ...plugins],
@@ -37,14 +37,6 @@ export const setupPluginManager = ({
37
37
  });
38
38
  }
39
39
 
40
- return pluginManager;
41
- };
42
-
43
- /**
44
- * Wraps a story with a plugin manager.
45
- */
46
- export const withPluginManager = (options: CreateAppOptions & { capabilities?: AnyCapability[] } = {}): Decorator => {
47
- const pluginManager = setupPluginManager(options);
48
40
  const App = createApp({ pluginManager });
49
41
 
50
42
  return (Story, context) => {
package/tsconfig.json CHANGED
@@ -20,6 +20,9 @@
20
20
  {
21
21
  "path": "../../common/async"
22
22
  },
23
+ {
24
+ "path": "../../common/context"
25
+ },
23
26
  {
24
27
  "path": "../../common/debug"
25
28
  },
@@ -32,9 +35,6 @@
32
35
  {
33
36
  "path": "../../common/log"
34
37
  },
35
- {
36
- "path": "../../common/random"
37
- },
38
38
  {
39
39
  "path": "../../common/storybook-utils"
40
40
  },
@@ -50,9 +50,6 @@
50
50
  {
51
51
  "path": "../../core/echo/live-object"
52
52
  },
53
- {
54
- "path": "../../experimental/artifact"
55
- },
56
53
  {
57
54
  "path": "../../ui/primitives/react-hooks"
58
55
  },