@dxos/app-framework 0.8.4-main.40e3dcdf1b → 0.8.4-main.43cb759274

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 (389) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/browser/{capability-LF3OXSCV.mjs → capability-JCUNWZ66.mjs} +12 -11
  4. package/dist/lib/browser/capability-JCUNWZ66.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-WEBSGU5L.mjs → chunk-2ZIYRDAF.mjs} +20 -5
  6. package/dist/lib/browser/chunk-2ZIYRDAF.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-5GY3YOEL.mjs +28 -0
  8. package/dist/lib/browser/chunk-5GY3YOEL.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-272IPLHQ.mjs → chunk-66IXTIVK.mjs} +3 -2
  10. package/dist/lib/browser/chunk-66IXTIVK.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-7MBI66M7.mjs +587 -0
  12. package/dist/lib/browser/chunk-7MBI66M7.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-BMLCIFZW.mjs +1467 -0
  14. package/dist/lib/browser/chunk-BMLCIFZW.mjs.map +7 -0
  15. package/dist/lib/browser/{chunk-7M4467QR.mjs → chunk-DC3WRPBV.mjs} +100 -18
  16. package/dist/lib/browser/chunk-DC3WRPBV.mjs.map +7 -0
  17. package/dist/lib/browser/{chunk-JGWCBVKJ.mjs → chunk-E5DTDNDY.mjs} +28 -55
  18. package/dist/lib/browser/chunk-E5DTDNDY.mjs.map +7 -0
  19. package/dist/lib/browser/{chunk-TGX63LTL.mjs → chunk-FJ4765WW.mjs} +1 -1
  20. package/dist/lib/browser/{chunk-TGX63LTL.mjs.map → chunk-FJ4765WW.mjs.map} +2 -2
  21. package/dist/lib/browser/chunk-FO3IYSLV.mjs +68 -0
  22. package/dist/lib/browser/chunk-FO3IYSLV.mjs.map +7 -0
  23. package/dist/lib/browser/{chunk-YNFPIQGB.mjs → chunk-IW44C7UL.mjs} +9 -2
  24. package/dist/lib/browser/chunk-IW44C7UL.mjs.map +7 -0
  25. package/dist/lib/browser/chunk-KZUDO43J.mjs +422 -0
  26. package/dist/lib/browser/chunk-KZUDO43J.mjs.map +7 -0
  27. package/dist/lib/browser/chunk-Q2GLJTVV.mjs +12 -0
  28. package/dist/lib/browser/chunk-Q2GLJTVV.mjs.map +7 -0
  29. package/dist/lib/browser/chunk-VBG5F5UF.mjs +476 -0
  30. package/dist/lib/browser/chunk-VBG5F5UF.mjs.map +7 -0
  31. package/dist/lib/browser/cli/index.mjs +15 -30
  32. package/dist/lib/browser/cli/index.mjs.map +3 -3
  33. package/dist/lib/browser/common/activation-events.mjs +11 -14
  34. package/dist/lib/browser/common/capabilities.mjs +19 -8
  35. package/dist/lib/browser/core/activation-event.mjs +1 -1
  36. package/dist/lib/browser/core/capability.mjs +5 -1
  37. package/dist/lib/browser/core/plugin-manager.mjs +8 -4
  38. package/dist/lib/browser/core/plugin.mjs +18 -4
  39. package/dist/lib/browser/core/url-loader.mjs +24 -0
  40. package/dist/lib/browser/index.mjs +51 -54
  41. package/dist/lib/browser/index.mjs.map +4 -4
  42. package/dist/lib/browser/meta.json +1 -1
  43. package/dist/lib/browser/process-manager-capability-4FUA4TRP.mjs +89 -0
  44. package/dist/lib/browser/process-manager-capability-4FUA4TRP.mjs.map +7 -0
  45. package/dist/lib/browser/testing/index.mjs +198 -54
  46. package/dist/lib/browser/testing/index.mjs.map +4 -4
  47. package/dist/lib/browser/testing/react.mjs +78 -0
  48. package/dist/lib/browser/testing/react.mjs.map +7 -0
  49. package/dist/lib/browser/ui/index.mjs +22 -15
  50. package/dist/lib/node-esm/{capability-SA6LPYGL.mjs → capability-7TCQK7ZP.mjs} +12 -11
  51. package/dist/lib/node-esm/capability-7TCQK7ZP.mjs.map +7 -0
  52. package/dist/lib/node-esm/{chunk-FKE4Z3D6.mjs → chunk-37Z53PXZ.mjs} +1 -1
  53. package/dist/lib/node-esm/{chunk-FKE4Z3D6.mjs.map → chunk-37Z53PXZ.mjs.map} +2 -2
  54. package/dist/lib/node-esm/chunk-4BX2AE47.mjs +1468 -0
  55. package/dist/lib/node-esm/chunk-4BX2AE47.mjs.map +7 -0
  56. package/dist/lib/node-esm/{chunk-SB5ODNPX.mjs → chunk-CTKEZHKF.mjs} +9 -2
  57. package/dist/lib/node-esm/chunk-CTKEZHKF.mjs.map +7 -0
  58. package/dist/lib/node-esm/chunk-FPW45EZH.mjs +14 -0
  59. package/dist/lib/node-esm/chunk-FPW45EZH.mjs.map +7 -0
  60. package/dist/lib/node-esm/chunk-GEWHMHM7.mjs +588 -0
  61. package/dist/lib/node-esm/chunk-GEWHMHM7.mjs.map +7 -0
  62. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs +29 -0
  63. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs.map +7 -0
  64. package/dist/lib/node-esm/{chunk-3D66SZHP.mjs → chunk-KSH4OVMY.mjs} +28 -55
  65. package/dist/lib/node-esm/chunk-KSH4OVMY.mjs.map +7 -0
  66. package/dist/lib/node-esm/{chunk-SQICGJBW.mjs → chunk-QBUGLR4H.mjs} +20 -5
  67. package/dist/lib/node-esm/chunk-QBUGLR4H.mjs.map +7 -0
  68. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs +70 -0
  69. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs.map +7 -0
  70. package/dist/lib/node-esm/chunk-XGBUKRCK.mjs +423 -0
  71. package/dist/lib/node-esm/chunk-XGBUKRCK.mjs.map +7 -0
  72. package/dist/lib/node-esm/{chunk-JHFY3HTS.mjs → chunk-XIGPWXCQ.mjs} +100 -18
  73. package/dist/lib/node-esm/chunk-XIGPWXCQ.mjs.map +7 -0
  74. package/dist/lib/node-esm/{chunk-6REV5DE7.mjs → chunk-XOCUANHO.mjs} +3 -2
  75. package/dist/lib/node-esm/chunk-XOCUANHO.mjs.map +7 -0
  76. package/dist/lib/node-esm/chunk-Y7JKXNDU.mjs +477 -0
  77. package/dist/lib/node-esm/chunk-Y7JKXNDU.mjs.map +7 -0
  78. package/dist/lib/node-esm/cli/index.mjs +15 -30
  79. package/dist/lib/node-esm/cli/index.mjs.map +3 -3
  80. package/dist/lib/node-esm/common/activation-events.mjs +11 -14
  81. package/dist/lib/node-esm/common/capabilities.mjs +19 -8
  82. package/dist/lib/node-esm/core/activation-event.mjs +1 -1
  83. package/dist/lib/node-esm/core/capability.mjs +5 -1
  84. package/dist/lib/node-esm/core/plugin-manager.mjs +8 -4
  85. package/dist/lib/node-esm/core/plugin.mjs +18 -4
  86. package/dist/lib/node-esm/core/url-loader.mjs +25 -0
  87. package/dist/lib/node-esm/index.mjs +51 -54
  88. package/dist/lib/node-esm/index.mjs.map +4 -4
  89. package/dist/lib/node-esm/meta.json +1 -1
  90. package/dist/lib/node-esm/process-manager-capability-F23D62RN.mjs +90 -0
  91. package/dist/lib/node-esm/process-manager-capability-F23D62RN.mjs.map +7 -0
  92. package/dist/lib/node-esm/testing/index.mjs +198 -54
  93. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  94. package/dist/lib/node-esm/testing/react.mjs +79 -0
  95. package/dist/lib/node-esm/testing/react.mjs.map +7 -0
  96. package/dist/lib/node-esm/ui/index.mjs +22 -15
  97. package/dist/plugin/node-esm/index.mjs +971 -0
  98. package/dist/plugin/node-esm/index.mjs.map +7 -0
  99. package/dist/plugin/node-esm/meta.json +1 -0
  100. package/dist/types/src/cli/cli.d.ts +1 -3
  101. package/dist/types/src/cli/cli.d.ts.map +1 -1
  102. package/dist/types/src/common/activation-events.d.ts +10 -13
  103. package/dist/types/src/common/activation-events.d.ts.map +1 -1
  104. package/dist/types/src/common/annotations.d.ts +1 -0
  105. package/dist/types/src/common/annotations.d.ts.map +1 -0
  106. package/dist/types/src/common/capabilities.d.ts +113 -12
  107. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  108. package/dist/types/src/common/index.d.ts +0 -1
  109. package/dist/types/src/common/index.d.ts.map +1 -1
  110. package/dist/types/src/common/translations.d.ts +1 -1
  111. package/dist/types/src/core/activation-event.d.ts +4 -4
  112. package/dist/types/src/core/activation-event.d.ts.map +1 -1
  113. package/dist/types/src/core/capability-manager.d.ts +9 -0
  114. package/dist/types/src/core/capability-manager.d.ts.map +1 -1
  115. package/dist/types/src/core/capability.d.ts +13 -2
  116. package/dist/types/src/core/capability.d.ts.map +1 -1
  117. package/dist/types/src/core/edge-registry-plugin-provider.d.ts +30 -0
  118. package/dist/types/src/core/edge-registry-plugin-provider.d.ts.map +1 -0
  119. package/dist/types/src/core/index.d.ts +6 -0
  120. package/dist/types/src/core/index.d.ts.map +1 -1
  121. package/dist/types/src/core/plugin-asset-cache.d.ts +71 -0
  122. package/dist/types/src/core/plugin-asset-cache.d.ts.map +1 -0
  123. package/dist/types/src/core/plugin-manager.d.ts +238 -7
  124. package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
  125. package/dist/types/src/core/plugin-manifest.d.ts +101 -0
  126. package/dist/types/src/core/plugin-manifest.d.ts.map +1 -0
  127. package/dist/types/src/core/plugin-manifest.test.d.ts +2 -0
  128. package/dist/types/src/core/plugin-manifest.test.d.ts.map +1 -0
  129. package/dist/types/src/core/plugin.d.ts +213 -11
  130. package/dist/types/src/core/plugin.d.ts.map +1 -1
  131. package/dist/types/src/core/registry.d.ts +107 -0
  132. package/dist/types/src/core/registry.d.ts.map +1 -0
  133. package/dist/types/src/core/url-loader.d.ts +127 -0
  134. package/dist/types/src/core/url-loader.d.ts.map +1 -0
  135. package/dist/types/src/core/url-loader.test.d.ts +2 -0
  136. package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
  137. package/dist/types/src/helpers.d.ts.map +1 -1
  138. package/dist/types/src/index.d.ts +1 -2
  139. package/dist/types/src/index.d.ts.map +1 -1
  140. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts +3 -0
  141. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts.map +1 -0
  142. package/dist/types/src/plugin-process-manager/history/capability.d.ts.map +1 -0
  143. package/dist/types/src/plugin-process-manager/history/errors.d.ts +32 -0
  144. package/dist/types/src/plugin-process-manager/history/errors.d.ts.map +1 -0
  145. package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts +32 -0
  146. package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts.map +1 -0
  147. package/dist/types/src/plugin-process-manager/history/history-tracker.test.d.ts.map +1 -0
  148. package/dist/types/src/plugin-process-manager/history/index.d.ts.map +1 -0
  149. package/dist/types/src/{plugin-operation → plugin-process-manager}/history/types.d.ts +1 -1
  150. package/dist/types/src/plugin-process-manager/history/types.d.ts.map +1 -0
  151. package/dist/types/src/{plugin-operation → plugin-process-manager}/history/undo-mapping.d.ts +2 -2
  152. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts.map +1 -0
  153. package/dist/types/src/{plugin-operation → plugin-process-manager}/history/undo-registry.d.ts +1 -1
  154. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts.map +1 -0
  155. package/dist/types/src/plugin-process-manager/history/undo-registry.test.d.ts.map +1 -0
  156. package/dist/types/src/plugin-process-manager/index.d.ts +3 -0
  157. package/dist/types/src/plugin-process-manager/index.d.ts.map +1 -0
  158. package/dist/types/src/plugin-process-manager/meta.d.ts +3 -0
  159. package/dist/types/src/plugin-process-manager/meta.d.ts.map +1 -0
  160. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts +8 -0
  161. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -0
  162. package/dist/types/src/plugin-process-manager/testing.d.ts +59 -0
  163. package/dist/types/src/plugin-process-manager/testing.d.ts.map +1 -0
  164. package/dist/types/src/testing/harness.d.ts +79 -0
  165. package/dist/types/src/testing/harness.d.ts.map +1 -0
  166. package/dist/types/src/testing/index.d.ts +1 -0
  167. package/dist/types/src/testing/index.d.ts.map +1 -1
  168. package/dist/types/src/testing/react.d.ts +27 -0
  169. package/dist/types/src/testing/react.d.ts.map +1 -0
  170. package/dist/types/src/testing/react.test.d.ts +2 -0
  171. package/dist/types/src/testing/react.test.d.ts.map +1 -0
  172. package/dist/types/src/testing/service.d.ts.map +1 -1
  173. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  174. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  175. package/dist/types/src/ui/components/App/App.d.ts +36 -3
  176. package/dist/types/src/ui/components/App/App.d.ts.map +1 -1
  177. package/dist/types/src/ui/components/App/App.stories.d.ts +2 -2
  178. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -1
  179. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -1
  180. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +16 -4
  181. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
  182. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
  183. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -1
  184. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
  185. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
  186. package/dist/types/src/ui/components/Surface/index.d.ts +22 -6
  187. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
  188. package/dist/types/src/ui/components/Surface/types.d.ts +110 -9
  189. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
  190. package/dist/types/src/ui/components/Surface/types.test.d.ts +2 -0
  191. package/dist/types/src/ui/components/Surface/types.test.d.ts.map +1 -0
  192. package/dist/types/src/ui/hooks/index.d.ts +1 -1
  193. package/dist/types/src/ui/hooks/index.d.ts.map +1 -1
  194. package/dist/types/src/ui/hooks/useApp.d.ts +42 -12
  195. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -1
  196. package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
  197. package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
  198. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
  199. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -1
  200. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts +30 -0
  201. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts.map +1 -0
  202. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -1
  203. package/dist/types/src/vite-plugin/boot-loader/index.d.ts +2 -0
  204. package/dist/types/src/vite-plugin/boot-loader/index.d.ts.map +1 -0
  205. package/dist/types/src/vite-plugin/boot-loader/loader.d.ts +54 -0
  206. package/dist/types/src/vite-plugin/boot-loader/loader.d.ts.map +1 -0
  207. package/dist/types/src/vite-plugin/composer/index.d.ts +34 -0
  208. package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -0
  209. package/dist/types/src/vite-plugin/import-map/index.d.ts +28 -0
  210. package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -0
  211. package/dist/types/src/vite-plugin/index.d.ts +5 -0
  212. package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
  213. package/dist/types/src/vite-plugin/manifest.d.ts +41 -0
  214. package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -0
  215. package/dist/types/src/vite-plugin/manifest.test.d.ts +2 -0
  216. package/dist/types/src/vite-plugin/manifest.test.d.ts.map +1 -0
  217. package/dist/types/src/vite-plugin/packages.d.ts +13 -0
  218. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
  219. package/dist/types/tsconfig.tsbuildinfo +1 -1
  220. package/moon.yml +15 -0
  221. package/package.json +61 -57
  222. package/src/cli/cli.ts +2 -7
  223. package/src/common/activation-events.ts +10 -15
  224. package/src/common/annotations.ts +3 -0
  225. package/src/common/capabilities.ts +147 -16
  226. package/src/common/index.ts +0 -1
  227. package/src/common/translations.ts +1 -1
  228. package/src/core/activation-event.ts +4 -1
  229. package/src/core/capability-manager.test.ts +4 -1
  230. package/src/core/capability-manager.ts +44 -2
  231. package/src/core/capability.ts +20 -2
  232. package/src/core/edge-registry-plugin-provider.ts +92 -0
  233. package/src/core/index.ts +6 -0
  234. package/src/core/plugin-asset-cache.ts +60 -0
  235. package/src/core/plugin-manager.test.ts +1103 -19
  236. package/src/core/plugin-manager.ts +1176 -199
  237. package/src/core/plugin-manifest.test.ts +75 -0
  238. package/src/core/plugin-manifest.ts +134 -0
  239. package/src/core/plugin.ts +235 -17
  240. package/src/core/registry.ts +163 -0
  241. package/src/core/url-loader.test.ts +222 -0
  242. package/src/core/url-loader.ts +388 -0
  243. package/src/index.ts +1 -2
  244. package/src/plugin-process-manager/ProcessManagerPlugin.ts +24 -0
  245. package/src/{plugin-operation → plugin-process-manager}/history/capability.ts +1 -2
  246. package/src/plugin-process-manager/history/errors.ts +7 -0
  247. package/src/{plugin-operation → plugin-process-manager}/history/history-tracker.test.ts +61 -88
  248. package/src/{plugin-operation → plugin-process-manager}/history/history-tracker.ts +33 -18
  249. package/src/{plugin-operation → plugin-process-manager}/history/types.ts +1 -1
  250. package/src/{plugin-operation → plugin-process-manager}/history/undo-mapping.ts +2 -2
  251. package/src/{plugin-operation → plugin-process-manager}/history/undo-registry.test.ts +6 -5
  252. package/src/{plugin-operation → plugin-process-manager}/history/undo-registry.ts +1 -1
  253. package/src/{plugin-operation → plugin-process-manager}/index.ts +1 -1
  254. package/src/plugin-process-manager/meta.ts +16 -0
  255. package/src/plugin-process-manager/process-manager-capability.ts +178 -0
  256. package/src/{plugin-operation → plugin-process-manager}/testing.ts +32 -50
  257. package/src/testing/harness.ts +247 -0
  258. package/src/testing/index.ts +1 -0
  259. package/src/testing/react.test.tsx +50 -0
  260. package/src/testing/react.tsx +113 -0
  261. package/src/testing/service.ts +2 -2
  262. package/src/testing/withPluginManager.stories.tsx +1 -2
  263. package/src/testing/withPluginManager.tsx +47 -21
  264. package/src/ui/components/App/App.stories.tsx +12 -20
  265. package/src/ui/components/App/App.tsx +97 -10
  266. package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +13 -17
  267. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +17 -16
  268. package/src/ui/components/Surface/SurfaceComponent.tsx +111 -55
  269. package/src/ui/components/Surface/SurfaceInfo.tsx +0 -1
  270. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
  271. package/src/ui/components/Surface/index.ts +35 -1
  272. package/src/ui/components/Surface/types.test.ts +126 -0
  273. package/src/ui/components/Surface/types.ts +185 -12
  274. package/src/ui/hooks/index.ts +1 -1
  275. package/src/ui/hooks/useApp.test.tsx +161 -0
  276. package/src/ui/hooks/useApp.tsx +215 -24
  277. package/src/ui/hooks/useCapabilities.ts +1 -0
  278. package/src/ui/hooks/useLoading.tsx +14 -6
  279. package/src/ui/hooks/useProcessManagerRuntime.ts +78 -0
  280. package/src/vite-plugin/boot-loader/BootLoader.solid-stories.tsx +198 -0
  281. package/src/vite-plugin/boot-loader/index.ts +5 -0
  282. package/src/vite-plugin/boot-loader/loader-app/Loader.tsx +166 -0
  283. package/src/vite-plugin/boot-loader/loader-app/boot-loader.css +311 -0
  284. package/src/vite-plugin/boot-loader/loader-app/bridge.ts +25 -0
  285. package/src/vite-plugin/boot-loader/loader-app/entry.tsx +21 -0
  286. package/src/vite-plugin/boot-loader/loader-app/mount.tsx +70 -0
  287. package/src/vite-plugin/boot-loader/loader-app/store.test.ts +137 -0
  288. package/src/vite-plugin/boot-loader/loader-app/store.ts +149 -0
  289. package/src/vite-plugin/boot-loader/loader-app/tsconfig.json +11 -0
  290. package/src/vite-plugin/boot-loader/loader-app/types.ts +78 -0
  291. package/src/vite-plugin/boot-loader/loader.ts +193 -0
  292. package/src/vite-plugin/composer/index.ts +306 -0
  293. package/src/vite-plugin/import-map/index.ts +527 -0
  294. package/src/vite-plugin/index.ts +10 -0
  295. package/src/vite-plugin/manifest.test.ts +55 -0
  296. package/src/vite-plugin/manifest.ts +63 -0
  297. package/src/vite-plugin/packages.ts +187 -0
  298. package/tsconfig.json +26 -3
  299. package/tsconfig.node.json +1 -1
  300. package/vitest.config.ts +1 -1
  301. package/.swc/plugins/linux_x86_64_19.0.0/727453fb3a62f7f1d952a41e051ca8a6f88cadc45cee43c6a4d1aa45f9b75665.wasmer-v7 +0 -0
  302. package/dist/lib/browser/capability-6YMUBS54.mjs +0 -37
  303. package/dist/lib/browser/capability-6YMUBS54.mjs.map +0 -7
  304. package/dist/lib/browser/capability-LF3OXSCV.mjs.map +0 -7
  305. package/dist/lib/browser/chunk-272IPLHQ.mjs.map +0 -7
  306. package/dist/lib/browser/chunk-2UI6ACB5.mjs +0 -824
  307. package/dist/lib/browser/chunk-2UI6ACB5.mjs.map +0 -7
  308. package/dist/lib/browser/chunk-7M4467QR.mjs.map +0 -7
  309. package/dist/lib/browser/chunk-JGWCBVKJ.mjs.map +0 -7
  310. package/dist/lib/browser/chunk-M5IC326L.mjs +0 -34
  311. package/dist/lib/browser/chunk-M5IC326L.mjs.map +0 -7
  312. package/dist/lib/browser/chunk-NQPYE365.mjs +0 -703
  313. package/dist/lib/browser/chunk-NQPYE365.mjs.map +0 -7
  314. package/dist/lib/browser/chunk-TIEBZMTF.mjs +0 -44
  315. package/dist/lib/browser/chunk-TIEBZMTF.mjs.map +0 -7
  316. package/dist/lib/browser/chunk-WEBSGU5L.mjs.map +0 -7
  317. package/dist/lib/browser/chunk-YAFEA4GV.mjs +0 -1
  318. package/dist/lib/browser/chunk-YNFPIQGB.mjs.map +0 -7
  319. package/dist/lib/browser/invoker-capability-4AUGUMM5.mjs +0 -36
  320. package/dist/lib/browser/invoker-capability-4AUGUMM5.mjs.map +0 -7
  321. package/dist/lib/node-esm/capability-R5O2OYX4.mjs +0 -38
  322. package/dist/lib/node-esm/capability-R5O2OYX4.mjs.map +0 -7
  323. package/dist/lib/node-esm/capability-SA6LPYGL.mjs.map +0 -7
  324. package/dist/lib/node-esm/chunk-3D66SZHP.mjs.map +0 -7
  325. package/dist/lib/node-esm/chunk-6REV5DE7.mjs.map +0 -7
  326. package/dist/lib/node-esm/chunk-FHWPWQRJ.mjs +0 -704
  327. package/dist/lib/node-esm/chunk-FHWPWQRJ.mjs.map +0 -7
  328. package/dist/lib/node-esm/chunk-JHFY3HTS.mjs.map +0 -7
  329. package/dist/lib/node-esm/chunk-JIVXIJ2T.mjs +0 -825
  330. package/dist/lib/node-esm/chunk-JIVXIJ2T.mjs.map +0 -7
  331. package/dist/lib/node-esm/chunk-NHXBSAQR.mjs +0 -35
  332. package/dist/lib/node-esm/chunk-NHXBSAQR.mjs.map +0 -7
  333. package/dist/lib/node-esm/chunk-SB5ODNPX.mjs.map +0 -7
  334. package/dist/lib/node-esm/chunk-SCDGIGGU.mjs +0 -45
  335. package/dist/lib/node-esm/chunk-SCDGIGGU.mjs.map +0 -7
  336. package/dist/lib/node-esm/chunk-SQICGJBW.mjs.map +0 -7
  337. package/dist/lib/node-esm/chunk-Z4TJPSMP.mjs +0 -2
  338. package/dist/lib/node-esm/invoker-capability-3YDIVDWV.mjs +0 -37
  339. package/dist/lib/node-esm/invoker-capability-3YDIVDWV.mjs.map +0 -7
  340. package/dist/types/src/common/operations.d.ts +0 -33
  341. package/dist/types/src/common/operations.d.ts.map +0 -1
  342. package/dist/types/src/plugin-operation/OperationPlugin.d.ts +0 -3
  343. package/dist/types/src/plugin-operation/OperationPlugin.d.ts.map +0 -1
  344. package/dist/types/src/plugin-operation/history/capability.d.ts.map +0 -1
  345. package/dist/types/src/plugin-operation/history/errors.d.ts +0 -5
  346. package/dist/types/src/plugin-operation/history/errors.d.ts.map +0 -1
  347. package/dist/types/src/plugin-operation/history/history-tracker.d.ts +0 -18
  348. package/dist/types/src/plugin-operation/history/history-tracker.d.ts.map +0 -1
  349. package/dist/types/src/plugin-operation/history/history-tracker.test.d.ts.map +0 -1
  350. package/dist/types/src/plugin-operation/history/index.d.ts.map +0 -1
  351. package/dist/types/src/plugin-operation/history/types.d.ts.map +0 -1
  352. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts.map +0 -1
  353. package/dist/types/src/plugin-operation/history/undo-registry.d.ts.map +0 -1
  354. package/dist/types/src/plugin-operation/history/undo-registry.test.d.ts.map +0 -1
  355. package/dist/types/src/plugin-operation/index.d.ts +0 -3
  356. package/dist/types/src/plugin-operation/index.d.ts.map +0 -1
  357. package/dist/types/src/plugin-operation/invoker-capability.d.ts +0 -6
  358. package/dist/types/src/plugin-operation/invoker-capability.d.ts.map +0 -1
  359. package/dist/types/src/plugin-operation/meta.d.ts +0 -3
  360. package/dist/types/src/plugin-operation/meta.d.ts.map +0 -1
  361. package/dist/types/src/plugin-operation/testing.d.ts +0 -109
  362. package/dist/types/src/plugin-operation/testing.d.ts.map +0 -1
  363. package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts +0 -3
  364. package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts.map +0 -1
  365. package/dist/types/src/plugin-runtime/capability.d.ts +0 -6
  366. package/dist/types/src/plugin-runtime/capability.d.ts.map +0 -1
  367. package/dist/types/src/plugin-runtime/index.d.ts +0 -2
  368. package/dist/types/src/plugin-runtime/index.d.ts.map +0 -1
  369. package/dist/types/src/plugin-runtime/meta.d.ts +0 -3
  370. package/dist/types/src/plugin-runtime/meta.d.ts.map +0 -1
  371. package/dist/types/src/ui/hooks/useOperationResolver.d.ts +0 -19
  372. package/dist/types/src/ui/hooks/useOperationResolver.d.ts.map +0 -1
  373. package/src/common/operations.ts +0 -38
  374. package/src/plugin-operation/OperationPlugin.ts +0 -25
  375. package/src/plugin-operation/history/errors.ts +0 -11
  376. package/src/plugin-operation/invoker-capability.ts +0 -40
  377. package/src/plugin-operation/meta.ts +0 -11
  378. package/src/plugin-runtime/RuntimePlugin.ts +0 -20
  379. package/src/plugin-runtime/capability.ts +0 -53
  380. package/src/plugin-runtime/index.ts +0 -5
  381. package/src/plugin-runtime/meta.ts +0 -11
  382. package/src/ui/hooks/useOperationResolver.ts +0 -40
  383. /package/dist/lib/browser/{chunk-YAFEA4GV.mjs.map → core/url-loader.mjs.map} +0 -0
  384. /package/dist/lib/node-esm/{chunk-Z4TJPSMP.mjs.map → core/url-loader.mjs.map} +0 -0
  385. /package/dist/types/src/{plugin-operation → plugin-process-manager}/history/capability.d.ts +0 -0
  386. /package/dist/types/src/{plugin-operation → plugin-process-manager}/history/history-tracker.test.d.ts +0 -0
  387. /package/dist/types/src/{plugin-operation → plugin-process-manager}/history/index.d.ts +0 -0
  388. /package/dist/types/src/{plugin-operation → plugin-process-manager}/history/undo-registry.test.d.ts +0 -0
  389. /package/src/{plugin-operation → plugin-process-manager}/history/index.ts +0 -0
