@dxos/app-framework 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6

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 (421) hide show
  1. package/.storybook/main.mts +1 -3
  2. package/dist/lib/browser/{capability-7PCNSWBT.mjs → capability-4NSF2SOO.mjs} +16 -11
  3. package/dist/lib/browser/capability-4NSF2SOO.mjs.map +7 -0
  4. package/dist/lib/browser/capability-EB3UKSKA.mjs +35 -0
  5. package/dist/lib/browser/capability-EB3UKSKA.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-FMZN33N4.mjs → chunk-27FZETIA.mjs} +324 -181
  7. package/dist/lib/browser/chunk-27FZETIA.mjs.map +7 -0
  8. package/dist/lib/browser/chunk-CV7I2AAB.mjs +80 -0
  9. package/dist/lib/browser/chunk-CV7I2AAB.mjs.map +7 -0
  10. package/dist/lib/browser/{chunk-6Y7PZV72.mjs → chunk-FL2XTEJH.mjs} +3 -4
  11. package/dist/lib/browser/chunk-FL2XTEJH.mjs.map +7 -0
  12. package/dist/lib/browser/chunk-H7OMDDGW.mjs +42 -0
  13. package/dist/lib/browser/chunk-H7OMDDGW.mjs.map +7 -0
  14. package/dist/lib/browser/chunk-HDQXX5DC.mjs +157 -0
  15. package/dist/lib/browser/chunk-HDQXX5DC.mjs.map +7 -0
  16. package/dist/lib/browser/chunk-I34GF4NG.mjs +34 -0
  17. package/dist/lib/browser/chunk-I34GF4NG.mjs.map +7 -0
  18. package/dist/lib/browser/chunk-KNBRTZVK.mjs +892 -0
  19. package/dist/lib/browser/chunk-KNBRTZVK.mjs.map +7 -0
  20. package/dist/lib/browser/{chunk-7IQHKD4U.mjs → chunk-NO7R7QHA.mjs} +4 -7
  21. package/dist/lib/browser/chunk-NO7R7QHA.mjs.map +7 -0
  22. package/dist/lib/browser/{chunk-TCLLRCS3.mjs → chunk-P2E7VMRF.mjs} +10 -7
  23. package/dist/lib/browser/chunk-P2E7VMRF.mjs.map +7 -0
  24. package/dist/lib/browser/{chunk-PKQT6C53.mjs → chunk-QSXYHXCE.mjs} +3 -2
  25. package/dist/lib/browser/chunk-QSXYHXCE.mjs.map +7 -0
  26. package/dist/lib/browser/chunk-RFSO3JRG.mjs +1 -0
  27. package/dist/lib/browser/chunk-TGX63LTL.mjs +8 -0
  28. package/dist/lib/browser/{chunk-FHQTHCX7.mjs.map → chunk-TGX63LTL.mjs.map} +1 -1
  29. package/dist/lib/browser/cli/index.mjs +90 -0
  30. package/dist/lib/browser/cli/index.mjs.map +7 -0
  31. package/dist/lib/browser/common/activation-events.mjs +24 -0
  32. package/dist/lib/browser/common/capabilities.mjs +46 -0
  33. package/dist/lib/browser/core/activation-event.mjs +1 -1
  34. package/dist/lib/browser/core/capability.mjs +1 -1
  35. package/dist/lib/browser/core/plugin-manager.mjs +4 -4
  36. package/dist/lib/browser/core/plugin.mjs +6 -4
  37. package/dist/lib/browser/core/url-loader.mjs +12 -0
  38. package/dist/lib/browser/index.mjs +40 -131
  39. package/dist/lib/browser/index.mjs.map +4 -4
  40. package/dist/lib/browser/invoker-capability-P7KPBTP3.mjs +43 -0
  41. package/dist/lib/browser/invoker-capability-P7KPBTP3.mjs.map +7 -0
  42. package/dist/lib/browser/meta.json +1 -1
  43. package/dist/lib/browser/testing/index.mjs +56 -34
  44. package/dist/lib/browser/testing/index.mjs.map +3 -3
  45. package/dist/lib/browser/{react → ui}/index.mjs +19 -21
  46. package/dist/lib/browser/ui/index.mjs.map +7 -0
  47. package/dist/lib/node-esm/{capability-CFLQ2QQU.mjs → capability-CB3MNEI3.mjs} +16 -11
  48. package/dist/lib/node-esm/capability-CB3MNEI3.mjs.map +7 -0
  49. package/dist/lib/node-esm/capability-CMROGK7R.mjs +36 -0
  50. package/dist/lib/node-esm/capability-CMROGK7R.mjs.map +7 -0
  51. package/dist/lib/node-esm/{chunk-STMXUEPO.mjs → chunk-37NG7SIN.mjs} +3 -4
  52. package/dist/lib/node-esm/chunk-37NG7SIN.mjs.map +7 -0
  53. package/dist/lib/node-esm/chunk-7JPKC7OM.mjs +893 -0
  54. package/dist/lib/node-esm/chunk-7JPKC7OM.mjs.map +7 -0
  55. package/dist/lib/node-esm/chunk-7PPVTBYR.mjs +81 -0
  56. package/dist/lib/node-esm/chunk-7PPVTBYR.mjs.map +7 -0
  57. package/dist/lib/node-esm/chunk-BQ56U4QX.mjs +43 -0
  58. package/dist/lib/node-esm/chunk-BQ56U4QX.mjs.map +7 -0
  59. package/dist/lib/node-esm/{chunk-GT6OKM5I.mjs → chunk-CG6UBBZZ.mjs} +10 -7
  60. package/dist/lib/node-esm/chunk-CG6UBBZZ.mjs.map +7 -0
  61. package/dist/lib/node-esm/chunk-EL3R25OQ.mjs +2 -0
  62. package/dist/lib/node-esm/chunk-EL3R25OQ.mjs.map +7 -0
  63. package/dist/lib/node-esm/{chunk-663A54LQ.mjs → chunk-EXYTXQ47.mjs} +4 -7
  64. package/dist/lib/node-esm/chunk-EXYTXQ47.mjs.map +7 -0
  65. package/dist/lib/node-esm/{chunk-UEWJDI2L.mjs → chunk-FKE4Z3D6.mjs} +2 -2
  66. package/dist/lib/node-esm/{chunk-UEWJDI2L.mjs.map → chunk-FKE4Z3D6.mjs.map} +1 -1
  67. package/dist/lib/node-esm/chunk-OXXXRCQX.mjs +158 -0
  68. package/dist/lib/node-esm/chunk-OXXXRCQX.mjs.map +7 -0
  69. package/dist/lib/node-esm/chunk-WZCSOX5Q.mjs +35 -0
  70. package/dist/lib/node-esm/chunk-WZCSOX5Q.mjs.map +7 -0
  71. package/dist/lib/node-esm/{chunk-XYQTBFPA.mjs → chunk-YH44RHP6.mjs} +324 -181
  72. package/dist/lib/node-esm/chunk-YH44RHP6.mjs.map +7 -0
  73. package/dist/lib/node-esm/{chunk-7OWSHPYK.mjs → chunk-ZZ7CKK6W.mjs} +3 -2
  74. package/dist/lib/node-esm/chunk-ZZ7CKK6W.mjs.map +7 -0
  75. package/dist/lib/node-esm/cli/index.mjs +91 -0
  76. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  77. package/dist/lib/node-esm/common/activation-events.mjs +25 -0
  78. package/dist/lib/node-esm/common/activation-events.mjs.map +7 -0
  79. package/dist/lib/node-esm/common/capabilities.mjs +47 -0
  80. package/dist/lib/node-esm/common/capabilities.mjs.map +7 -0
  81. package/dist/lib/node-esm/core/activation-event.mjs +1 -1
  82. package/dist/lib/node-esm/core/capability.mjs +1 -1
  83. package/dist/lib/node-esm/core/plugin-manager.mjs +4 -4
  84. package/dist/lib/node-esm/core/plugin.mjs +6 -4
  85. package/dist/lib/node-esm/core/url-loader.mjs +13 -0
  86. package/dist/lib/node-esm/core/url-loader.mjs.map +7 -0
  87. package/dist/lib/node-esm/index.mjs +40 -131
  88. package/dist/lib/node-esm/index.mjs.map +4 -4
  89. package/dist/lib/node-esm/invoker-capability-3C5H46ZY.mjs +44 -0
  90. package/dist/lib/node-esm/invoker-capability-3C5H46ZY.mjs.map +7 -0
  91. package/dist/lib/node-esm/meta.json +1 -1
  92. package/dist/lib/node-esm/testing/index.mjs +56 -34
  93. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  94. package/dist/lib/node-esm/{react → ui}/index.mjs +19 -21
  95. package/dist/lib/node-esm/ui/index.mjs.map +7 -0
  96. package/dist/plugin/node-esm/index.mjs +384 -0
  97. package/dist/plugin/node-esm/index.mjs.map +7 -0
  98. package/dist/plugin/node-esm/meta.json +1 -0
  99. package/dist/types/src/{cli.d.ts → cli/cli.d.ts} +2 -2
  100. package/dist/types/src/cli/cli.d.ts.map +1 -0
  101. package/dist/types/src/cli/index.d.ts +2 -0
  102. package/dist/types/src/cli/index.d.ts.map +1 -0
  103. package/dist/types/src/common/activation-events.d.ts +27 -0
  104. package/dist/types/src/common/activation-events.d.ts.map +1 -0
  105. package/dist/types/src/common/capabilities.d.ts +110 -0
  106. package/dist/types/src/common/capabilities.d.ts.map +1 -0
  107. package/dist/types/src/common/index.d.ts +4 -9
  108. package/dist/types/src/common/index.d.ts.map +1 -1
  109. package/dist/types/src/common/operations.d.ts +8 -369
  110. package/dist/types/src/common/operations.d.ts.map +1 -1
  111. package/dist/types/src/common/translations.d.ts +0 -9
  112. package/dist/types/src/common/translations.d.ts.map +1 -1
  113. package/dist/types/src/core/activation-event.d.ts +1 -1
  114. package/dist/types/src/core/activation-event.d.ts.map +1 -1
  115. package/dist/types/src/core/capability.d.ts +7 -7
  116. package/dist/types/src/core/capability.d.ts.map +1 -1
  117. package/dist/types/src/core/index.d.ts +1 -0
  118. package/dist/types/src/core/index.d.ts.map +1 -1
  119. package/dist/types/src/core/plugin-manager.d.ts +9 -2
  120. package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
  121. package/dist/types/src/core/plugin.d.ts +6 -1
  122. package/dist/types/src/core/plugin.d.ts.map +1 -1
  123. package/dist/types/src/core/url-loader.d.ts +25 -0
  124. package/dist/types/src/core/url-loader.d.ts.map +1 -0
  125. package/dist/types/src/core/url-loader.test.d.ts +2 -0
  126. package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
  127. package/dist/types/src/index.d.ts +1 -3
  128. package/dist/types/src/index.d.ts.map +1 -1
  129. package/dist/types/src/plugin-operation/history/capability.d.ts +1 -1
  130. package/dist/types/src/plugin-operation/history/errors.d.ts +30 -3
  131. package/dist/types/src/plugin-operation/history/errors.d.ts.map +1 -1
  132. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts +11 -3
  133. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts.map +1 -1
  134. package/dist/types/src/plugin-operation/invoker-capability.d.ts +1 -1
  135. package/dist/types/src/plugin-operation/invoker-capability.d.ts.map +1 -1
  136. package/dist/types/src/plugin-operation/testing.d.ts +26 -77
  137. package/dist/types/src/plugin-operation/testing.d.ts.map +1 -1
  138. package/dist/types/src/plugin-runtime/capability.d.ts +2 -2
  139. package/dist/types/src/plugin-runtime/capability.d.ts.map +1 -1
  140. package/dist/types/src/testing/withPluginManager.d.ts +1 -1
  141. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  142. package/dist/types/src/{react → ui/components/App}/App.d.ts +3 -2
  143. package/dist/types/src/ui/components/App/App.d.ts.map +1 -0
  144. package/dist/types/src/{react/Surface.stories.d.ts → ui/components/App/App.stories.d.ts} +7 -2
  145. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -0
  146. package/dist/types/src/ui/components/App/index.d.ts +2 -0
  147. package/dist/types/src/ui/components/App/index.d.ts.map +1 -0
  148. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -0
  149. package/dist/types/src/{react → ui/components/PluginManager}/PluginManagerProvider.d.ts +1 -1
  150. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -0
  151. package/dist/types/src/ui/components/PluginManager/index.d.ts +2 -0
  152. package/dist/types/src/ui/components/PluginManager/index.d.ts.map +1 -0
  153. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +12 -0
  154. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -0
  155. package/dist/types/src/{react/App.stories.d.ts → ui/components/Surface/SurfaceComponent.stories.d.ts} +1 -1
  156. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -0
  157. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -0
  158. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
  159. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
  160. package/dist/types/src/ui/components/Surface/context.d.ts +5 -0
  161. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -0
  162. package/dist/types/src/ui/components/Surface/index.d.ts +26 -0
  163. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -0
  164. package/dist/types/src/{common/surface.d.ts → ui/components/Surface/types.d.ts} +20 -18
  165. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -0
  166. package/dist/types/src/ui/components/index.d.ts +4 -0
  167. package/dist/types/src/ui/components/index.d.ts.map +1 -0
  168. package/dist/types/src/ui/hooks/index.d.ts +6 -0
  169. package/dist/types/src/ui/hooks/index.d.ts.map +1 -0
  170. package/dist/types/src/{react → ui/hooks}/useApp.d.ts +26 -9
  171. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -0
  172. package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
  173. package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
  174. package/dist/types/src/{react → ui/hooks}/useCapabilities.d.ts +6 -1
  175. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -0
  176. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -0
  177. package/dist/types/src/{react/common.d.ts → ui/hooks/useSettingsState.d.ts} +1 -5
  178. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -0
  179. package/dist/types/src/ui/hooks/useSurface.d.ts +3 -0
  180. package/dist/types/src/ui/hooks/useSurface.d.ts.map +1 -0
  181. package/dist/types/src/ui/index.d.ts +3 -0
  182. package/dist/types/src/ui/index.d.ts.map +1 -0
  183. package/dist/types/src/vite-plugin/composer-plugin.d.ts +18 -0
  184. package/dist/types/src/vite-plugin/composer-plugin.d.ts.map +1 -0
  185. package/dist/types/src/vite-plugin/import-map-plugin.d.ts +16 -0
  186. package/dist/types/src/vite-plugin/import-map-plugin.d.ts.map +1 -0
  187. package/dist/types/src/vite-plugin/index.d.ts +3 -0
  188. package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
  189. package/dist/types/src/vite-plugin/packages.d.ts +7 -0
  190. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
  191. package/dist/types/tsconfig.tsbuildinfo +1 -1
  192. package/moon.yml +20 -6
  193. package/package.json +91 -64
  194. package/src/{cli.ts → cli/cli.ts} +10 -10
  195. package/src/{playground/debug → cli}/index.ts +1 -1
  196. package/src/common/activation-events.ts +44 -0
  197. package/src/common/capabilities.ts +172 -0
  198. package/src/common/index.ts +4 -9
  199. package/src/common/operations.ts +6 -382
  200. package/src/common/translations.ts +0 -12
  201. package/src/context.ts +1 -1
  202. package/src/core/activation-event.ts +5 -2
  203. package/src/core/capability-manager.ts +1 -1
  204. package/src/core/capability.ts +11 -10
  205. package/src/core/index.ts +1 -0
  206. package/src/core/plugin-manager.test.ts +313 -44
  207. package/src/core/plugin-manager.ts +344 -157
  208. package/src/core/plugin.ts +10 -2
  209. package/src/core/url-loader.test.ts +79 -0
  210. package/src/core/url-loader.ts +148 -0
  211. package/src/index.ts +1 -3
  212. package/src/plugin-operation/OperationPlugin.ts +5 -5
  213. package/src/plugin-operation/history/capability.ts +5 -5
  214. package/src/plugin-operation/history/errors.ts +2 -6
  215. package/src/plugin-operation/history/history-tracker.test.ts +36 -42
  216. package/src/plugin-operation/history/undo-mapping.ts +6 -3
  217. package/src/plugin-operation/history/undo-registry.test.ts +3 -3
  218. package/src/plugin-operation/invoker-capability.ts +21 -7
  219. package/src/plugin-operation/meta.ts +1 -1
  220. package/src/plugin-operation/testing.ts +25 -45
  221. package/src/plugin-runtime/RuntimePlugin.ts +4 -4
  222. package/src/plugin-runtime/capability.ts +5 -5
  223. package/src/plugin-runtime/meta.ts +1 -1
  224. package/src/testing/service.ts +6 -6
  225. package/src/testing/withPluginManager.stories.tsx +6 -6
  226. package/src/testing/withPluginManager.tsx +46 -19
  227. package/src/ui/components/App/App.stories.tsx +92 -0
  228. package/src/{react → ui/components/App}/App.tsx +9 -11
  229. package/src/{playground/layout → ui/components/App}/index.ts +1 -1
  230. package/src/{react → ui/components/PluginManager}/PluginManagerContext.stories.tsx +13 -14
  231. package/src/{react → ui/components/PluginManager}/PluginManagerProvider.ts +1 -1
  232. package/src/ui/components/PluginManager/index.ts +5 -0
  233. package/src/{react/Surface.stories.tsx → ui/components/Surface/SurfaceComponent.stories.tsx} +28 -24
  234. package/src/{react/Surface.tsx → ui/components/Surface/SurfaceComponent.tsx} +48 -58
  235. package/src/{react → ui/components/Surface}/SurfaceInfo.tsx +2 -2
  236. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
  237. package/src/ui/components/Surface/context.ts +12 -0
  238. package/src/ui/components/Surface/index.ts +35 -0
  239. package/src/{common/surface.ts → ui/components/Surface/types.ts} +22 -25
  240. package/src/ui/components/index.ts +7 -0
  241. package/src/ui/hooks/index.ts +9 -0
  242. package/src/ui/hooks/useApp.test.tsx +159 -0
  243. package/src/{react → ui/hooks}/useApp.tsx +110 -30
  244. package/src/{react → ui/hooks}/useCapabilities.ts +9 -5
  245. package/src/{react/common.ts → ui/hooks/useSettingsState.ts} +0 -11
  246. package/src/ui/hooks/useSurface.ts +13 -0
  247. package/src/ui/index.ts +6 -0
  248. package/src/vite-plugin/composer-plugin.ts +128 -0
  249. package/src/vite-plugin/import-map-plugin.ts +315 -0
  250. package/src/vite-plugin/index.ts +6 -0
  251. package/src/vite-plugin/packages.ts +29 -0
  252. package/tsconfig.json +4 -28
  253. package/tsconfig.node.json +2 -4
  254. package/typedoc.json +2 -4
  255. package/vitest.config.ts +1 -1
  256. package/dist/lib/browser/app-graph-builder-M2VPYQC6.mjs +0 -149
  257. package/dist/lib/browser/app-graph-builder-M2VPYQC6.mjs.map +0 -7
  258. package/dist/lib/browser/capability-7PCNSWBT.mjs.map +0 -7
  259. package/dist/lib/browser/capability-KP3PFEXD.mjs +0 -31
  260. package/dist/lib/browser/capability-KP3PFEXD.mjs.map +0 -7
  261. package/dist/lib/browser/chunk-6Y7PZV72.mjs.map +0 -7
  262. package/dist/lib/browser/chunk-7IQHKD4U.mjs.map +0 -7
  263. package/dist/lib/browser/chunk-BLQJSGL3.mjs +0 -732
  264. package/dist/lib/browser/chunk-BLQJSGL3.mjs.map +0 -7
  265. package/dist/lib/browser/chunk-FHQTHCX7.mjs +0 -8
  266. package/dist/lib/browser/chunk-FMZN33N4.mjs.map +0 -7
  267. package/dist/lib/browser/chunk-H4WPA7U7.mjs +0 -77
  268. package/dist/lib/browser/chunk-H4WPA7U7.mjs.map +0 -7
  269. package/dist/lib/browser/chunk-PKQT6C53.mjs.map +0 -7
  270. package/dist/lib/browser/chunk-TCLLRCS3.mjs.map +0 -7
  271. package/dist/lib/browser/chunk-XYNO72GQ.mjs +0 -746
  272. package/dist/lib/browser/chunk-XYNO72GQ.mjs.map +0 -7
  273. package/dist/lib/browser/common/index.mjs +0 -38
  274. package/dist/lib/browser/invoker-capability-SZRSTHEH.mjs +0 -32
  275. package/dist/lib/browser/invoker-capability-SZRSTHEH.mjs.map +0 -7
  276. package/dist/lib/browser/operation-resolver-6MP2MYOY.mjs +0 -64
  277. package/dist/lib/browser/operation-resolver-6MP2MYOY.mjs.map +0 -7
  278. package/dist/lib/node-esm/app-graph-builder-LROHGJEM.mjs +0 -150
  279. package/dist/lib/node-esm/app-graph-builder-LROHGJEM.mjs.map +0 -7
  280. package/dist/lib/node-esm/capability-CFLQ2QQU.mjs.map +0 -7
  281. package/dist/lib/node-esm/capability-RCUNM2M7.mjs +0 -32
  282. package/dist/lib/node-esm/capability-RCUNM2M7.mjs.map +0 -7
  283. package/dist/lib/node-esm/chunk-663A54LQ.mjs.map +0 -7
  284. package/dist/lib/node-esm/chunk-6WXBT3EC.mjs +0 -747
  285. package/dist/lib/node-esm/chunk-6WXBT3EC.mjs.map +0 -7
  286. package/dist/lib/node-esm/chunk-7OWSHPYK.mjs.map +0 -7
  287. package/dist/lib/node-esm/chunk-GQEBIGKD.mjs +0 -733
  288. package/dist/lib/node-esm/chunk-GQEBIGKD.mjs.map +0 -7
  289. package/dist/lib/node-esm/chunk-GT6OKM5I.mjs.map +0 -7
  290. package/dist/lib/node-esm/chunk-STMXUEPO.mjs.map +0 -7
  291. package/dist/lib/node-esm/chunk-XR6NMKEP.mjs +0 -78
  292. package/dist/lib/node-esm/chunk-XR6NMKEP.mjs.map +0 -7
  293. package/dist/lib/node-esm/chunk-XYQTBFPA.mjs.map +0 -7
  294. package/dist/lib/node-esm/common/index.mjs +0 -39
  295. package/dist/lib/node-esm/invoker-capability-PNMA5JOS.mjs +0 -33
  296. package/dist/lib/node-esm/invoker-capability-PNMA5JOS.mjs.map +0 -7
  297. package/dist/lib/node-esm/operation-resolver-7YWDMTNU.mjs +0 -65
  298. package/dist/lib/node-esm/operation-resolver-7YWDMTNU.mjs.map +0 -7
  299. package/dist/types/src/cli.d.ts.map +0 -1
  300. package/dist/types/src/common/activation-event.d.ts +0 -66
  301. package/dist/types/src/common/activation-event.d.ts.map +0 -1
  302. package/dist/types/src/common/capability.d.ts +0 -265
  303. package/dist/types/src/common/capability.d.ts.map +0 -1
  304. package/dist/types/src/common/collaboration.d.ts +0 -26
  305. package/dist/types/src/common/collaboration.d.ts.map +0 -1
  306. package/dist/types/src/common/file.d.ts +0 -14
  307. package/dist/types/src/common/file.d.ts.map +0 -1
  308. package/dist/types/src/common/graph.d.ts +0 -21
  309. package/dist/types/src/common/graph.d.ts.map +0 -1
  310. package/dist/types/src/common/plugin.d.ts +0 -201
  311. package/dist/types/src/common/plugin.d.ts.map +0 -1
  312. package/dist/types/src/common/surface.d.ts.map +0 -1
  313. package/dist/types/src/playground/debug/Debug.d.ts +0 -8
  314. package/dist/types/src/playground/debug/Debug.d.ts.map +0 -1
  315. package/dist/types/src/playground/debug/index.d.ts +0 -2
  316. package/dist/types/src/playground/debug/index.d.ts.map +0 -1
  317. package/dist/types/src/playground/debug/plugin.d.ts +0 -3
  318. package/dist/types/src/playground/debug/plugin.d.ts.map +0 -1
  319. package/dist/types/src/playground/generator/Main.d.ts +0 -8
  320. package/dist/types/src/playground/generator/Main.d.ts.map +0 -1
  321. package/dist/types/src/playground/generator/Toolbar.d.ts +0 -8
  322. package/dist/types/src/playground/generator/Toolbar.d.ts.map +0 -1
  323. package/dist/types/src/playground/generator/generator.d.ts +0 -19
  324. package/dist/types/src/playground/generator/generator.d.ts.map +0 -1
  325. package/dist/types/src/playground/generator/index.d.ts +0 -3
  326. package/dist/types/src/playground/generator/index.d.ts.map +0 -1
  327. package/dist/types/src/playground/generator/plugin.d.ts +0 -3
  328. package/dist/types/src/playground/generator/plugin.d.ts.map +0 -1
  329. package/dist/types/src/playground/layout/Layout.d.ts +0 -10
  330. package/dist/types/src/playground/layout/Layout.d.ts.map +0 -1
  331. package/dist/types/src/playground/layout/index.d.ts +0 -2
  332. package/dist/types/src/playground/layout/index.d.ts.map +0 -1
  333. package/dist/types/src/playground/layout/plugin.d.ts +0 -3
  334. package/dist/types/src/playground/layout/plugin.d.ts.map +0 -1
  335. package/dist/types/src/playground/logger/Toolbar.d.ts +0 -8
  336. package/dist/types/src/playground/logger/Toolbar.d.ts.map +0 -1
  337. package/dist/types/src/playground/logger/index.d.ts +0 -2
  338. package/dist/types/src/playground/logger/index.d.ts.map +0 -1
  339. package/dist/types/src/playground/logger/plugin.d.ts +0 -3
  340. package/dist/types/src/playground/logger/plugin.d.ts.map +0 -1
  341. package/dist/types/src/playground/logger/schema.d.ts +0 -27
  342. package/dist/types/src/playground/logger/schema.d.ts.map +0 -1
  343. package/dist/types/src/playground/playground.stories.d.ts +0 -11
  344. package/dist/types/src/playground/playground.stories.d.ts.map +0 -1
  345. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +0 -3
  346. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +0 -1
  347. package/dist/types/src/plugin-settings/actions.d.ts +0 -61
  348. package/dist/types/src/plugin-settings/actions.d.ts.map +0 -1
  349. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -6
  350. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  351. package/dist/types/src/plugin-settings/index.d.ts +0 -3
  352. package/dist/types/src/plugin-settings/index.d.ts.map +0 -1
  353. package/dist/types/src/plugin-settings/meta.d.ts +0 -3
  354. package/dist/types/src/plugin-settings/meta.d.ts.map +0 -1
  355. package/dist/types/src/plugin-settings/operation-resolver.d.ts +0 -6
  356. package/dist/types/src/plugin-settings/operation-resolver.d.ts.map +0 -1
  357. package/dist/types/src/plugin-settings/translations.d.ts +0 -11
  358. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  359. package/dist/types/src/react/App.d.ts.map +0 -1
  360. package/dist/types/src/react/App.stories.d.ts.map +0 -1
  361. package/dist/types/src/react/DefaultFallback.d.ts +0 -8
  362. package/dist/types/src/react/DefaultFallback.d.ts.map +0 -1
  363. package/dist/types/src/react/ErrorBoundary.d.ts +0 -30
  364. package/dist/types/src/react/ErrorBoundary.d.ts.map +0 -1
  365. package/dist/types/src/react/PluginManagerContext.stories.d.ts.map +0 -1
  366. package/dist/types/src/react/PluginManagerProvider.d.ts.map +0 -1
  367. package/dist/types/src/react/Surface.d.ts +0 -14
  368. package/dist/types/src/react/Surface.d.ts.map +0 -1
  369. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  370. package/dist/types/src/react/SurfaceInfo.d.ts.map +0 -1
  371. package/dist/types/src/react/common.d.ts.map +0 -1
  372. package/dist/types/src/react/index.d.ts +0 -9
  373. package/dist/types/src/react/index.d.ts.map +0 -1
  374. package/dist/types/src/react/types.d.ts +0 -12
  375. package/dist/types/src/react/types.d.ts.map +0 -1
  376. package/dist/types/src/react/useApp.d.ts.map +0 -1
  377. package/dist/types/src/react/useCapabilities.d.ts.map +0 -1
  378. package/dist/types/src/react/useLoading.d.ts.map +0 -1
  379. package/dist/types/src/react/useOperationResolver.d.ts +0 -19
  380. package/dist/types/src/react/useOperationResolver.d.ts.map +0 -1
  381. package/src/common/activation-event.ts +0 -99
  382. package/src/common/capability.ts +0 -343
  383. package/src/common/collaboration.ts +0 -31
  384. package/src/common/file.ts +0 -22
  385. package/src/common/graph.ts +0 -30
  386. package/src/common/plugin.ts +0 -364
  387. package/src/playground/debug/Debug.tsx +0 -49
  388. package/src/playground/debug/plugin.ts +0 -16
  389. package/src/playground/generator/Main.tsx +0 -80
  390. package/src/playground/generator/Toolbar.tsx +0 -57
  391. package/src/playground/generator/generator.ts +0 -48
  392. package/src/playground/generator/index.ts +0 -6
  393. package/src/playground/generator/plugin.ts +0 -21
  394. package/src/playground/layout/Layout.tsx +0 -37
  395. package/src/playground/layout/plugin.ts +0 -18
  396. package/src/playground/logger/Toolbar.tsx +0 -33
  397. package/src/playground/logger/index.ts +0 -5
  398. package/src/playground/logger/plugin.ts +0 -42
  399. package/src/playground/logger/schema.ts +0 -22
  400. package/src/playground/playground.stories.tsx +0 -54
  401. package/src/plugin-settings/SettingsPlugin.ts +0 -19
  402. package/src/plugin-settings/actions.ts +0 -64
  403. package/src/plugin-settings/app-graph-builder.ts +0 -140
  404. package/src/plugin-settings/index.ts +0 -6
  405. package/src/plugin-settings/meta.ts +0 -10
  406. package/src/plugin-settings/operation-resolver.ts +0 -55
  407. package/src/plugin-settings/translations.ts +0 -19
  408. package/src/react/App.stories.tsx +0 -63
  409. package/src/react/DefaultFallback.tsx +0 -26
  410. package/src/react/ErrorBoundary.tsx +0 -56
  411. package/src/react/index.ts +0 -14
  412. package/src/react/types.ts +0 -27
  413. package/src/react/useOperationResolver.ts +0 -40
  414. /package/dist/lib/{node-esm/react/index.mjs.map → browser/chunk-RFSO3JRG.mjs.map} +0 -0
  415. /package/dist/lib/{node-esm/common/index.mjs.map → browser/common/activation-events.mjs.map} +0 -0
  416. /package/dist/lib/browser/{react/index.mjs.map → common/capabilities.mjs.map} +0 -0
  417. /package/dist/lib/browser/{common/index.mjs.map → core/url-loader.mjs.map} +0 -0
  418. /package/dist/types/src/{react → ui/components/PluginManager}/PluginManagerContext.stories.d.ts +0 -0
  419. /package/dist/types/src/{react → ui/components/Surface}/SurfaceInfo.d.ts +0 -0
  420. /package/dist/types/src/{react → ui/hooks}/useLoading.d.ts +0 -0
  421. /package/src/{react → ui/hooks}/useLoading.tsx +0 -0
