@dxos/app-framework 0.7.5-main.9cb18ac → 0.7.5-main.9d2a38b

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 (316) hide show
  1. package/dist/lib/browser/chunk-GNLU3GAU.mjs +1595 -0
  2. package/dist/lib/browser/chunk-GNLU3GAU.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +112 -618
  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 +67 -0
  7. package/dist/lib/browser/testing/index.mjs.map +7 -0
  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 +123 -651
  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 +91 -0
  14. package/dist/lib/node/testing/index.cjs.map +7 -0
  15. package/dist/lib/node-esm/chunk-KPMTPXQI.mjs +1597 -0
  16. package/dist/lib/node-esm/chunk-KPMTPXQI.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +112 -618
  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 +68 -0
  21. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  22. package/dist/types/src/App.d.ts +22 -13
  23. package/dist/types/src/App.d.ts.map +1 -1
  24. package/dist/types/src/common/capabilities.d.ts +340 -0
  25. package/dist/types/src/common/capabilities.d.ts.map +1 -0
  26. package/dist/types/src/common/events.d.ts +41 -0
  27. package/dist/types/src/common/events.d.ts.map +1 -0
  28. package/dist/types/src/common/file.d.ts +14 -0
  29. package/dist/types/src/common/file.d.ts.map +1 -0
  30. package/dist/types/src/common/graph.d.ts +21 -0
  31. package/dist/types/src/common/graph.d.ts.map +1 -0
  32. package/dist/types/src/{plugins/common → common}/index.d.ts +3 -1
  33. package/dist/types/src/common/index.d.ts.map +1 -0
  34. package/dist/types/src/{plugins/common → common}/layout.d.ts +0 -11
  35. package/dist/types/src/common/layout.d.ts.map +1 -0
  36. package/dist/types/src/{plugins/common → common}/navigation.d.ts +0 -2
  37. package/dist/types/src/common/navigation.d.ts.map +1 -0
  38. package/dist/types/src/{plugins/plugin-surface/SurfaceContext.d.ts → common/surface.d.ts} +12 -29
  39. package/dist/types/src/common/surface.d.ts.map +1 -0
  40. package/dist/types/src/{plugins/common → common}/translations.d.ts +0 -11
  41. package/dist/types/src/common/translations.d.ts.map +1 -0
  42. package/dist/types/src/core/capabilities.d.ts +90 -0
  43. package/dist/types/src/core/capabilities.d.ts.map +1 -0
  44. package/dist/types/src/core/capabilities.test.d.ts +2 -0
  45. package/dist/types/src/core/capabilities.test.d.ts.map +1 -0
  46. package/dist/types/src/core/events.d.ts +58 -0
  47. package/dist/types/src/core/events.d.ts.map +1 -0
  48. package/dist/types/src/core/index.d.ts +5 -0
  49. package/dist/types/src/core/index.d.ts.map +1 -0
  50. package/dist/types/src/core/manager.d.ts +126 -0
  51. package/dist/types/src/core/manager.d.ts.map +1 -0
  52. package/dist/types/src/core/manager.test.d.ts +2 -0
  53. package/dist/types/src/core/manager.test.d.ts.map +1 -0
  54. package/dist/types/src/core/plugin.d.ts +94 -0
  55. package/dist/types/src/core/plugin.d.ts.map +1 -0
  56. package/dist/types/src/helpers.d.ts +10 -0
  57. package/dist/types/src/helpers.d.ts.map +1 -0
  58. package/dist/types/src/helpers.test.d.ts +2 -0
  59. package/dist/types/src/helpers.test.d.ts.map +1 -0
  60. package/dist/types/src/index.d.ts +5 -1
  61. package/dist/types/src/index.d.ts.map +1 -1
  62. package/dist/types/src/playground/debug/Debug.d.ts +6 -0
  63. package/dist/types/src/playground/debug/Debug.d.ts.map +1 -0
  64. package/dist/types/src/playground/debug/index.d.ts +2 -0
  65. package/dist/types/src/playground/debug/index.d.ts.map +1 -0
  66. package/dist/types/src/playground/debug/plugin.d.ts +2 -0
  67. package/dist/types/src/playground/debug/plugin.d.ts.map +1 -0
  68. package/dist/types/src/playground/generator/Main.d.ts +6 -0
  69. package/dist/types/src/playground/generator/Main.d.ts.map +1 -0
  70. package/dist/types/src/playground/generator/Toolbar.d.ts +6 -0
  71. package/dist/types/src/playground/generator/Toolbar.d.ts.map +1 -0
  72. package/dist/types/src/playground/generator/generator.d.ts +5 -0
  73. package/dist/types/src/playground/generator/generator.d.ts.map +1 -0
  74. package/dist/types/src/playground/generator/index.d.ts +3 -0
  75. package/dist/types/src/playground/generator/index.d.ts.map +1 -0
  76. package/dist/types/src/playground/generator/plugin.d.ts +2 -0
  77. package/dist/types/src/playground/generator/plugin.d.ts.map +1 -0
  78. package/dist/types/src/playground/layout/Layout.d.ts +8 -0
  79. package/dist/types/src/playground/layout/Layout.d.ts.map +1 -0
  80. package/dist/types/src/playground/layout/index.d.ts +2 -0
  81. package/dist/types/src/playground/layout/index.d.ts.map +1 -0
  82. package/dist/types/src/playground/layout/plugin.d.ts +2 -0
  83. package/dist/types/src/playground/layout/plugin.d.ts.map +1 -0
  84. package/dist/types/src/playground/logger/Toolbar.d.ts +6 -0
  85. package/dist/types/src/playground/logger/Toolbar.d.ts.map +1 -0
  86. package/dist/types/src/playground/logger/index.d.ts +2 -0
  87. package/dist/types/src/playground/logger/index.d.ts.map +1 -0
  88. package/dist/types/src/playground/logger/plugin.d.ts +2 -0
  89. package/dist/types/src/playground/logger/plugin.d.ts.map +1 -0
  90. package/dist/types/src/playground/logger/schema.d.ts +13 -0
  91. package/dist/types/src/playground/logger/schema.d.ts.map +1 -0
  92. package/dist/types/src/playground/playground.stories.d.ts +10 -0
  93. package/dist/types/src/playground/playground.stories.d.ts.map +1 -0
  94. package/dist/types/src/{plugins/plugin-intent → plugin-intent}/IntentContext.d.ts +1 -1
  95. package/dist/types/src/plugin-intent/IntentContext.d.ts.map +1 -0
  96. package/dist/types/src/plugin-intent/IntentPlugin.d.ts +2 -0
  97. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +1 -0
  98. package/dist/types/src/plugin-intent/actions.d.ts +23 -0
  99. package/dist/types/src/plugin-intent/actions.d.ts.map +1 -0
  100. package/dist/types/src/plugin-intent/errors.d.ts +16 -0
  101. package/dist/types/src/plugin-intent/errors.d.ts.map +1 -0
  102. package/dist/types/src/plugin-intent/index.d.ts +6 -0
  103. package/dist/types/src/plugin-intent/index.d.ts.map +1 -0
  104. package/dist/types/src/{plugins/plugin-intent → plugin-intent}/intent-dispatcher.d.ts +18 -19
  105. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +1 -0
  106. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts.map +1 -0
  107. package/dist/types/src/{plugins/plugin-intent → plugin-intent}/intent.d.ts +5 -25
  108. package/dist/types/src/plugin-intent/intent.d.ts.map +1 -0
  109. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +2 -0
  110. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +1 -0
  111. package/dist/types/src/{plugins/plugin-settings/provides.d.ts → plugin-settings/actions.d.ts} +1 -10
  112. package/dist/types/src/plugin-settings/actions.d.ts.map +1 -0
  113. package/dist/types/src/plugin-settings/index.d.ts +3 -0
  114. package/dist/types/src/plugin-settings/index.d.ts.map +1 -0
  115. package/dist/types/src/react/ErrorBoundary.d.ts.map +1 -0
  116. package/dist/types/src/react/PluginManagerProvider.d.ts +10 -0
  117. package/dist/types/src/react/PluginManagerProvider.d.ts.map +1 -0
  118. package/dist/types/src/react/Surface.d.ts +12 -0
  119. package/dist/types/src/react/Surface.d.ts.map +1 -0
  120. package/dist/types/src/react/index.d.ts +5 -0
  121. package/dist/types/src/react/index.d.ts.map +1 -0
  122. package/dist/types/src/react/useCapabilities.d.ts +13 -0
  123. package/dist/types/src/react/useCapabilities.d.ts.map +1 -0
  124. package/dist/types/src/testing/index.d.ts +2 -0
  125. package/dist/types/src/testing/index.d.ts.map +1 -0
  126. package/dist/types/src/testing/withPluginManager.d.ts +10 -0
  127. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -0
  128. package/dist/types/src/testing/withPluginManager.stories.d.ts +5 -0
  129. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -0
  130. package/dist/types/tsconfig.tsbuildinfo +1 -1
  131. package/package.json +28 -15
  132. package/project.json +2 -1
  133. package/src/App.tsx +138 -34
  134. package/src/common/capabilities.ts +82 -0
  135. package/src/common/events.ts +63 -0
  136. package/src/common/file.ts +22 -0
  137. package/src/common/graph.ts +30 -0
  138. package/src/{plugins/common → common}/index.ts +3 -1
  139. package/src/{plugins/common → common}/layout.ts +0 -16
  140. package/src/{plugins/common → common}/navigation.ts +0 -15
  141. package/src/{plugins/plugin-surface/SurfaceContext.ts → common/surface.ts} +6 -37
  142. package/src/common/translations.ts +18 -0
  143. package/src/core/capabilities.test.ts +116 -0
  144. package/src/core/capabilities.ts +213 -0
  145. package/src/core/events.ts +58 -0
  146. package/src/core/index.ts +8 -0
  147. package/src/core/manager.test.ts +567 -0
  148. package/src/core/manager.ts +497 -0
  149. package/src/core/plugin.ts +128 -0
  150. package/src/helpers.test.ts +97 -0
  151. package/src/helpers.ts +45 -0
  152. package/src/index.ts +6 -3
  153. package/src/playground/debug/Debug.tsx +39 -0
  154. package/src/playground/debug/index.ts +5 -0
  155. package/src/playground/debug/plugin.ts +17 -0
  156. package/src/playground/generator/Main.tsx +71 -0
  157. package/src/playground/generator/Toolbar.tsx +46 -0
  158. package/src/playground/generator/generator.ts +23 -0
  159. package/src/playground/generator/index.ts +6 -0
  160. package/src/playground/generator/plugin.ts +18 -0
  161. package/src/playground/layout/Layout.tsx +33 -0
  162. package/src/playground/layout/index.ts +5 -0
  163. package/src/playground/layout/plugin.ts +17 -0
  164. package/src/playground/logger/Toolbar.tsx +28 -0
  165. package/src/playground/logger/index.ts +5 -0
  166. package/src/playground/logger/plugin.ts +33 -0
  167. package/src/playground/logger/schema.ts +12 -0
  168. package/src/playground/playground.stories.tsx +34 -0
  169. package/src/{plugins/plugin-intent → plugin-intent}/IntentContext.tsx +12 -4
  170. package/src/plugin-intent/IntentPlugin.tsx +60 -0
  171. package/src/plugin-intent/actions.ts +22 -0
  172. package/src/plugin-intent/errors.ts +39 -0
  173. package/src/{plugins/plugin-intent → plugin-intent}/index.ts +2 -6
  174. package/src/{plugins/plugin-intent → plugin-intent}/intent-dispatcher.test.ts +36 -35
  175. package/src/{plugins/plugin-intent → plugin-intent}/intent-dispatcher.ts +49 -65
  176. package/src/{plugins/plugin-intent → plugin-intent}/intent.ts +5 -21
  177. package/src/plugin-settings/SettingsPlugin.ts +29 -0
  178. package/src/plugin-settings/actions.ts +17 -0
  179. package/src/plugin-settings/index.ts +6 -0
  180. package/src/react/PluginManagerProvider.ts +22 -0
  181. package/src/react/Surface.tsx +72 -0
  182. package/src/react/index.ts +8 -0
  183. package/src/react/useCapabilities.ts +39 -0
  184. package/src/testing/index.ts +5 -0
  185. package/src/testing/withPluginManager.stories.tsx +47 -0
  186. package/src/testing/withPluginManager.tsx +67 -0
  187. package/tsconfig.json +13 -1
  188. package/dist/lib/browser/chunk-3E7RY3CE.mjs +0 -72
  189. package/dist/lib/browser/chunk-3E7RY3CE.mjs.map +0 -7
  190. package/dist/lib/browser/chunk-QG25ZU2N.mjs +0 -320
  191. package/dist/lib/browser/chunk-QG25ZU2N.mjs.map +0 -7
  192. package/dist/lib/browser/chunk-SPDTXTOV.mjs +0 -163
  193. package/dist/lib/browser/chunk-SPDTXTOV.mjs.map +0 -7
  194. package/dist/lib/browser/chunk-WBOXEHBE.mjs +0 -51
  195. package/dist/lib/browser/chunk-WBOXEHBE.mjs.map +0 -7
  196. package/dist/lib/browser/plugin-intent-T7Y3MJ5C.mjs +0 -32
  197. package/dist/lib/browser/plugin-intent-T7Y3MJ5C.mjs.map +0 -7
  198. package/dist/lib/browser/plugin-settings-5U2L2NRU.mjs +0 -15
  199. package/dist/lib/browser/plugin-settings-5U2L2NRU.mjs.map +0 -7
  200. package/dist/lib/browser/plugin-surface-OKPF3EQI.mjs +0 -24
  201. package/dist/lib/browser/plugin-surface-OKPF3EQI.mjs.map +0 -7
  202. package/dist/lib/node/chunk-BW3RNEVI.cjs +0 -185
  203. package/dist/lib/node/chunk-BW3RNEVI.cjs.map +0 -7
  204. package/dist/lib/node/chunk-FCMHRU3M.cjs +0 -70
  205. package/dist/lib/node/chunk-FCMHRU3M.cjs.map +0 -7
  206. package/dist/lib/node/chunk-QBM42OQ6.cjs +0 -97
  207. package/dist/lib/node/chunk-QBM42OQ6.cjs.map +0 -7
  208. package/dist/lib/node/chunk-VWHAALIN.cjs +0 -344
  209. package/dist/lib/node/chunk-VWHAALIN.cjs.map +0 -7
  210. package/dist/lib/node/plugin-intent-F3TQZIUR.cjs +0 -53
  211. package/dist/lib/node/plugin-intent-F3TQZIUR.cjs.map +0 -7
  212. package/dist/lib/node/plugin-settings-W6UHMH5M.cjs +0 -36
  213. package/dist/lib/node/plugin-settings-W6UHMH5M.cjs.map +0 -7
  214. package/dist/lib/node/plugin-surface-CCSIONYW.cjs +0 -45
  215. package/dist/lib/node/plugin-surface-CCSIONYW.cjs.map +0 -7
  216. package/dist/lib/node-esm/chunk-3T5UIJY3.mjs +0 -53
  217. package/dist/lib/node-esm/chunk-3T5UIJY3.mjs.map +0 -7
  218. package/dist/lib/node-esm/chunk-4GX7V5ZE.mjs +0 -164
  219. package/dist/lib/node-esm/chunk-4GX7V5ZE.mjs.map +0 -7
  220. package/dist/lib/node-esm/chunk-CFOUYXQ6.mjs +0 -321
  221. package/dist/lib/node-esm/chunk-CFOUYXQ6.mjs.map +0 -7
  222. package/dist/lib/node-esm/chunk-EYCTSFEJ.mjs +0 -74
  223. package/dist/lib/node-esm/chunk-EYCTSFEJ.mjs.map +0 -7
  224. package/dist/lib/node-esm/plugin-intent-W2HQC6LC.mjs +0 -33
  225. package/dist/lib/node-esm/plugin-intent-W2HQC6LC.mjs.map +0 -7
  226. package/dist/lib/node-esm/plugin-settings-H5RHNFVC.mjs +0 -16
  227. package/dist/lib/node-esm/plugin-settings-H5RHNFVC.mjs.map +0 -7
  228. package/dist/lib/node-esm/plugin-surface-V3YET3UL.mjs +0 -25
  229. package/dist/lib/node-esm/plugin-surface-V3YET3UL.mjs.map +0 -7
  230. package/dist/types/src/plugins/common/file.d.ts +0 -22
  231. package/dist/types/src/plugins/common/file.d.ts.map +0 -1
  232. package/dist/types/src/plugins/common/graph.d.ts +0 -51
  233. package/dist/types/src/plugins/common/graph.d.ts.map +0 -1
  234. package/dist/types/src/plugins/common/index.d.ts.map +0 -1
  235. package/dist/types/src/plugins/common/layout.d.ts.map +0 -1
  236. package/dist/types/src/plugins/common/metadata.d.ts +0 -16
  237. package/dist/types/src/plugins/common/metadata.d.ts.map +0 -1
  238. package/dist/types/src/plugins/common/navigation.d.ts.map +0 -1
  239. package/dist/types/src/plugins/common/translations.d.ts.map +0 -1
  240. package/dist/types/src/plugins/helpers.d.ts +0 -41
  241. package/dist/types/src/plugins/helpers.d.ts.map +0 -1
  242. package/dist/types/src/plugins/index.d.ts +0 -7
  243. package/dist/types/src/plugins/index.d.ts.map +0 -1
  244. package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts +0 -16
  245. package/dist/types/src/plugins/plugin-host/HostPlugin.d.ts.map +0 -1
  246. package/dist/types/src/plugins/plugin-host/PluginContainer.d.ts +0 -14
  247. package/dist/types/src/plugins/plugin-host/PluginContainer.d.ts.map +0 -1
  248. package/dist/types/src/plugins/plugin-host/PluginContext.d.ts +0 -47
  249. package/dist/types/src/plugins/plugin-host/PluginContext.d.ts.map +0 -1
  250. package/dist/types/src/plugins/plugin-host/index.d.ts +0 -6
  251. package/dist/types/src/plugins/plugin-host/index.d.ts.map +0 -1
  252. package/dist/types/src/plugins/plugin-host/plugin.d.ts +0 -104
  253. package/dist/types/src/plugins/plugin-host/plugin.d.ts.map +0 -1
  254. package/dist/types/src/plugins/plugin-host/plugin.test.d.ts +0 -35
  255. package/dist/types/src/plugins/plugin-host/plugin.test.d.ts.map +0 -1
  256. package/dist/types/src/plugins/plugin-intent/IntentContext.d.ts.map +0 -1
  257. package/dist/types/src/plugins/plugin-intent/IntentPlugin.d.ts +0 -8
  258. package/dist/types/src/plugins/plugin-intent/IntentPlugin.d.ts.map +0 -1
  259. package/dist/types/src/plugins/plugin-intent/index.d.ts +0 -7
  260. package/dist/types/src/plugins/plugin-intent/index.d.ts.map +0 -1
  261. package/dist/types/src/plugins/plugin-intent/intent-dispatcher.d.ts.map +0 -1
  262. package/dist/types/src/plugins/plugin-intent/intent-dispatcher.test.d.ts.map +0 -1
  263. package/dist/types/src/plugins/plugin-intent/intent.d.ts.map +0 -1
  264. package/dist/types/src/plugins/plugin-intent/meta.d.ts +0 -6
  265. package/dist/types/src/plugins/plugin-intent/meta.d.ts.map +0 -1
  266. package/dist/types/src/plugins/plugin-intent/provides.d.ts +0 -16
  267. package/dist/types/src/plugins/plugin-intent/provides.d.ts.map +0 -1
  268. package/dist/types/src/plugins/plugin-settings/SettingsPlugin.d.ts +0 -4
  269. package/dist/types/src/plugins/plugin-settings/SettingsPlugin.d.ts.map +0 -1
  270. package/dist/types/src/plugins/plugin-settings/index.d.ts +0 -4
  271. package/dist/types/src/plugins/plugin-settings/index.d.ts.map +0 -1
  272. package/dist/types/src/plugins/plugin-settings/meta.d.ts +0 -5
  273. package/dist/types/src/plugins/plugin-settings/meta.d.ts.map +0 -1
  274. package/dist/types/src/plugins/plugin-settings/provides.d.ts.map +0 -1
  275. package/dist/types/src/plugins/plugin-surface/ErrorBoundary.d.ts.map +0 -1
  276. package/dist/types/src/plugins/plugin-surface/Surface.d.ts +0 -7
  277. package/dist/types/src/plugins/plugin-surface/Surface.d.ts.map +0 -1
  278. package/dist/types/src/plugins/plugin-surface/SurfaceContext.d.ts.map +0 -1
  279. package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts +0 -7
  280. package/dist/types/src/plugins/plugin-surface/SurfacePlugin.d.ts.map +0 -1
  281. package/dist/types/src/plugins/plugin-surface/helpers.d.ts +0 -21
  282. package/dist/types/src/plugins/plugin-surface/helpers.d.ts.map +0 -1
  283. package/dist/types/src/plugins/plugin-surface/index.d.ts +0 -8
  284. package/dist/types/src/plugins/plugin-surface/index.d.ts.map +0 -1
  285. package/dist/types/src/plugins/plugin-surface/meta.d.ts +0 -5
  286. package/dist/types/src/plugins/plugin-surface/meta.d.ts.map +0 -1
  287. package/dist/types/src/plugins/plugin-surface/provides.d.ts +0 -17
  288. package/dist/types/src/plugins/plugin-surface/provides.d.ts.map +0 -1
  289. package/src/plugins/common/file.ts +0 -36
  290. package/src/plugins/common/graph.ts +0 -70
  291. package/src/plugins/common/metadata.ts +0 -29
  292. package/src/plugins/common/translations.ts +0 -36
  293. package/src/plugins/helpers.ts +0 -92
  294. package/src/plugins/index.ts +0 -11
  295. package/src/plugins/plugin-host/HostPlugin.tsx +0 -88
  296. package/src/plugins/plugin-host/PluginContainer.tsx +0 -120
  297. package/src/plugins/plugin-host/PluginContext.tsx +0 -79
  298. package/src/plugins/plugin-host/index.ts +0 -12
  299. package/src/plugins/plugin-host/plugin.test.ts +0 -158
  300. package/src/plugins/plugin-host/plugin.ts +0 -133
  301. package/src/plugins/plugin-intent/IntentPlugin.tsx +0 -75
  302. package/src/plugins/plugin-intent/meta.ts +0 -11
  303. package/src/plugins/plugin-intent/provides.ts +0 -26
  304. package/src/plugins/plugin-settings/SettingsPlugin.tsx +0 -22
  305. package/src/plugins/plugin-settings/index.ts +0 -9
  306. package/src/plugins/plugin-settings/meta.ts +0 -9
  307. package/src/plugins/plugin-settings/provides.ts +0 -34
  308. package/src/plugins/plugin-surface/Surface.tsx +0 -62
  309. package/src/plugins/plugin-surface/SurfacePlugin.tsx +0 -45
  310. package/src/plugins/plugin-surface/helpers.ts +0 -22
  311. package/src/plugins/plugin-surface/index.ts +0 -14
  312. package/src/plugins/plugin-surface/meta.ts +0 -9
  313. package/src/plugins/plugin-surface/provides.ts +0 -27
  314. /package/dist/types/src/{plugins/plugin-intent → plugin-intent}/intent-dispatcher.test.d.ts +0 -0
  315. /package/dist/types/src/{plugins/plugin-surface → react}/ErrorBoundary.d.ts +0 -0
  316. /package/src/{plugins/plugin-surface → react}/ErrorBoundary.tsx +0 -0