@@ -0,0 +1,178 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { Registry } from '@effect-atom/atom';
6
+ import * as KeyValueStore from '@effect/platform/KeyValueStore';
7
+ import * as Effect from 'effect/Effect';
8
+ import * as Layer from 'effect/Layer';
9
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
10
+
11
+ import { LayerSpec, OperationHandlerSet, Process, ServiceResolver, Trace } from '@dxos/compute';
12
+ import { LayerStack, ProcessManager } from '@dxos/compute-runtime';
13
+ import { invariant } from '@dxos/invariant';
14
+ // Explicit import so the emitted `.d.ts` references the package via its public
15
+ // alias instead of a relative `node_modules` path (TS2883).
16
+ import { OperationInvoker } from '@dxos/operation';
17
+
18
+ import { ActivationEvents, Capabilities } from '../common';
19
+ import { Capability, Plugin } from '../core';
20
+
21
+ //
22
+ // Capability Module
23
+ //
24
+ // Hosts the {@link ProcessManager} runtime for the plugin system.
25
+ //
26
+ // Workflow:
27
+ // 1. Activates {@link ActivationEvents.SetupProcessManager} so plugins can
28
+ // contribute {@link Capabilities.LayerSpec} entries and
29
+ // {@link Capabilities.OperationHandler} sets.
30
+ // 2. Collects all contributed {@link LayerSpec.LayerSpec}s and builds a
31
+ // {@link LayerStack} whose {@link ServiceResolver} drives process-scoped
32
+ // service resolution.
33
+ // 3. Wires a reactive {@link OperationHandlerSet} that tracks
34
+ // {@link Capabilities.OperationHandler} contributions and invalidates its
35
+ // cached merge when new handlers register.
36
+ // 4. Composes the fixed runtime requirements (capability/plugin managers,
37
+ // service resolver, operation invoker, process manager) into a single
38
+ // {@link Layer} and builds a {@link ManagedRuntime} from it.
39
+ // 5. Exposes a disposable-less wrapper as {@link Capabilities.ProcessManagerRuntime}
40
+ // (the plugin system manages its lifecycle).
41
+ //
42
+
43
+ export default Capability.makeModule(
44
+ Effect.fnUntraced(function* () {
45
+ const capabilityManager = yield* Capability.Service;
46
+ const pluginManager = yield* Plugin.Service;
47
+ const atomRegistry = yield* Capability.get(Capabilities.AtomRegistry);
48
+
49
+ yield* Plugin.activate(ActivationEvents.SetupProcessManager);
50
+
51
+ const layerSpecs = yield* Capability.getAll(Capabilities.LayerSpec);
52
+ const traceSinkFactories = yield* Capability.getAll(Capabilities.TraceSink);
53
+
54
+ // Forward reference to `ProcessManager.ProcessManagerService`. The runtime
55
+ // that owns the manager depends transitively on `ServiceResolver` (which is
56
+ // built from the `LayerStack` below), so we cannot materialise it before
57
+ // the stack exists. Instead we publish the manager into this holder as
58
+ // soon as the runtime is built, and the ambient layer reads it lazily via
59
+ // `Layer.effect` — slice init only runs once a process actually triggers
60
+ // service resolution, by which point the holder is populated.
61
+ let processManagerHolder: ProcessManager.Manager | undefined;
62
+
63
+ // Expose the foundational app-framework services through the LayerStack so
64
+ // that operations declaring `services: [Capability.Service]` (and friends)
65
+ // can resolve them via the ServiceResolver. Without this, only consumers
66
+ // sitting on the same ManagedRuntime layer graph can see them — process
67
+ // executions go through ServiceResolver.resolveAll and would fail.
68
+ const ambientLayerSpec = LayerSpec.make(
69
+ {
70
+ affinity: 'application',
71
+ requires: [],
72
+ provides: [Capability.Service, Plugin.Service, Registry.AtomRegistry, ProcessManager.ProcessManagerService],
73
+ },
74
+ () =>
75
+ Layer.mergeAll(
76
+ Layer.succeed(Capability.Service, capabilityManager),
77
+ Layer.succeed(Plugin.Service, pluginManager),
78
+ Layer.succeed(Registry.AtomRegistry, atomRegistry),
79
+ Layer.effect(
80
+ ProcessManager.ProcessManagerService,
81
+ Effect.sync(() => {
82
+ invariant(
83
+ processManagerHolder,
84
+ 'ProcessManagerService accessed before the process-manager runtime was initialised',
85
+ );
86
+ return processManagerHolder;
87
+ }),
88
+ ),
89
+ ),
90
+ );
91
+
92
+ const layerStack = new LayerStack.LayerStack({ layers: [ambientLayerSpec, ...layerSpecs] });
93
+ const serviceResolver = layerStack.getServiceResolver();
94
+
95
+ const handlerSet = OperationHandlerSet.reactive(
96
+ atomRegistry,
97
+ capabilityManager.atom(Capabilities.OperationHandler),
98
+ );
99
+
100
+ const traceSinks = traceSinkFactories.map((factory) => factory({ resolver: serviceResolver }));
101
+ const mergedTraceSink = Trace.mergeSinks(traceSinks);
102
+
103
+ // Base services required by ProcessManager and the operation invoker.
104
+ // Sensible defaults are provided here; plugins that want alternative
105
+ // implementations (e.g. persistent KV store, real tracing) can contribute
106
+ // their own LayerSpec entries against the ServiceResolver.
107
+ const baseLayer = Layer.mergeAll(
108
+ Layer.succeed(Capability.Service, capabilityManager),
109
+ Layer.succeed(Plugin.Service, pluginManager),
110
+ Layer.succeed(Registry.AtomRegistry, atomRegistry),
111
+ Layer.succeed(ServiceResolver.ServiceResolver, serviceResolver),
112
+ OperationHandlerSet.provide(handlerSet),
113
+ KeyValueStore.layerMemory,
114
+ Layer.succeed(Trace.TraceSink, mergedTraceSink),
115
+ );
116
+
117
+ const processManagerLayer = ProcessManager.layer({ runtimeName: Trace.CommonRuntimeName.local }).pipe(
118
+ Layer.provide(baseLayer),
119
+ );
120
+ const operationInvokerLayer = ProcessManager.ProcessOperationInvoker.layer.pipe(
121
+ Layer.provide(Layer.mergeAll(processManagerLayer, baseLayer)),
122
+ );
123
+
124
+ const runtimeLayer = Layer.mergeAll(baseLayer, processManagerLayer, operationInvokerLayer);
125
+
126
+ const managedRuntime = ManagedRuntime.make(runtimeLayer as Layer.Layer<any, any, never>);
127
+
128
+ // TODO(dmaretskyi): Capability modules don't currently expose a teardown
129
+ // hook (`makeModule` only allows `Service | Plugin.Service` in the effect's
130
+ // requirements, ruling out `Effect.addFinalizer`). Once the plugin
131
+ // framework grows a shutdown lifecycle, dispose `managedRuntime` and then
132
+ // call `layerStack.destroy()` to tear down keep-alive slices.
133
+
134
+ const processManagerRuntime: Capabilities.ProcessManagerRuntime = {
135
+ runPromise: (effect, options) => managedRuntime.runPromise(effect as Effect.Effect<any, any, any>, options),
136
+ runPromiseExit: (effect, options) =>
137
+ managedRuntime.runPromiseExit(effect as Effect.Effect<any, any, any>, options),
138
+ runFork: (effect, options) => managedRuntime.runFork(effect as Effect.Effect<any, any, any>, options),
139
+ runSync: (effect) => managedRuntime.runSync(effect as Effect.Effect<any, any, any>),
140
+ };
141
+
142
+ // Eagerly extract the process monitor. Safe because it does not require a
143
+ // fresh scope and is a stable reference for the lifetime of the runtime.
144
+ const processMonitor = managedRuntime.runSync(
145
+ Effect.flatMap(Process.ProcessMonitorService, Effect.succeed) as Effect.Effect<Process.Monitor, never, never>,
146
+ );
147
+
148
+ // Publish the manager into the ambient-layer holder so that
149
+ // `ProcessManager.ProcessManagerService` becomes resolvable through the
150
+ // LayerStack alongside the other framework-supplied services.
151
+ processManagerHolder = managedRuntime.runSync(
152
+ Effect.flatMap(ProcessManager.ProcessManagerService, Effect.succeed) as Effect.Effect<
153
+ ProcessManager.Manager,
154
+ never,
155
+ never
156
+ >,
157
+ );
158
+
159
+ // Eagerly extract the operation invoker built by ProcessOperationInvoker.layer.
160
+ // Pulled via the ProcessOperationInvoker tag so the contributed value carries
161
+ // the full OperationInvoker interface (`invocations`, `pendingFollowups`,
162
+ // `awaitFollowups`, `_invokeCore`) that HistoryTracker requires.
163
+ const operationInvoker: OperationInvoker.OperationInvoker = managedRuntime.runSync(
164
+ Effect.flatMap(ProcessManager.ProcessOperationInvoker.Service, Effect.succeed) as unknown as Effect.Effect<
165
+ OperationInvoker.OperationInvoker,
166
+ never,
167
+ never
168
+ >,
169
+ );
170
+
171
+ return [
172
+ Capability.contributes(Capabilities.ProcessManagerRuntime, processManagerRuntime),
173
+ Capability.contributes(Capabilities.ServiceResolver, serviceResolver),
174
+ Capability.contributes(Capabilities.ProcessMonitor, processMonitor),
175
+ Capability.contributes(Capabilities.OperationInvoker, operationInvoker),
176
+ ];
177
+ }),
178
+ );
@@ -9,84 +9,66 @@ import * as Ref from 'effect/Ref';
9
9
  import * as Schema from 'effect/Schema';