@@ -0,0 +1,79 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { assert, describe, it } from '@effect/vitest';
6
+ import * as Effect from 'effect/Effect';
7
+
8
+ import * as Plugin from './plugin';
9
+ import * as UrlLoader from './url-loader';
10
+
11
+ const testMeta = { id: 'org.dxos.plugin.test', name: 'Test' };
12
+
13
+ describe('UrlLoader', () => {
14
+ describe('make', () => {
15
+ it.effect('resolves built-in plugins by meta.id', () =>
16
+ Effect.gen(function* () {
17
+ const testPlugin = Plugin.make(Plugin.define(testMeta))();
18
+ const loader = UrlLoader.make([testPlugin]);
19
+ const result = yield* loader(testMeta.id);
20
+ assert.strictEqual(result.meta.id, testMeta.id);
21
+ }),
22
+ );
23
+
24
+ it.effect('fails for unknown non-URL locator', () =>
25
+ Effect.gen(function* () {
26
+ const loader = UrlLoader.make([]);
27
+ const exit = yield* Effect.exit(loader('not-a-url'));
28
+ assert.isTrue(exit._tag === 'Failure');
29
+ }),
30
+ );
31
+ });
32
+
33
+ describe('preload', () => {
34
+ it('returns empty array when storage has no entries', async ({ expect }) => {
35
+ const storage: UrlLoader.Storage = {
36
+ get: () => null,
37
+ set: () => {},
38
+ };
39
+ const result = await UrlLoader.preload({ storage });
40
+ expect(result).toEqual([]);
41
+ });
42
+
43
+ it('returns empty array when storage has invalid JSON', async ({ expect }) => {
44
+ const storage: UrlLoader.Storage = {
45
+ get: () => '{{invalid json',
46
+ set: () => {},
47
+ };
48
+ const result = await UrlLoader.preload({ storage });
49
+ expect(result).toEqual([]);
50
+ });
51
+
52
+ it('returns empty array when storage contains null', async ({ expect }) => {
53
+ const storage: UrlLoader.Storage = {
54
+ get: () => 'null',
55
+ set: () => {},
56
+ };
57
+ const result = await UrlLoader.preload({ storage });
58
+ expect(result).toEqual([]);
59
+ });
60
+
61
+ it('returns empty array when storage contains an object', async ({ expect }) => {
62
+ const storage: UrlLoader.Storage = {
63
+ get: () => '{}',
64
+ set: () => {},
65
+ };
66
+ const result = await UrlLoader.preload({ storage });
67
+ expect(result).toEqual([]);
68
+ });
69
+
70
+ it('returns empty array when entries are missing required fields', async ({ expect }) => {
71
+ const storage: UrlLoader.Storage = {
72
+ get: () => '[{"title":"no url"}]',
73
+ set: () => {},
74
+ };
75
+ const result = await UrlLoader.preload({ storage });
76
+ expect(result).toEqual([]);
77
+ });
78
+ });
79
+ });
@@ -0,0 +1,148 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { log } from '@dxos/log';
8
+
9
+ import * as Plugin from './plugin';
10
+
11
+ const DEFAULT_KEY = 'org.dxos.composer.remote-plugins';
12
+
13
+ /**
14
+ * Abstraction over key-value storage (defaults to localStorage).
15
+ */
16
+ export type Storage = {
17
+ get(key: string): string | null;
18
+ set(key: string, value: string): void;
19
+ };
20
+
21
+ /**
22
+ * Options for configuring the URL loader.
23
+ */
24
+ export type Options = {
25
+ storage?: Storage;
26
+ key?: string;
27
+ };
28
+
29
+ type RemotePluginEntry = { id: string; url: string };
30
+
31
+ const defaultStorage = (): Storage => ({
32
+ get: (key) => localStorage.getItem(key),
33
+ set: (key, value) => localStorage.setItem(key, value),
34
+ });
35
+
36
+ const getPersistedRemotePlugins = (storage: Storage, key: string): RemotePluginEntry[] => {
37
+ try {
38
+ const parsed: unknown = JSON.parse(storage.get(key) ?? '[]');
39
+ if (!Array.isArray(parsed)) {
40
+ return [];
41
+ }
42
+ return parsed.filter(
43
+ (entry): entry is RemotePluginEntry =>
44
+ typeof entry === 'object' && entry !== null && typeof entry.id === 'string' && typeof entry.url === 'string',
45
+ );
46
+ } catch {
47
+ return [];
48
+ }
49
+ };
50
+
51
+ const persistRemotePlugin = (storage: Storage, key: string, entry: RemotePluginEntry): void => {
52
+ try {
53
+ const entries = getPersistedRemotePlugins(storage, key).filter((existing) => existing.id !== entry.id);
54
+ entries.push(entry);
55
+ storage.set(key, JSON.stringify(entries));
56
+ } catch (error) {
57
+ log.warn('failed to persist remote plugin entry', { entry, error });
58
+ }
59
+ };
60
+
61
+ const isUrl = (locator: string): boolean => {
62
+ try {
63
+ const url = new URL(locator);
64
+ return url.protocol === 'http:' || url.protocol === 'https:';
65
+ } catch {
66
+ return false;
67
+ }
68
+ };
69
+
70
+ const normalizePluginExport = (mod: Record<string, unknown>): Plugin.Plugin => {
71
+ const exported = mod.default;
72
+ if (Plugin.isPlugin(exported)) {
73
+ return exported;
74
+ }
75
+ if (typeof exported === 'function') {
76
+ const result = (exported as () => unknown)();
77
+ if (Plugin.isPlugin(result)) {
78
+ return result;
79
+ }
80
+ }
81
+ throw new Error('Remote module default export is not a Plugin or a zero-arg plugin factory.');
82
+ };
83
+
84
+ const loadRemotePlugin = async (url: string): Promise<Plugin.Plugin> => {
85
+ log.info('loading remote plugin', { url });
86
+ const mod = await import(/* @vite-ignore */ url);
87
+ const plugin = normalizePluginExport(mod);
88
+ if (!plugin.meta.id || !plugin.meta.name) {
89
+ throw new Error(`Remote plugin at ${url} is missing required meta.id or meta.name.`);
90
+ }
91
+ return plugin;
92
+ };
93
+
94
+ /**
95
+ * Preloads previously persisted remote plugins from storage.
96
+ */
97
+ export const preload = async (options: Options = {}): Promise<Plugin.Plugin[]> => {
98
+ const storage = options.storage ?? defaultStorage();
99
+ const key = options.key ?? DEFAULT_KEY;
100
+
101
+ const entries = getPersistedRemotePlugins(storage, key);
102
+ if (entries.length === 0) {
103
+ return [];
104
+ }
105
+ log.info('preloading remote plugins', { count: entries.length });
106
+ const results = await Promise.allSettled(entries.map((entry) => loadRemotePlugin(entry.url)));
107
+ const plugins: Plugin.Plugin[] = [];
108
+ for (let index = 0; index < results.length; index++) {
109
+ const result = results[index];
110
+ if (result.status === 'fulfilled') {
111
+ plugins.push(result.value);
112
+ } else {
113
+ log.warn('failed to preload remote plugin', { entry: entries[index], error: result.reason });
114
+ }
115
+ }
116
+ return plugins;
117
+ };
118
+
119
+ /**
120
+ * Creates a plugin loader that resolves built-in plugins by ID or loads remote plugins from URLs.
121
+ */
122
+ export const make = (builtinPlugins: Plugin.Plugin[], options: Options = {}) => {
123
+ const storage = options.storage ?? defaultStorage();
124
+ const key = options.key ?? DEFAULT_KEY;
125
+
126
+ return (locator: string): Effect.Effect<Plugin.Plugin, Error> =>
127
+ Effect.gen(function* () {
128
+ const builtin = builtinPlugins.find((plugin) => plugin.meta.id === locator);
129
+ if (builtin) {
130
+ return builtin;
131
+ }
132
+ if (!isUrl(locator)) {
133
+ return yield* Effect.fail(new Error(`Plugin not found and locator is not a URL: ${locator}`));
134
+ }
135
+ const plugin = yield* Effect.tryPromise({
136
+ try: () => loadRemotePlugin(locator),
137
+ catch: (error) => new Error(`Failed to load remote plugin from ${locator}: ${error}`),
138
+ });
139
+ const duplicate = builtinPlugins.find((existing) => existing.meta.id === plugin.meta.id);
140
+ if (duplicate) {
141
+ return yield* Effect.fail(
142
+ new Error(`Remote plugin ${plugin.meta.id} conflicts with built-in plugin of the same id.`),
143
+ );
144
+ }
145
+ persistRemotePlugin(storage, key, { id: plugin.meta.id, url: locator });
146
+ return plugin;
147
+ });
148
+ };
package/src/index.ts CHANGED
@@ -2,10 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './cli';
6
- export * as Common from './common';
5
+ export * from './common';
7
6
  export * from './context';