@@ -0,0 +1,22 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { S } from '@dxos/echo-schema';
6
+
7
+ import { Label } from './intent';
8
+
9
+ export const INTENT_PLUGIN = 'dxos.org/plugin/intent';
10
+ export const INTENT_ACTION = `${INTENT_PLUGIN}/action`;
11
+
12
+ export namespace IntentAction {
13
+ /**
14
+ * Fired after an intent is dispatched if the intent is undoable.
15
+ */
16
+ export class ShowUndo extends S.TaggedClass<ShowUndo>()(`${INTENT_ACTION}/show-undo`, {
17
+ input: S.Struct({
18
+ message: Label,
19
+ }),
20
+ output: S.Void,
21
+ }) {}
22
+ }
@@ -0,0 +1,39 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ // TODO(wittjosiah): Reconcile with @dxos/protocols. Factor out errors.
6
+
7
+ /**
8
+ * NOTE: Messages should be sentences (Start with a capital letter and end with a period).
9
+ * Errors can optionally include a JSON context object.
10
+ */
11
+ export class BaseError extends Error {
12
+ constructor(
13
+ readonly code: string,
14
+ message?: string,
15
+ readonly context?: Record<string, any>,
16
+ ) {
17
+ // TODO(dmaretskyi): Error.cause.
18
+ super(message ?? code);
19
+ this.name = code;
20
+ // NOTE: Restores prototype chain (https://stackoverflow.com/a/48342359).
21
+ Object.setPrototypeOf(this, new.target.prototype);
22
+ }
23
+ }
24
+
25
+ export class NoResolversError extends BaseError {
26
+ constructor(action: string) {
27
+ super('NO_RESOLVERS', 'No resolvers were found for the action', { action });
28
+ }
29
+ }
30
+
31
+ export class CycleDetectedError extends BaseError {
32
+ constructor(context?: Record<string, any>) {
33
+ super(
34
+ 'CYCLE_DETECTED',
35
+ 'Intent execution limit exceeded. This is likely due to an infinite loop within intent resolvers.',
36
+ context,
37
+ );
38
+ }
39
+ }
@@ -2,12 +2,8 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { IntentPlugin } from './IntentPlugin';
6
-
5
+ export * from './actions';
7
6
  export * from './intent';