10
10
  import * as Stream from 'effect/Stream';
11
11
 
12
- import { Operation, type OperationInvoker, OperationResolver } from '@dxos/operation';
12
+ import { Operation } from '@dxos/compute';
13
+ import { DXN } from '@dxos/keys';
14
+ import { OperationInvoker } from '@dxos/operation';
13
15
 
14
16
  //
15
17
  // Test Operations
16
18
  //
17
19
 
18
20
  export const Compute = Operation.make({
19
- schema: {
20
- input: Schema.Struct({ value: Schema.Number }),
21
- output: Schema.Struct({ value: Schema.Number }),
22
- },
23
- meta: { key: 'test.compute' },
21
+ input: Schema.Struct({ value: Schema.Number }),
22
+ output: Schema.Struct({ value: Schema.Number }),
23
+ meta: { key: DXN.make('org.dxos.test.compute') },
24
24
  });
25
25
 
26
26
  export const HalveCompute = Operation.make({
27
- schema: {
28
- input: Schema.Struct({ value: Schema.Number }),
29
- output: Schema.Struct({ value: Schema.Number }),
30
- },
31
- meta: { key: 'test.halve-compute' },
27
+ input: Schema.Struct({ value: Schema.Number }),
28
+ output: Schema.Struct({ value: Schema.Number }),
29
+ meta: { key: DXN.make('org.dxos.test.halveCompute') },
32
30
  });