8
7
  export * from './core';
9
8
  export * from './plugin-operation';
10
9
  export * from './plugin-runtime';
11
- export * from './plugin-settings';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import * as Common from '../common';
5
+ import { ActivationEvents } from '../common';
6
6
  import { Capability, Plugin } from '../core';
7
7
 
8
8
  import { meta } from './meta';
@@ -12,13 +12,13 @@ const HistoryCapabilities = Capability.lazy('HistoryCapabilities', () => import(
12
12
 
13
13
  export const OperationPlugin = Plugin.define(meta).pipe(
14
14
  Plugin.addModule({
15
- activatesOn: Common.ActivationEvent.ManagedRuntimeReady,
16
- activatesBefore: [Common.ActivationEvent.SetupOperationResolver],
17
- activatesAfter: [Common.ActivationEvent.OperationInvokerReady],
15
+ activatesOn: ActivationEvents.ManagedRuntimeReady,
16
+ activatesBefore: [ActivationEvents.SetupOperationHandler],
17
+ activatesAfter: [ActivationEvents.OperationInvokerReady],
18
18
  activate: OperationInvoker,
19
19
  }),
20
20
  Plugin.addModule({
21
- activatesOn: Common.ActivationEvent.OperationInvokerReady,
21
+ activatesOn: ActivationEvents.OperationInvokerReady,
22
22
  activate: HistoryCapabilities,
23
23
  }),
24
24
  Plugin.make,
@@ -6,7 +6,7 @@ import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { type OperationInvoker } from '@dxos/operation';
8
8
 
9
- import * as Common from '../../common';
9
+ import { Capabilities } from '../../common';
10
10
  import { Capability } from '../../core';
11
11
 
12
12
  import * as HistoryTracker from './history-tracker';
@@ -22,16 +22,16 @@ export default Capability.makeModule(
22
22
  const capabilities = yield* Capability.Service;
23
23
 
24
24
  // Create UndoRegistry.
25
- const undoRegistry = UndoRegistry.make(() => capabilities.getAll(Common.Capability.UndoMapping).flat());
25
+ const undoRegistry = UndoRegistry.make(() => capabilities.getAll(Capabilities.UndoMapping).flat());
26
26
 
27
27
  // Create HistoryTracker (depends on UndoRegistry and OperationInvoker).
28
- const invoker = yield* Capability.get(Common.Capability.OperationInvoker);
28
+ const invoker = yield* Capability.get(Capabilities.OperationInvoker);
29
29
  // Cast to internal type - the factory always returns OperationInvokerInternal.
30
30
  const historyTracker = HistoryTracker.make(invoker as OperationInvoker.OperationInvokerInternal, undoRegistry);
31
31
 
32
32
  return [
33
- Capability.contributes(Common.Capability.UndoRegistry, undoRegistry),
34
- Capability.contributes(Common.Capability.HistoryTracker, historyTracker),
33
+ Capability.contributes(Capabilities.UndoRegistry, undoRegistry),
34
+ Capability.contributes(Capabilities.HistoryTracker, historyTracker),
35
35
  ];
36
36
  }),
37
37
  );
@@ -2,10 +2,6 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { OperationError } from '@dxos/operation';
5
+ import { BaseError } from '@dxos/errors';
6
6
 
7
- export class EmptyHistoryError extends OperationError {
8
- constructor() {
9
- super('EMPTY_HISTORY', 'Cannot undo: history is empty.');
10
- }
11
- }
7
+ export class EmptyHistoryError extends BaseError.extend('EmptyHistoryError', 'Cannot undo: history is empty.') {}
@@ -5,10 +5,14 @@
5
5
  import { it } from '@effect/vitest';
6
6
  import * as Effect from 'effect/Effect';
7
7
  import * as Fiber from 'effect/Fiber';
8
+ import * as Layer from 'effect/Layer';
9
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
8
10
  import * as TestClock from 'effect/TestClock';
9
11
  import { describe, expect } from 'vitest';
10
12
 
11
- import { OperationInvoker, OperationResolver } from '@dxos/operation';
13
+ import { Operation, OperationInvoker } from '@dxos/operation';
14
+
15
+ const testRuntime = ManagedRuntime.make(Layer.empty) as unknown as ManagedRuntime.ManagedRuntime<any, any>;
12
16
 
13
17
  import { UndoOperation } from '../../common';
14
18
  import {
@@ -35,7 +39,7 @@ describe('HistoryTracker', () => {
35
39
  deriveContext: (_input, output) => ({ value: output.value }),
36
40
  });
37
41
 
38
- const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]));
42
+ const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]), testRuntime);
39
43
  const undoRegistry = UndoRegistry.make(() => [undoMapping]);