8
7
  export * from './intent-dispatcher';
9
- export * from './provides';
10
-
11
8
  export * from './IntentContext';
12
-
13
- export default IntentPlugin;
9
+ export * from './IntentPlugin';
@@ -8,11 +8,11 @@ import { describe, expect, test } from 'vitest';
8
8
  import { S } from '@dxos/echo-schema';
9
9
 
10
10
  import { chain, createIntent } from './intent';
11
- import { createDispatcher, createResolver } from './intent-dispatcher';
11
+ import { type AnyIntentResolver, createDispatcher, createResolver } from './intent-dispatcher';
12
12
 
13
13
  describe('Intent dispatcher', () => {
14
14
  test('throws error if no resolver found', async () => {
15
- const { dispatchPromise } = createDispatcher({});
15
+ const { dispatchPromise } = createDispatcher(() => []);
16
16
  const { data, error } = await dispatchPromise(createIntent(ToString, { value: 1 }));
17
17
 
18
18
  expect(data).toBe(undefined);
@@ -20,7 +20,7 @@ describe('Intent dispatcher', () => {
20
20
  });
21
21
 
22
22
  test('matches intent to resolver and executes', async () => {
23
- const { dispatchPromise } = createDispatcher({ test: [toStringResolver] });
23
+ const { dispatchPromise } = createDispatcher(() => [toStringResolver]);
24
24
  const { data, error } = await dispatchPromise(createIntent(ToString, { value: 1 }));
25
25
 
26
26
  expect(error).toBe(undefined);
@@ -28,18 +28,19 @@ describe('Intent dispatcher', () => {
28
28
  });
29
29
 
30
30
  test('update resolvers', async () => {
31
- const { dispatchPromise, registerResolver } = createDispatcher({ test: [] });
31
+ const resolvers: AnyIntentResolver[] = [];
32
+ const { dispatchPromise } = createDispatcher(() => resolvers);
32
33
  const { error } = await dispatchPromise(createIntent(ToString, { value: 1 }));
33
34
 
34
35
  expect(error).toBeInstanceOf(Error);
35
36
 
36
- const removeResolver = registerResolver('test', toStringResolver);
37
+ resolvers.push(toStringResolver);
37
38
 
38
39
  const { data } = await dispatchPromise(createIntent(ToString, { value: 1 }));
39
40
 
40
41
  expect(data?.string).toBe('1');
41
42
 
42
- removeResolver();
43
+ resolvers.splice(resolvers.indexOf(toStringResolver), 1);
43
44
 
44
45
  {
45
46
  const { data, error } = await dispatchPromise(createIntent(ToString, { value: 1 }));
@@ -50,34 +51,34 @@ describe('Intent dispatcher', () => {
50
51
  });
51
52
 
52
53
  test('compose intent effects', async () => {
53
- const { dispatch } = createDispatcher({ test: [computeResolver] });
54
+ const { dispatch } = createDispatcher(() => [computeResolver]);
54
55
  const program = Effect.gen(function* () {
55
56
  const a = yield* dispatch(createIntent(Compute, { value: 1 }));
56
57
  const b = yield* dispatch(createIntent(Compute, { value: 2 }));
57
- return b.data!.value - a.data!.value;
58
+ return b.value - a.value;
58
59
  });
59
60
 
60
61
  expect(await Effect.runPromise(program)).toBe(2);
61
62
  });
62
63
 
63
64
  test('concurrent intent effects', async () => {
64
- const { dispatch } = createDispatcher({ test: [computeResolver] });
65
+ const { dispatch } = createDispatcher(() => [computeResolver]);
65
66
  const program = Effect.gen(function* () {
66
67
  const fiberA = yield* Effect.fork(dispatch(createIntent(Compute, { value: 5 })));
67
68
  const fiberB = yield* Effect.fork(dispatch(createIntent(Compute, { value: 2 })));
68
69
  const [a, b] = yield* Fiber.join(Fiber.zip(fiberA, fiberB));
69
- return b.data!.value - a.data!.value;
70
+ return b.value - a.value;
70
71
  });
71
72
 
72
73
  expect(await Effect.runPromise(program)).toBe(-6);
73
74
  });
74
75
 
75
76
  test('mix & match intent effects with promises', async () => {
76
- const { dispatch, dispatchPromise } = createDispatcher({ test: [toStringResolver, computeResolver] });
77
+ const { dispatch, dispatchPromise } = createDispatcher(() => [toStringResolver, computeResolver]);
77
78
  const program = Effect.gen(function* () {
78
79
  const a = yield* dispatch(createIntent(Compute, { value: 2 }));
79
- const b = yield* dispatch(createIntent(ToString, { value: a.data!.value }));
80
- return b.data?.string;
80
+ const b = yield* dispatch(createIntent(ToString, { value: a.value }));
81
+ return b.string;
81
82
  });
82
83
 
83
84
  expect(await Effect.runPromise(program)).toBe('4');
@@ -89,22 +90,22 @@ describe('Intent dispatcher', () => {
89
90
  });
90
91
 
91
92
  test('undo intent', async () => {
92
- const { dispatch, undo } = createDispatcher({ test: [computeResolver] });
93
+ const { dispatch, undo } = createDispatcher(() => [computeResolver]);
93
94
  const program = Effect.gen(function* () {
94
95
  const a = yield* dispatch(createIntent(Compute, { value: 2 }));
95
96
 
96
- expect(a.data?.value).toBe(4);
97
+ expect(a.value).toBe(4);
97
98
 
98
99
  const b = yield* undo();
99
100
 
100
- expect(b?.data?.value).toBe(2);
101
+ expect(b.value).toBe(2);
101
102
  });
102
103
 
103
104
  await Effect.runPromise(program);
104
105
  });
105
106
 
106
107
  test('chain intents', async () => {
107
- const { dispatch } = createDispatcher({ test: [computeResolver, toStringResolver, concatResolver] });
108
+ const { dispatch } = createDispatcher(() => [computeResolver, toStringResolver, concatResolver]);
108
109
  const intent = pipe(createIntent(Compute, { value: 1 }), chain(ToString, {}), chain(Concat, { plus: '!' }));
109
110
 
110
111
  expect(intent.first.action).toBe(Compute._tag);
@@ -112,24 +113,24 @@ describe('Intent dispatcher', () => {
112
113
  expect(intent.all.length).toBe(3);
113
114
 
114
115
  const program = Effect.gen(function* () {
115
- const { data } = yield* dispatch(intent);
116
- return data?.string;
116
+ const data = yield* dispatch(intent);
117
+ return data.string;
117
118
  });
118
119
 
119
120
  expect(await Effect.runPromise(program)).toBe('2!');
120
121
  });
121
122
 
122
123
  test('undo chained intent', async () => {
123
- const { dispatch, undo } = createDispatcher({ test: [computeResolver, toStringResolver, concatResolver] });
124
+ const { dispatch, undo } = createDispatcher(() => [computeResolver, toStringResolver, concatResolver]);
124
125
  const intent = pipe(createIntent(Compute, { value: 1 }), chain(Compute, {}), chain(Compute, {}));
125
126
  const program = Effect.gen(function* () {
126
127
  const a = yield* dispatch(intent);
127
128
 
128
- expect(a.data?.value).toBe(8);
129
+ expect(a.value).toBe(8);
129
130
 
130
131
  const b = yield* undo();
131
132
 
132
- expect(b?.data?.value).toBe(1);
133
+ expect(b.value).toBe(1);
133
134
  });
134
135
 
135
136
  await Effect.runPromise(program);
@@ -137,15 +138,15 @@ describe('Intent dispatcher', () => {
137
138
 
138
139
  test('filter resolvers by plugin', async () => {
139
140
  const otherComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 3 } }));
140
- const { dispatch } = createDispatcher({ test: [computeResolver], other: [otherComputeResolver] });
141
+ const { dispatch } = createDispatcher((module) => (module === 'test' ? [computeResolver] : [otherComputeResolver]));
141
142
  const program = Effect.gen(function* () {
142
143
  const a = yield* dispatch(createIntent(Compute, { value: 1 }));
143
144
 
144
- expect(a.data?.value).toBe(2);
145
+ expect(a.value).toBe(3);
145
146
 
146
- const b = yield* dispatch(createIntent(Compute, { value: 1 }, { plugin: 'other' }));
147
+ const b = yield* dispatch(createIntent(Compute, { value: 1 }, { module: 'test' }));
147
148
 
148
- expect(b.data?.value).toBe(3);
149
+ expect(b.value).toBe(2);
149
150
  });
150
151
 
151
152
  await Effect.runPromise(program);
@@ -155,15 +156,15 @@ describe('Intent dispatcher', () => {
155
156
  const conditionalComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 3 } }), {
156
157
  filter: (data): data is { value: number } => data?.value > 1,
157
158
  });
158
- const { dispatch } = createDispatcher({ test: [conditionalComputeResolver, computeResolver] });
159
+ const { dispatch } = createDispatcher(() => [conditionalComputeResolver, computeResolver]);
159
160
  const program = Effect.gen(function* () {
160
161
  const a = yield* dispatch(createIntent(Compute, { value: 1 }));
161
162
 
162
- expect(a.data?.value).toBe(2);
163
+ expect(a.value).toBe(2);
163
164
 
164
165
  const b = yield* dispatch(createIntent(Compute, { value: 2 }));
165
166
 
166
- expect(b.data?.value).toBe(6);
167
+ expect(b.value).toBe(6);
167
168
  });
168
169
 
169
170
  await Effect.runPromise(program);
@@ -173,7 +174,7 @@ describe('Intent dispatcher', () => {
173
174
  const hoistedComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 3 } }), {
174
175
  disposition: 'hoist',
175
176
  });
176
- const { dispatchPromise } = createDispatcher({ test: [computeResolver, hoistedComputeResolver] });
177
+ const { dispatchPromise } = createDispatcher(() => [computeResolver, hoistedComputeResolver]);
177
178
  const { data } = await dispatchPromise(createIntent(Compute, { value: 1 }));
178
179
  expect(data?.value).toBe(3);
179
180
  });
@@ -185,28 +186,28 @@ describe('Intent dispatcher', () => {
185
186
  const fallbackComputeResolver = createResolver(Compute, async (data) => ({ data: { value: data?.value * 3 } }), {
186
187
  disposition: 'fallback',
187
188
  });
188
- const { dispatch } = createDispatcher({ test: [fallbackComputeResolver, conditionalComputeResolver] });
189
+ const { dispatch } = createDispatcher(() => [fallbackComputeResolver, conditionalComputeResolver]);
189
190
  const program = Effect.gen(function* () {
190
191
  const a = yield* dispatch(createIntent(Compute, { value: 1 }));
191
192
 
192
- expect(a.data?.value).toBe(2);
193
+ expect(a.value).toBe(2);
193
194
 
194
195
  const b = yield* dispatch(createIntent(Compute, { value: 2 }));
195
196
 
196
- expect(b.data?.value).toBe(6);
197
+ expect(b.value).toBe(6);
197
198
  });
198
199
 
199
200
  await Effect.runPromise(program);
200
201
  });
201
202
 
202
203
  test('non-struct inputs & outputs', async () => {
203
- const { dispatchPromise } = createDispatcher({ test: [addResolver] });
204
+ const { dispatchPromise } = createDispatcher(() => [addResolver]);
204
205
  const { data } = await dispatchPromise(createIntent(Add, [1, 1]));
205
206
  expect(data).toBe(2);
206
207
  });
207
208
 
208
209
  test('empty inputs & outputs', async () => {
209
- const { dispatchPromise } = createDispatcher({ test: [sideEffectResolver] });
210
+ const { dispatchPromise } = createDispatcher(() => [sideEffectResolver]);
210
211
  const { data } = await dispatchPromise(createIntent(SideEffect));
211
212
  expect(data).toBe(undefined);
212
213
  });
@@ -2,13 +2,15 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Effect, Ref } from 'effect';
5
+ import { Effect, Option, pipe, Ref } from 'effect';
6
+ import { type Simplify } from 'effect/Types';
6
7
 
7
- import { type MaybePromise, pick } from '@dxos/util';
8
+ import { type MaybePromise, byDisposition, type Disposition } from '@dxos/util';
8
9
 
10
+ import { IntentAction } from './actions';
11
+ import { CycleDetectedError, NoResolversError } from './errors';
9
12
  import {
10
13
  createIntent,
11
- IntentAction,
12
14
  type AnyIntent,
13
15
  type AnyIntentChain,
14
16
  type Intent,
@@ -53,6 +55,8 @@ export type IntentEffectResult<Fields extends IntentParams> = {
53
55
  * An error that occurred while performing the action.
54
56
  *
55
57
  * If the intent is apart of a chain of intents and an error occurs, the chain will be aborted.
58
+ *
59
+ * Return caught error instead of throwing to trigger other intent to be triggered prior to returning the error.
56
60
  */
57
61
  error?: Error;
58
62
 
@@ -69,15 +73,6 @@ export type AnyIntentEffectResult = IntentEffectResult<any>;
69
73
  */
70
74
  export type IntentDispatcherResult<Fields extends IntentParams> = Pick<IntentEffectResult<Fields>, 'data' | 'error'>;
71
75
 
72
- /**
73
- * Determines the priority of the effect when multiple intent resolvers are matched.
74
- *
75
- * - `static` - The effect is selected in the order it was resolved.
76
- * - `hoist` - The effect is selected before `static` effects.
77
- * - `fallback` - The effect is selected after `static` effects.
78
- */
79
- export type IntentDisposition = 'static' | 'hoist' | 'fallback';
80
-
81
76
  /**
82
77
  * The implementation of an intent effect.
83
78
  */
@@ -89,13 +84,13 @@ export type IntentEffectDefinition<Fields extends IntentParams> = (
89
84
  /**
90
85
  * Intent resolver to match intents to their effects.
91
86
  */
92
- export type IntentResolver<Tag extends string, Fields extends IntentParams> = {
87
+ export type IntentResolver<Tag extends string, Fields extends IntentParams> = Readonly<{
93
88
  action: Tag;
94
- disposition?: IntentDisposition;
89
+ disposition?: Disposition;
95
90
  // TODO(wittjosiah): Would be nice to make this a guard for intents with optional data.
96
91
  filter?: (data: IntentData<Fields>) => boolean;
97
92
  effect: IntentEffectDefinition<Fields>;
98
- };
93
+ }>;
99
94
 
100
95
  export type AnyIntentResolver = IntentResolver<any, any>;
101
96
 
@@ -121,7 +116,7 @@ export const createResolver = <Tag extends string, Fields extends IntentParams>(
121
116
  */
122
117
  export type PromiseIntentDispatcher = <Fields extends IntentParams>(
123
118
  intent: IntentChain<any, any, any, Fields>,
124
- ) => Promise<IntentDispatcherResult<Fields>>;
119
+ ) => Promise<Simplify<IntentDispatcherResult<Fields>>>;
125
120
 
126
121
  /**
127
122
  * Creates an effect for intents.
@@ -129,23 +124,23 @@ export type PromiseIntentDispatcher = <Fields extends IntentParams>(
129
124
  export type IntentDispatcher = <Fields extends IntentParams>(
130
125
  intent: IntentChain<any, any, any, Fields>,
131
126
  depth?: number,
132
- ) => Effect.Effect<IntentDispatcherResult<Fields>, Error>;
127
+ ) => Effect.Effect<Simplify<Required<IntentDispatcherResult<Fields>>['data']>, Error>;
133
128
 
134
129
  type IntentResult<Tag extends string, Fields extends IntentParams> = IntentEffectResult<Fields> & {
135
130
  _intent: Intent<Tag, Fields>;
136
131
  };
137
132
 
138
- type AnyIntentResult = IntentResult<any, any>;
133
+ export type AnyIntentResult = IntentResult<any, any>;
139
134
 
140
135
  /**
141
136
  * Invokes the most recent undoable intent with undo flags.
142
137
  */
143
- export type PromiseIntentUndo = () => Promise<IntentDispatcherResult<any> | undefined>;
138
+ export type PromiseIntentUndo = () => Promise<IntentDispatcherResult<any>>;
144
139
 
145
140
  /**
146
141
  * Creates an effect which undoes the last intent.
147
142
  */
148
- export type IntentUndo = () => Effect.Effect<IntentDispatcherResult<any> | undefined, Error>;
143
+ export type IntentUndo = () => Effect.Effect<any, Error>;
149
144
 
150
145
  /**
151
146
  * Check if a chain of results is undoable.
@@ -158,7 +153,6 @@ export type IntentContext = {
158
153
  dispatchPromise: PromiseIntentDispatcher;
159
154
  undo: IntentUndo;
160
155
  undoPromise: PromiseIntentUndo;
161
- registerResolver: (id: string, resolver: AnyIntentResolver) => () => void;
162
156
  };
163
157
 
164
158
  /**
@@ -169,40 +163,34 @@ export type IntentContext = {
169
163
  * @param params.executionLimit The maximum recursion depth of intent chains.
170
164
  */
171
165
  export const createDispatcher = (
172
- resolvers: Record<string, AnyIntentResolver[]>,
166
+ getResolvers: (module?: string) => AnyIntentResolver[],
173
167
  { executionLimit = EXECUTION_LIMIT, historyLimit = HISTORY_LIMIT } = {},
174
168
  ): IntentContext => {
175
169
  const historyRef = Effect.runSync(Ref.make<AnyIntentResult[][]>([]));
176
170
 
177
171
  const handleIntent = (intent: AnyIntent) => {
178
172
  return Effect.gen(function* () {
179
- const candidates = Object.entries(resolvers)
180
- .filter(([id, _]) => (intent.plugin ? id === intent.plugin : true))
181
- .flatMap(([_, resolvers]) => resolvers)
173
+ const candidates = getResolvers(intent.module)
182
174
  .filter((r) => r.action === intent.action)
183
175
  .filter((r) => !r.filter || r.filter(intent.data))
184
- .toSorted(({ disposition: a = 'static' }, { disposition: b = 'static' }) => {
185
- return a === b ? 0 : a === 'hoist' || b === 'fallback' ? -1 : b === 'hoist' || a === 'fallback' ? 1 : 0;
186
- });
176
+ .toSorted(byDisposition);
187
177
  if (candidates.length === 0) {
188
178
  return {
189
179
  _intent: intent,
190
- error: new Error(`No resolver found for action: ${intent.action}`),
191
- } satisfies AnyIntentResult;
180
+ error: new NoResolversError(intent.action),
181
+ } as AnyIntentResult;
192
182
  }
193
183
 
194
184
  const effect = candidates[0].effect(intent.data, intent.undo ?? false);
195
185
  const result = Effect.isEffect(effect) ? yield* effect : yield* Effect.promise(async () => effect);
196
- return { _intent: intent, ...result } satisfies AnyIntentResult;
186
+ return { _intent: intent, ...result } as AnyIntentResult;
197
187
  });
198
188
  };
199
189
 
200
190
  const dispatch: IntentDispatcher = (intentChain, depth = 0) => {
201
191
  return Effect.gen(function* () {
202
192
  if (depth > executionLimit) {
203
- yield* Effect.fail(
204
- new Error('Intent execution limit exceeded. This is likely due to an infinite loop within intent resolvers.'),
205
- );
193
+ yield* Effect.fail(new CycleDetectedError());
206
194
  }
207
195
 
208
196
  const resultsRef = yield* Ref.make<AnyIntentResult[]>([]);
@@ -210,9 +198,6 @@ export const createDispatcher = (
210
198
  const { data: prev } = (yield* resultsRef.get)[0] ?? {};
211
199
  const result = yield* handleIntent({ ...intent, data: { ...intent.data, ...prev } });
212
200
  yield* Ref.update(resultsRef, (results) => [result, ...results]);
213
- if (result.error) {
214
- break;
215
- }
216
201
  if (result.intents) {
217
202
  for (const intent of result.intents) {
218
203
  // Returned intents are dispatched but not yielded into results,
@@ -221,34 +206,39 @@ export const createDispatcher = (
221
206
  yield* dispatch(intent, depth + 1);
222
207
  }
223
208
  }
209
+ if (result.error) {
210
+ yield* Effect.fail(result.error);
211
+ }
224
212
  }
225
213
 
226
214
  const results = yield* resultsRef.get;
227
215
  const result = results[0];
228
- if (result) {
229
- yield* Ref.update(historyRef, (history) => {
230
- const next = [...history, results];
231
- if (next.length > historyLimit) {
232
- next.splice(0, next.length - historyLimit);
233
- }
234
- return next;
235
- });
236
-
237
- if (result.undoable && isUndoable(results)) {
238
- // TODO(wittjosiah): Is there a better way to handle showing undo for chains?
239
- yield* dispatch(createIntent(IntentAction.ShowUndo, { message: result.undoable.message }));
216
+ yield* Ref.update(historyRef, (history) => {
217
+ const next = [...history, results];
218
+ if (next.length > historyLimit) {
219
+ next.splice(0, next.length - historyLimit);
240
220
  }
241
-
242
- return pick(result, ['data', 'error']);
243
- } else {
244
- return { data: {}, error: new Error('No results') };
221
+ return next;
222
+ });
223
+
224
+ if (result.undoable && isUndoable(results)) {
225
+ // TODO(wittjosiah): Is there a better way to handle showing undo for chains?
226
+ yield* pipe(
227
+ dispatch(createIntent(IntentAction.ShowUndo, { message: result.undoable.message })),
228
+ Effect.catchSome((err) =>
229
+ err instanceof NoResolversError ? Option.some(Effect.succeed(undefined)) : Option.none(),
230
+ ),
231
+ );
245
232
  }
233
+
234
+ return result.data;
246
235
  });
247
236
  };
248
237
 
249
238
  const dispatchPromise: PromiseIntentDispatcher = (intentChain) => {
250
- const program = dispatch(intentChain);
251
- return Effect.runPromise(program);
239
+ return Effect.runPromise(dispatch(intentChain))
240
+ .then((data) => ({ data }))
241
+ .catch((error) => ({ error }));
252
242
  };
253
243
 
254
244
  const undo: IntentUndo = () => {
@@ -270,16 +260,10 @@ export const createDispatcher = (
270
260
  };
271
261
 
272
262
  const undoPromise: PromiseIntentUndo = () => {
273
- const program = undo();
274
- return Effect.runPromise(program);
275
- };
276
-
277
- const registerResolver = (id: string, resolver: AnyIntentResolver) => {
278
- resolvers[id] = [...(resolvers[id] ?? []), resolver];
279
- return () => {
280
- resolvers[id] = resolvers[id].filter((r) => r !== resolver);
281
- };
263
+ return Effect.runPromise(undo())
264
+ .then((data) => ({ data }))
265
+ .catch((error) => ({ error }));
282
266
  };
283
267
 
284
- return { dispatch, dispatchPromise, undo, undoPromise, registerResolver };
268
+ return { dispatch, dispatchPromise, undo, undoPromise };
285
269
  };
@@ -4,8 +4,6 @@
4
4
 
5
5
  import { S } from '@dxos/echo-schema';
6
6
 
7
- import { INTENT_PLUGIN } from './meta';
8
-
9
7
  export type IntentParams = {
10
8
  readonly input: S.Schema.All;
11
9
  readonly output: S.Schema.All;
@@ -37,11 +35,11 @@ export type Intent<Tag extends string, Fields extends IntentParams> = {
37
35
  data: IntentData<Fields>;
38
36
 
39
37
  /**
40
- * Plugin ID.
41
- * If specified, the intent will be sent explicitly to the plugin.
38
+ * Module ID.
39
+ * If specified, the intent will be sent explicitly to the plugin module.
42
40
  * Otherwise, the intent will be sent to all plugins, in order and the first to resolve a non-null value will be used.
43
41
  */
44
- plugin?: string;
42
+ module?: string;
45
43
 
46
44
  /**
47
45
  * Whether or not the intent is being undone.
@@ -78,7 +76,7 @@ export type AnyIntentChain = IntentChain<any, any, any, any>;
78
76
  export const createIntent = <Tag extends string, Fields extends IntentParams>(
79
77
  schema: IntentSchema<Tag, Fields>,
80
78
  data: IntentData<Fields> = {},
81
- params: Pick<AnyIntent, 'plugin' | 'undo'> = {},
79
+ params: Pick<AnyIntent, 'module' | 'undo'> = {},
82
80
  ): IntentChain<Tag, Tag, Fields, Fields> => {
83
81
  // The output of validateSync breaks proxy objects so this is just used for validation.
84
82
  // TODO(wittjosiah): Is there a better way to make theses types align?
@@ -114,7 +112,7 @@ export const chain =
114
112
  >(
115
113
  schema: IntentSchema<NextTag, NextFields>,
116
114
  data: Omit<IntentData<NextFields>, keyof IntentResultData<LastFields>> = {},
117
- params: Pick<AnyIntent, 'plugin' | 'undo'> = {},
115
+ params: Pick<AnyIntent, 'module' | 'undo'> = {},
118
116
  ) =>
119
117
  (
120
118
  intent: IntentChain<FirstTag, any, FirstFields, LastFields>,
@@ -146,17 +144,3 @@ export const Label = S.Union(
146
144
  S.mutable(S.Tuple(S.String, S.mutable(S.Struct({ ns: S.String, count: S.optional(S.Number) })))),
147
145
  );
148
146
  export type Label = S.Schema.Type<typeof Label>;
149
-
150
- export const INTENT_ACTION = `${INTENT_PLUGIN}/action`;
151
-
152
- export namespace IntentAction {
153
- /**
154
- * Fired after an intent is dispatched if the intent is undoable.
155
- */
156
- export class ShowUndo extends S.TaggedClass<ShowUndo>()(`${INTENT_ACTION}/show-undo`, {
157
- input: S.Struct({
158
- message: Label,
159
- }),
160
- output: S.Void,
161
- }) {}
162
- }
@@ -0,0 +1,29 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { RootSettingsStore } from '@dxos/local-storage';
6
+
7
+ import { SETTINGS_PLUGIN } from './actions';
8
+ import { Capabilities, Events } from '../common';
9
+ import { contributes, defineModule, definePlugin } from '../core';
10
+
11
+ export const SettingsPlugin = () =>
12
+ definePlugin({ id: SETTINGS_PLUGIN }, [
13
+ defineModule({
14
+ id: `${SETTINGS_PLUGIN}/module/store`,
15
+ activatesOn: Events.Startup,
16
+ activatesBefore: [Events.SetupSettings],
17
+ activatesAfter: [Events.SettingsReady],
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
+ },
28
+ }),
29
+ ]);
@@ -0,0 +1,17 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { S } from '@dxos/echo-schema';
6
+
7
+ export const SETTINGS_PLUGIN = 'dxos.org/plugin/settings';
8
+ export const SETTINGS_ACTION = `${SETTINGS_PLUGIN}/action`;
9
+
10
+ export namespace SettingsAction {
11
+ export class Open extends S.TaggedClass<Open>()(`${SETTINGS_ACTION}/open`, {
12
+ input: S.Struct({
13
+ plugin: S.optional(S.String),
14
+ }),
15
+ output: S.Void,
16
+ }) {}
17
+ }
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './actions';
6
+ export * from './SettingsPlugin';