33
31
 
34
32
  export const ToString = Operation.make({
35
- schema: {
36
- input: Schema.Struct({ value: Schema.Number }),
37
- output: Schema.Struct({ string: Schema.String }),
38
- },
39
- meta: { key: 'test.to-string' },
33
+ input: Schema.Struct({ value: Schema.Number }),
34
+ output: Schema.Struct({ string: Schema.String }),
35
+ meta: { key: DXN.make('org.dxos.test.toString') },
40
36
  });
41
37
 
42
38
  export const Add = Operation.make({
43
- schema: {
44
- input: Schema.Tuple(Schema.Number, Schema.Number),
45
- output: Schema.Number,
46
- },
47
- meta: { key: 'test.add' },
39
+ input: Schema.Tuple(Schema.Number, Schema.Number),
40
+ output: Schema.Number,
41
+ meta: { key: DXN.make('org.dxos.test.add') },
48
42
  });
49
43
 
50
44
  export const SideEffect = Operation.make({
51
- schema: {
52
- input: Schema.Void,
53
- output: Schema.Void,
54
- },
55
- meta: { key: 'test.side-effect' },
45
+ input: Schema.Void,
46
+ output: Schema.Void,
47
+ meta: { key: DXN.make('org.dxos.test.sideEffect') },
56
48
  });