40
44
  const tracker = HistoryTracker.make(invoker, undoRegistry);
41
45
 
@@ -55,7 +59,7 @@ describe('HistoryTracker', () => {
55
59
 
56
60
  it.effect('does not track operations without undo mapping', () =>
57
61
  Effect.gen(function* () {
58
- const invoker = OperationInvoker.make(() => Effect.succeed([toStringHandler]));
62
+ const invoker = OperationInvoker.make(() => Effect.succeed([toStringHandler]), testRuntime);
59
63
  const undoRegistry = UndoRegistry.make(() => []);
60
64
  const tracker = HistoryTracker.make(invoker, undoRegistry);
61
65
  const collector = yield* createEventCollector(invoker);
@@ -81,15 +85,12 @@ describe('HistoryTracker', () => {
81
85
  });
82
86
 
83
87
  let halveWasCalled = false;
84
- const trackingHalveHandler = OperationResolver.make({
85
- operation: HalveCompute,
86
- handler: (data) => {
87
- halveWasCalled = true;
88
- return Effect.succeed({ value: data.value / 2 });
89
- },
88
+ const trackingHalveHandler = Operation.withHandler(HalveCompute, (data) => {
89
+ halveWasCalled = true;
90
+ return Effect.succeed({ value: data.value / 2 });
90
91
  });
91
92
 
92
- const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, trackingHalveHandler]));
93
+ const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, trackingHalveHandler]), testRuntime);
93
94
  const undoRegistry = UndoRegistry.make(() => [undoMapping]);
94
95
  const tracker = HistoryTracker.make(invoker, undoRegistry);
95
96
 
@@ -117,7 +118,7 @@ describe('HistoryTracker', () => {
117
118
  deriveContext: (_input, output) => ({ value: output.value }),
118
119
  });
119
120
 
120
- const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]));
121
+ const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]), testRuntime);
121
122
  const undoRegistry = UndoRegistry.make(() => [undoMapping]);