57
49
 
58
50
  //
59
51
  // Test Handlers
60
52
  //
61
53
 
62
- export const computeHandler = OperationResolver.make({
63
- operation: Compute,
64
- handler: (data) =>
65
- Effect.gen(function* () {
66
- yield* Effect.sleep(data.value * 10);
67
- return { value: data.value * 2 };
68
- }),
69
- });
54
+ export const computeHandler = Operation.withHandler(Compute, (data) =>
55
+ Effect.gen(function* () {
56
+ yield* Effect.sleep(data.value * 10);
57
+ return { value: data.value * 2 };
58
+ }),
59
+ );
70
60
 
71
- export const halveComputeHandler = OperationResolver.make({
72
- operation: HalveCompute,
73
- handler: (data) => Effect.succeed({ value: data.value / 2 }),
74
- });
61
+ export const halveComputeHandler = Operation.withHandler(HalveCompute, (data) =>
62
+ Effect.succeed({ value: data.value / 2 }),
63
+ );
75
64
 
76
- export const toStringHandler = OperationResolver.make({
77
- operation: ToString,
78
- handler: (data) => Effect.succeed({ string: data.value.toString() }),
79
- });
65
+ export const toStringHandler = Operation.withHandler(ToString, (data) =>
66
+ Effect.succeed({ string: data.value.toString() }),
67
+ );
80
68
 
81
- export const addHandler = OperationResolver.make({
82
- operation: Add,
83
- handler: (data) => Effect.succeed(data[0] + data[1]),
84
- });
69
+ export const addHandler = Operation.withHandler(Add, (data) => Effect.succeed(data[0] + data[1]));
85
70
 
86
- export const sideEffectHandler = OperationResolver.make({
87
- operation: SideEffect,
88
- handler: () => Effect.succeed(undefined),
89
- });
71
+ export const sideEffectHandler = Operation.withHandler(SideEffect, () => Effect.succeed(undefined));
90
72
 
91
73
  //
92
74
  // Test Utilities
@@ -0,0 +1,247 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Registry } from '@effect-atom/atom-react';
6
+ import * as Duration from 'effect/Duration';
7
+ import * as Effect from 'effect/Effect';
8
+ import * as PubSub from 'effect/PubSub';
9
+ import * as Queue from 'effect/Queue';
10
+
11
+ import { type Operation } from '@dxos/compute';
12
+ import { runAndForwardErrors } from '@dxos/effect';
13
+ import { invariant } from '@dxos/invariant';
14
+
15
+ import { ActivationEvents, Capabilities } from '../common';
16
+ import { ActivationEvent, type Capability, type CapabilityManager, type Plugin, PluginManager } from '../core';
17
+
18
+ export type TestAppOptions = {
19
+ /**
20
+ * Plugins to register. Plugins whose `meta.tags` includes `'system'` are treated as core
21
+ * (force-enabled). For test convenience, plugins without a `'system'` tag are enabled by
22
+ * default unless `enabled` is provided.
23
+ */
24
+ plugins: Plugin.Plugin[];
25
+ /** Plugin ids that are enabled by default in addition to core. Defaults to all non-system plugin ids. */
26
+ enabled?: string[];
27
+ /** Additional activation events fired alongside SetupReactSurface. */
28
+ setupEvents?: ActivationEvent.ActivationEvent[];
29
+ /**
30
+ * Whether to automatically fire SetupReactSurface + Startup during setup.
31
+ * Defaults to true.
32
+ */
33
+ autoStart?: boolean;
34
+ /**
35
+ * Whether to register the PluginManager + AtomRegistry framework capabilities.
36
+ * Defaults to true.
37
+ */
38
+ registerFrameworkCapabilities?: boolean;
39
+ };
40
+
41
+ /**
42
+ * A running plugin manager plus helpers for driving it in tests.
43
+ */
44
+ export interface TestHarness {
45
+ readonly manager: PluginManager.PluginManager;
46
+ readonly capabilities: CapabilityManager.CapabilityManager;
47
+ readonly registry: Registry.Registry;
48
+
49
+ /** Activate the given event. Equivalent to `manager.activate(event)`. */
50
+ fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;
51
+ /** Re-activate all modules that were activated by the given event. */
52
+ reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;
53
+
54
+ /** Returns the first contributed capability for the given interface. Throws if none are present. */
55
+ get<T>(iface: Capability.InterfaceDef<T>): T;
56
+ /** Returns all contributed capabilities for the given interface. */
57
+ getAll<T>(iface: Capability.InterfaceDef<T>): T[];
58
+ /** Waits until at least one capability is contributed for the given interface. */
59
+ waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T>;
60
+ /** Waits until the given activation event has completed. */
61
+ waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void>;
62
+
63
+ /** Invokes an operation through the `Capabilities.OperationInvoker` capability. */
64
+ invoke<I, O>(op: Operation.Definition<I, O>, ...args: void extends I ? [input?: I] : [input: I]): Promise<O>;
65
+
66
+ /**
67
+ * Waits for `Capabilities.ProcessManagerRuntime` and runs the given effect on it.
68
+ * Convenience around `waitForCapability(ProcessManagerRuntime).runPromise(effect)`.
69
+ */
70
+ runPromise<A, E>(
71
+ effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,
72
+ options?: { readonly timeout?: number; readonly signal?: AbortSignal },
73
+ ): Promise<A>;
74
+
75
+ enable(id: string): Promise<boolean>;
76
+ disable(id: string): Promise<boolean>;
77
+
78
+ /** Shuts down the underlying plugin manager. */
79
+ dispose(): Promise<void>;
80
+
81
+ /** Async-disposable support so tests can use `await using harness = ...`. */
82
+ [Symbol.asyncDispose](): Promise<void>;
83
+ }
84
+
85
+ const DEFAULT_TIMEOUT_MS = 5_000;
86
+
87
+ /**
88
+ * Creates a TestHarness with the same bootstrap sequence that `useApp` performs,
89
+ * minus the React provider tree.
90
+ *
91
+ * For Node-only tests, this is enough to fire activation events, read
92
+ * capabilities, and invoke operations.
93
+ *
94
+ * For React tests, pass the returned harness to `render` or `renderSurface`
95
+ * from `@dxos/app-framework/testing-react`.
96
+ */
97
+ export const createTestApp = async (opts: TestAppOptions): Promise<TestHarness> => {
98
+ const {
99
+ plugins,
100
+ enabled = plugins.filter(({ meta }) => !meta.tags?.includes('system')).map((plugin) => plugin.meta.id),
101
+ setupEvents = [],
102
+ autoStart = true,
103
+ registerFrameworkCapabilities = true,
104
+ } = opts;
105
+
106
+ const pluginLoader = (id: string) =>
107
+ Effect.sync(() => {
108
+ const plugin = plugins.find((plugin) => plugin.meta.id === id);
109
+ invariant(plugin, `Plugin not found: ${id}`);
110
+ return { plugin };
111
+ });
112
+
113
+ const manager = PluginManager.make({ pluginLoader, plugins, enabled });
114
+
115
+ if (registerFrameworkCapabilities) {
116
+ manager.capabilities.contribute({
117
+ interface: Capabilities.PluginManager,
118
+ implementation: manager,
119
+ module: 'org.dxos.app-framework.plugin-manager',
120
+ });
121
+ manager.capabilities.contribute({
122
+ interface: Capabilities.AtomRegistry,
123
+ implementation: manager.registry,
124
+ module: 'org.dxos.app-framework.atom-registry',
125
+ });
126
+ }
127
+
128
+ if (autoStart) {
129
+ try {
130
+ await runAndForwardErrors(
131
+ Effect.all([
132
+ ...setupEvents.map((event) => manager.activate(event)),
133
+ manager.activate(ActivationEvents.SetupReactSurface),
134
+ manager.activate(ActivationEvents.Startup),
135
+ ]),
136
+ );
137
+ } catch (err) {
138
+ await runAndForwardErrors(manager.shutdown()).catch(() => undefined);
139
+ throw err;
140
+ }
141
+ }
142
+
143
+ return new TestHarnessImpl(manager);
144
+ };
145
+
146
+ class TestHarnessImpl implements TestHarness {
147
+ constructor(readonly manager: PluginManager.PluginManager) {}
148
+
149
+ get capabilities(): CapabilityManager.CapabilityManager {
150
+ return this.manager.capabilities;
151
+ }
152
+
153
+ get registry(): Registry.Registry {
154
+ return this.manager.registry;
155
+ }
156
+
157
+ fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {
158
+ return runAndForwardErrors(this.manager.activate(event));
159
+ }
160
+
161
+ reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {
162
+ return runAndForwardErrors(this.manager.reset(event));
163
+ }
164
+
165
+ get<T>(iface: Capability.InterfaceDef<T>): T {
166
+ return this.manager.capabilities.get(iface);
167
+ }
168
+
169
+ getAll<T>(iface: Capability.InterfaceDef<T>): T[] {
170
+ return this.manager.capabilities.getAll(iface);
171
+ }
172
+
173
+ waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T> {
174
+ const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;
175
+ return runAndForwardErrors(
176
+ this.manager.capabilities.waitFor(iface).pipe(
177
+ Effect.timeoutFail({
178
+ duration: Duration.millis(timeout),
179
+ onTimeout: () => timeoutError(iface.identifier),
180
+ }),
181
+ ),
182
+ );
183
+ }
184
+
185
+ waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void> {
186
+ const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);
187
+ const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;
188
+
189
+ const program = Effect.gen(this, function* () {
190
+ const queue = yield* PubSub.subscribe(this.manager.activation);
191
+ // Re-check after subscribing to avoid a race where the event fires
192
+ // between the caller invoking this and the subscription being installed.
193
+ if (this.manager.getEventsFired().includes(key)) {
194
+ return;
195
+ }
196
+ while (true) {
197
+ const message = yield* Queue.take(queue);
198
+ if (message.event === key && message.state === 'activated') {
199
+ return;
200
+ }
201
+ }
202
+ }).pipe(
203
+ Effect.scoped,
204
+ Effect.timeoutFail({
205
+ duration: Duration.millis(timeout),
206
+ onTimeout: () => timeoutError(key),
207
+ }),
208
+ );
209
+
210
+ return runAndForwardErrors(program);
211
+ }
212
+
213
+ async invoke<I, O>(op: Operation.Definition<I, O>, ...args: [input?: I]): Promise<O> {
214
+ const invoker = await this.waitForCapability(Capabilities.OperationInvoker);
215
+ const result = await invoker.invokePromise(op as any, ...(args as [any]));
216
+ if (result.error) {
217
+ throw result.error;
218
+ }
219
+ return result.data as O;
220
+ }
221
+
222
+ async runPromise<A, E>(
223
+ effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,
224
+ options?: { readonly timeout?: number; readonly signal?: AbortSignal },
225
+ ): Promise<A> {
226
+ const runtime = await this.waitForCapability(Capabilities.ProcessManagerRuntime, { timeout: options?.timeout });
227
+ return runtime.runPromise(effect, options?.signal ? { signal: options.signal } : undefined);
228
+ }
229
+
230
+ enable(id: string): Promise<boolean> {
231
+ return runAndForwardErrors(this.manager.enable(id));
232
+ }
233
+
234
+ disable(id: string): Promise<boolean> {
235
+ return runAndForwardErrors(this.manager.disable(id));
236
+ }
237
+
238
+ async dispose(): Promise<void> {
239
+ await runAndForwardErrors(this.manager.shutdown());
240
+ }
241
+
242
+ [Symbol.asyncDispose](): Promise<void> {
243
+ return this.dispose();
244
+ }
245
+ }
246
+
247
+ const timeoutError = (id: string) => new Error(`Timed out waiting for ${id}`);
@@ -2,5 +2,6 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ export * from './harness';
5
6
  export * from './service';