122
123
  const tracker = HistoryTracker.make(invoker, undoRegistry);
123
124
  const collector = yield* createEventCollector(invoker);
@@ -152,15 +153,12 @@ describe('HistoryTracker', () => {
152
153
  });
153
154
 
154
155
  const halveInputs: number[] = [];
155
- const trackingHalveHandler = OperationResolver.make({
156
- operation: HalveCompute,
157
- handler: (data) => {
158
- halveInputs.push(data.value);
159
- return Effect.succeed({ value: data.value / 2 });
160
- },
156
+ const trackingHalveHandler = Operation.withHandler(HalveCompute, (data) => {
157
+ halveInputs.push(data.value);
158
+ return Effect.succeed({ value: data.value / 2 });
161
159
  });
162
160
 
163
- const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, trackingHalveHandler]));
161
+ const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, trackingHalveHandler]), testRuntime);
164
162
  const undoRegistry = UndoRegistry.make(() => [undoMapping]);
165
163
  const tracker = HistoryTracker.make(invoker, undoRegistry);
166
164
  const collector = yield* createEventCollector(invoker);
@@ -194,7 +192,7 @@ describe('HistoryTracker', () => {
194
192
 
195
193
  it.effect('undo on empty history returns error', () =>
196
194
  Effect.gen(function* () {
197
- const invoker = OperationInvoker.make(() => Effect.succeed([]));
195
+ const invoker = OperationInvoker.make(() => Effect.succeed([]), testRuntime);
198
196
  const undoRegistry = UndoRegistry.make(() => []);
199
197
  const tracker = HistoryTracker.make(invoker, undoRegistry);
200
198
 
@@ -208,7 +206,7 @@ describe('HistoryTracker', () => {
208
206
 
209
207
  it.effect('fires ShowUndo operation when undoable operation is tracked', () =>
210
208
  Effect.gen(function* () {
211
- const testMessage: [string, { ns: string }] = ['test undo message', { ns: 'test' }];
209
+ const testMessage: [string, { ns: string }] = ['test-undo.message', { ns: 'test' }];
212
210
  const undoMapping = UndoMapping.make({
213
211
  operation: Compute,
214
212
  inverse: HalveCompute,
@@ -218,17 +216,15 @@ describe('HistoryTracker', () => {
218
216
 
219
217
  let showUndoWasCalled = false;
220
218
  let showUndoMessage: unknown = undefined;
221
- const showUndoHandler = OperationResolver.make({
222
- operation: UndoOperation.ShowUndo,
223
- handler: (input) => {
224
- showUndoWasCalled = true;
225
- showUndoMessage = input.message;
226
- return Effect.succeed(undefined);
227
- },
219
+ const showUndoHandler = Operation.withHandler(UndoOperation.ShowUndo, (input) => {
220
+ showUndoWasCalled = true;
221
+ showUndoMessage = input.message;
222
+ return Effect.succeed(undefined);
228
223
  });
229
224
 
230
- const invoker = OperationInvoker.make(() =>
231
- Effect.succeed([computeHandler, halveComputeHandler, showUndoHandler]),
225
+ const invoker = OperationInvoker.make(
226
+ () => Effect.succeed([computeHandler, halveComputeHandler, showUndoHandler]),
227
+ testRuntime,
232
228
  );
233
229
  const undoRegistry = UndoRegistry.make(() => [undoMapping]);
234
230
  const tracker = HistoryTracker.make(invoker, undoRegistry);
@@ -254,7 +250,7 @@ describe('HistoryTracker', () => {
254
250
  Effect.gen(function* () {
255
251
  // Dynamic message that depends on input/output.
256
252
  const dynamicMessage = (input: { value: number }, output: { value: number }): [string, { ns: string }] => [
257
- `computed ${input.value} to ${output.value}`,
253
+ `computed-${input.value}-to-${output.value}`,
258
254
  { ns: 'test' },
259
255
  ];
260
256
  const undoMapping = UndoMapping.make({
@@ -266,17 +262,15 @@ describe('HistoryTracker', () => {
266
262
 
267
263
  let showUndoWasCalled = false;
268
264
  let showUndoMessage: unknown = undefined;
269
- const showUndoHandler = OperationResolver.make({
270
- operation: UndoOperation.ShowUndo,
271
- handler: (input) => {
272
- showUndoWasCalled = true;
273
- showUndoMessage = input.message;
274
- return Effect.succeed(undefined);
275
- },
265
+ const showUndoHandler = Operation.withHandler(UndoOperation.ShowUndo, (input) => {
266
+ showUndoWasCalled = true;
267
+ showUndoMessage = input.message;
268
+ return Effect.succeed(undefined);
276
269
  });
277
270
 
278
- const invoker = OperationInvoker.make(() =>
279
- Effect.succeed([computeHandler, halveComputeHandler, showUndoHandler]),
271
+ const invoker = OperationInvoker.make(
272
+ () => Effect.succeed([computeHandler, halveComputeHandler, showUndoHandler]),
273
+ testRuntime,
280
274
  );
281
275
  const undoRegistry = UndoRegistry.make(() => [undoMapping]);
282
276
  const tracker = HistoryTracker.make(invoker, undoRegistry);
@@ -295,7 +289,7 @@ describe('HistoryTracker', () => {
295
289
  yield* waitUntil(() => showUndoWasCalled);
296
290
  expect(showUndoWasCalled).toBe(true);
297
291
  // Compute 2 * 2 = 4, so message should be 'computed 2 to 4'.
298
- expect(showUndoMessage).toEqual(['computed 2 to 4', { ns: 'test' }]);
292
+ expect(showUndoMessage).toEqual(['computed-2-to-4', { ns: 'test' }]);
299
293
  }),
300
294
  );
301
295
 
@@ -314,7 +308,7 @@ describe('HistoryTracker', () => {
314
308
  },
315
309
  });
316
310
 
317
- const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]));
311
+ const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]), testRuntime);
318
312
  const undoRegistry = UndoRegistry.make(() => [undoMapping]);
319
313
  const tracker = HistoryTracker.make(invoker, undoRegistry);
320
314
  const collector = yield* createEventCollector(invoker);
@@ -352,7 +346,7 @@ describe('HistoryTracker', () => {
352
346
  },
353
347
  });
354
348
 
355
- const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]));
349
+ const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]), testRuntime);
356
350
  const undoRegistry = UndoRegistry.make(() => [undoMapping]);
357
351
  const tracker = HistoryTracker.make(invoker, undoRegistry);
358
352
  const collector = yield* createEventCollector(invoker);
@@ -4,7 +4,10 @@
4
4
 
5
5
  import type { Operation } from '@dxos/operation';
6
6
 
7
- import type { Label } from '../../common/translations';
7
+ /**
8
+ * Label type for translatable text (canonical definition in @dxos/app-toolkit).
9
+ */
10
+ type Label = string | [string, { ns: string; count?: number; defaultValue?: string }];
8
11
 
9
12
  /**
10
13
  * Extract the input type from an OperationDefinition.
@@ -95,7 +98,7 @@ export interface UndoMappingProps<
95
98
  * thread: output.thread,
96
99
  * anchor: output.anchor,
97
100
  * }),
98
- * message: ['thread deleted label', { ns: 'plugin-thread' }],
101
+ * message: ['thread deleted label', { ns: '@dxos/plugin-thread' }],
99
102
  * });
100
103
  *
101
104
  * // Dynamic message based on input/output
@@ -106,7 +109,7 @@ export interface UndoMappingProps<
106
109
  * message: (input, _output) =>
107
110
  * input.objects.length === 1
108
111
  * ? ['object deleted label', { ns: getTypename(input.objects[0]) }]
109
- * : ['objects deleted label', { ns: 'plugin-space' }],
112
+ * : ['objects deleted label', { ns: '@dxos/plugin-space' }],
110
113
  * });
111
114
  * ```
112
115
  */
@@ -52,18 +52,18 @@ describe('resolveMessage', () => {
52
52
  });
53
53
 
54
54
  test('returns static label as-is', ({ expect }) => {
55
- const staticMessage: [string, { ns: string }] = ['test message', { ns: 'test' }];
55
+ const staticMessage: [string, { ns: string }] = ['test.message', { ns: 'test' }];
56
56
  const result = UndoMapping.resolveMessage(staticMessage, { value: 1 }, { value: 2 });
57
57
  expect(result).toEqual(staticMessage);
58
58
  });
59
59
 
60
60
  test('calls function message with input and output', ({ expect }) => {
61
61
  const messageFunc = (input: { value: number }, output: { value: number }): [string, { ns: string }] => [
62
- `input: ${input.value}, output: ${output.value}`,
62
+ `input-${input.value}-output-${output.value}`,
63
63
  { ns: 'test' },
64
64
  ];
65
65
  const result = UndoMapping.resolveMessage(messageFunc, { value: 5 }, { value: 10 });
66
- expect(result).toEqual(['input: 5, output: 10', { ns: 'test' }]);
66
+ expect(result).toEqual(['input-5-output-10', { ns: 'test' }]);
67
67
  });
68
68
 
69
69
  test('returns string label as-is', ({ expect }) => {
@@ -4,9 +4,9 @@
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
- import { OperationInvoker } from '@dxos/operation';
7
+ import { OperationHandlerSet, OperationInvoker } from '@dxos/operation';
8
8
 
9
- import * as Common from '../common';
9
+ import { ActivationEvents, Capabilities } from '../common';
10
10
  import { Capability, Plugin } from '../core';
11
11
 
12
12
  //
@@ -20,21 +20,35 @@ export default Capability.makeModule(
20
20
  const pluginManager = yield* Plugin.Service;
21
21
 
22
22
  // Get the ManagedRuntime capability (should be available since we activate after ManagedRuntimeReady).
23
- const managedRuntimes = yield* Capability.getAll(Common.Capability.ManagedRuntime);
24
- const managedRuntime = managedRuntimes.length > 0 ? managedRuntimes[0] : undefined;
23
+ const managedRuntime = yield* Capability.get(Capabilities.ManagedRuntime);
24
+
25
+ // Cache the merged handler promise to prevent concurrent module loading.
26
+ // Multiple Effects can invoke getHandlers simultaneously; without caching each
27
+ // creates a new merge() which triggers parallel dynamic imports that race in
28
+ // WebKit's module evaluator, causing TDZ errors on export default bindings.
29
+ let cachedSets: readonly OperationHandlerSet.OperationHandlerSet[] | undefined;
30
+ let cachedHandlers: ReturnType<OperationHandlerSet.OperationHandlerSet['getHandlers']> | undefined;
25
31
 
26
32
  const invoker = OperationInvoker.make(
27
33
  () =>
28
34
  Effect.gen(function* () {
29
- yield* Plugin.activate(Common.ActivationEvent.SetupOperationResolver);
30
- return (yield* Capability.getAll(Common.Capability.OperationResolver)).flat();
35
+ yield* Plugin.activate(ActivationEvents.SetupOperationHandler);
36
+ const sets = yield* Capability.getAll(Capabilities.OperationHandler);
37
+
38
+ if (sets !== cachedSets) {
39
+ cachedSets = sets;
40
+ cachedHandlers = OperationHandlerSet.merge(...sets).getHandlers();
41
+ }
42
+
43
+ return yield* Effect.promise(() => cachedHandlers!);
31
44
  }).pipe(
32
45
  Effect.provideService(Capability.Service, capabilityManager),
33
46
  Effect.provideService(Plugin.Service, pluginManager),
47
+ Effect.orDie,
34
48
  ),
35
49
  managedRuntime,
36
50
  );
37
51
 
38
- return Capability.contributes(Common.Capability.OperationInvoker, invoker);
52
+ return Capability.contributes(Capabilities.OperationInvoker, invoker);
39
53
  }),
40
54
  );
@@ -5,7 +5,7 @@
5
5
  import { type Plugin } from '../core';
6
6
 
7
7
  export const meta: Plugin.Meta = {
8
- id: 'dxos.org/plugin/operation',
8
+ id: 'org.dxos.plugin.operation',
9
9
  name: 'Operation Plugin',
10
10
  description: 'Provides operation invocation, undo registry, and history tracking.',
11
11
  };