6
7
  export * from './withPluginManager';
@@ -0,0 +1,50 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import React from 'react';
7
+ import { describe, test } from 'vitest';
8
+
9
+ import { DXN } from '@dxos/keys';
10
+
11
+ import { ActivationEvents, Capabilities } from '../common';
12
+ import { Capability, Plugin } from '../core';
13
+ import { Surface } from '../ui';
14
+ import { createTestApp } from './harness';
15
+ import { render, renderSurface } from './react';
16
+
17
+ const testMeta = Plugin.makeMeta({ key: DXN.make('org.dxos.plugin.test.reactHarness'), name: 'ReactHarnessTest' });
18
+
19
+ const TestPlugin = Plugin.define(testMeta).pipe(
20
+ Plugin.addModule({
21
+ id: 'surfaces',
22
+ activatesOn: ActivationEvents.SetupReactSurface,
23
+ activate: () =>
24
+ Effect.succeed(
25
+ Capability.contributes(Capabilities.ReactSurface, [
26
+ Surface.create<{ message: string }>({
27
+ id: 'greeting',
28
+ role: 'greeting',
29
+ component: ({ data }) => <span data-testid='greeting'>hello {data.message}</span>,
30
+ }),
31
+ ]),
32
+ ),
33
+ }),
34
+ Plugin.make,
35
+ );
36
+
37
+ describe('testing/react', () => {
38
+ test('render wraps ui in the harness provider tree', async ({ expect }) => {
39
+ await using harness = await createTestApp({ plugins: [TestPlugin()] });
40
+ const view = render(harness, <span data-testid='hello'>world</span>);
41
+ expect(view.getByTestId('hello').textContent).toBe('world');
42
+ });
43
+
44
+ test('renderSurface mounts a surface registered by a plugin', async ({ expect }) => {
45
+ await using harness = await createTestApp({ plugins: [TestPlugin()] });
46
+ const view = renderSurface(harness, { role: 'greeting', data: { message: 'plugins' } });
47
+ const node = await view.findByTestId('greeting');
48
+ expect(node.textContent).toBe('hello plugins');
49
+ });
50
+ });