@dxos/app-framework 0.8.4-main.ead640a → 0.8.4-main.effb148878

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 (572) hide show
  1. package/.storybook/main.mts +2 -4
  2. package/.storybook/preview.mts +2 -2
  3. package/LICENSE +102 -5
  4. package/README.md +1 -1
  5. package/dist/lib/browser/capability-C4WE22TJ.mjs +35 -0
  6. package/dist/lib/browser/capability-C4WE22TJ.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-2ZIYRDAF.mjs +95 -0
  8. package/dist/lib/browser/chunk-2ZIYRDAF.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-5GY3YOEL.mjs +28 -0
  10. package/dist/lib/browser/chunk-5GY3YOEL.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-66IXTIVK.mjs +48 -0
  12. package/dist/lib/browser/chunk-66IXTIVK.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-67GCXX5I.mjs +581 -0
  14. package/dist/lib/browser/chunk-67GCXX5I.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-FJ4765WW.mjs +8 -0
  16. package/dist/lib/browser/chunk-FJ4765WW.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-FO3IYSLV.mjs +68 -0
  18. package/dist/lib/browser/chunk-FO3IYSLV.mjs.map +7 -0
  19. package/dist/lib/browser/chunk-IW44C7UL.mjs +83 -0
  20. package/dist/lib/browser/chunk-IW44C7UL.mjs.map +7 -0
  21. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  22. package/dist/lib/browser/chunk-KLHQNYJ2.mjs +422 -0
  23. package/dist/lib/browser/chunk-KLHQNYJ2.mjs.map +7 -0
  24. package/dist/lib/browser/chunk-LPWOVOOB.mjs +142 -0
  25. package/dist/lib/browser/chunk-LPWOVOOB.mjs.map +7 -0
  26. package/dist/lib/browser/chunk-LUQOVTWB.mjs +43 -0
  27. package/dist/lib/browser/chunk-LUQOVTWB.mjs.map +7 -0
  28. package/dist/lib/browser/chunk-SLX73WRZ.mjs +218 -0
  29. package/dist/lib/browser/chunk-SLX73WRZ.mjs.map +7 -0
  30. package/dist/lib/browser/chunk-SZMB3K2N.mjs +517 -0
  31. package/dist/lib/browser/chunk-SZMB3K2N.mjs.map +7 -0
  32. package/dist/lib/browser/chunk-VJ5PFAWC.mjs +1446 -0
  33. package/dist/lib/browser/chunk-VJ5PFAWC.mjs.map +7 -0
  34. package/dist/lib/browser/cli/index.mjs +74 -0
  35. package/dist/lib/browser/cli/index.mjs.map +7 -0
  36. package/dist/lib/browser/common/activation-events.mjs +20 -0
  37. package/dist/lib/browser/common/capabilities.mjs +56 -0
  38. package/dist/lib/browser/core/activation-event.mjs +20 -0
  39. package/dist/lib/browser/core/capability.mjs +32 -0
  40. package/dist/lib/browser/core/capability.mjs.map +7 -0
  41. package/dist/lib/browser/core/plugin-manager.mjs +19 -0
  42. package/dist/lib/browser/core/plugin-manager.mjs.map +7 -0
  43. package/dist/lib/browser/core/plugin.mjs +39 -0
  44. package/dist/lib/browser/core/plugin.mjs.map +7 -0
  45. package/dist/lib/browser/core/url-loader.mjs +24 -0
  46. package/dist/lib/browser/core/url-loader.mjs.map +7 -0
  47. package/dist/lib/browser/index.mjs +85 -148
  48. package/dist/lib/browser/index.mjs.map +4 -4
  49. package/dist/lib/browser/meta.json +1 -1
  50. package/dist/lib/browser/process-manager-capability-3Q4TA73T.mjs +89 -0
  51. package/dist/lib/browser/process-manager-capability-3Q4TA73T.mjs.map +7 -0
  52. package/dist/lib/browser/testing/index.mjs +245 -47
  53. package/dist/lib/browser/testing/index.mjs.map +4 -4
  54. package/dist/lib/browser/testing/react.mjs +78 -0
  55. package/dist/lib/browser/testing/react.mjs.map +7 -0
  56. package/dist/lib/browser/ui/index.mjs +54 -0
  57. package/dist/lib/browser/ui/index.mjs.map +7 -0
  58. package/dist/lib/node-esm/capability-GPN6OS6M.mjs +36 -0
  59. package/dist/lib/node-esm/capability-GPN6OS6M.mjs.map +7 -0
  60. package/dist/lib/node-esm/chunk-37Z53PXZ.mjs +10 -0
  61. package/dist/lib/node-esm/chunk-37Z53PXZ.mjs.map +7 -0
  62. package/dist/lib/node-esm/chunk-42UNAKYO.mjs +423 -0
  63. package/dist/lib/node-esm/chunk-42UNAKYO.mjs.map +7 -0
  64. package/dist/lib/node-esm/chunk-6S45OMUP.mjs +219 -0
  65. package/dist/lib/node-esm/chunk-6S45OMUP.mjs.map +7 -0
  66. package/dist/lib/node-esm/chunk-CTKEZHKF.mjs +84 -0
  67. package/dist/lib/node-esm/chunk-CTKEZHKF.mjs.map +7 -0
  68. package/dist/lib/node-esm/chunk-FEVJEUD7.mjs +143 -0
  69. package/dist/lib/node-esm/chunk-FEVJEUD7.mjs.map +7 -0
  70. package/dist/lib/node-esm/chunk-GBHZF46K.mjs +518 -0
  71. package/dist/lib/node-esm/chunk-GBHZF46K.mjs.map +7 -0
  72. package/dist/lib/node-esm/chunk-GUE5V5CG.mjs +582 -0
  73. package/dist/lib/node-esm/chunk-GUE5V5CG.mjs.map +7 -0
  74. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  75. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  76. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs +29 -0
  77. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs.map +7 -0
  78. package/dist/lib/node-esm/chunk-MXWDXYV2.mjs +44 -0
  79. package/dist/lib/node-esm/chunk-MXWDXYV2.mjs.map +7 -0
  80. package/dist/lib/node-esm/chunk-QBUGLR4H.mjs +96 -0
  81. package/dist/lib/node-esm/chunk-QBUGLR4H.mjs.map +7 -0
  82. package/dist/lib/node-esm/chunk-SFYCO3PT.mjs +1447 -0
  83. package/dist/lib/node-esm/chunk-SFYCO3PT.mjs.map +7 -0
  84. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs +70 -0
  85. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs.map +7 -0
  86. package/dist/lib/node-esm/chunk-XOCUANHO.mjs +49 -0
  87. package/dist/lib/node-esm/chunk-XOCUANHO.mjs.map +7 -0
  88. package/dist/lib/node-esm/cli/index.mjs +75 -0
  89. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  90. package/dist/lib/node-esm/common/activation-events.mjs +21 -0
  91. package/dist/lib/node-esm/common/activation-events.mjs.map +7 -0
  92. package/dist/lib/node-esm/common/capabilities.mjs +57 -0
  93. package/dist/lib/node-esm/common/capabilities.mjs.map +7 -0
  94. package/dist/lib/node-esm/core/activation-event.mjs +21 -0
  95. package/dist/lib/node-esm/core/activation-event.mjs.map +7 -0
  96. package/dist/lib/node-esm/core/capability.mjs +33 -0
  97. package/dist/lib/node-esm/core/capability.mjs.map +7 -0
  98. package/dist/lib/node-esm/core/plugin-manager.mjs +20 -0
  99. package/dist/lib/node-esm/core/plugin-manager.mjs.map +7 -0
  100. package/dist/lib/node-esm/core/plugin.mjs +40 -0
  101. package/dist/lib/node-esm/core/plugin.mjs.map +7 -0
  102. package/dist/lib/node-esm/core/url-loader.mjs +25 -0
  103. package/dist/lib/node-esm/core/url-loader.mjs.map +7 -0
  104. package/dist/lib/node-esm/index.mjs +85 -148
  105. package/dist/lib/node-esm/index.mjs.map +4 -4
  106. package/dist/lib/node-esm/meta.json +1 -1
  107. package/dist/lib/node-esm/process-manager-capability-5KCLSNQM.mjs +90 -0
  108. package/dist/lib/node-esm/process-manager-capability-5KCLSNQM.mjs.map +7 -0
  109. package/dist/lib/node-esm/testing/index.mjs +245 -47
  110. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  111. package/dist/lib/node-esm/testing/react.mjs +79 -0
  112. package/dist/lib/node-esm/testing/react.mjs.map +7 -0
  113. package/dist/lib/node-esm/ui/index.mjs +55 -0
  114. package/dist/lib/node-esm/ui/index.mjs.map +7 -0
  115. package/dist/plugin/node-esm/index.mjs +893 -0
  116. package/dist/plugin/node-esm/index.mjs.map +7 -0
  117. package/dist/plugin/node-esm/meta.json +1 -0
  118. package/dist/types/src/cli/cli.d.ts +37 -0
  119. package/dist/types/src/cli/cli.d.ts.map +1 -0
  120. package/dist/types/src/cli/index.d.ts +2 -0
  121. package/dist/types/src/cli/index.d.ts.map +1 -0
  122. package/dist/types/src/common/activation-events.d.ts +24 -0
  123. package/dist/types/src/common/activation-events.d.ts.map +1 -0
  124. package/dist/types/src/common/annotations.d.ts +1 -0
  125. package/dist/types/src/common/annotations.d.ts.map +1 -0
  126. package/dist/types/src/common/capabilities.d.ts +214 -199
  127. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  128. package/dist/types/src/common/index.d.ts +4 -8
  129. package/dist/types/src/common/index.d.ts.map +1 -1
  130. package/dist/types/src/common/operations.d.ts +19 -0
  131. package/dist/types/src/common/operations.d.ts.map +1 -0
  132. package/dist/types/src/common/translations.d.ts +7 -7
  133. package/dist/types/src/common/translations.d.ts.map +1 -1
  134. package/dist/types/src/context.d.ts +5 -0
  135. package/dist/types/src/context.d.ts.map +1 -0
  136. package/dist/types/src/core/{events.d.ts → activation-event.d.ts} +11 -11
  137. package/dist/types/src/core/activation-event.d.ts.map +1 -0
  138. package/dist/types/src/core/capability-manager.d.ts +48 -0
  139. package/dist/types/src/core/capability-manager.d.ts.map +1 -0
  140. package/dist/types/src/core/capability-manager.test.d.ts +2 -0
  141. package/dist/types/src/core/capability-manager.test.d.ts.map +1 -0
  142. package/dist/types/src/core/capability.d.ts +161 -0
  143. package/dist/types/src/core/capability.d.ts.map +1 -0
  144. package/dist/types/src/core/edge-registry-plugin-provider.d.ts +30 -0
  145. package/dist/types/src/core/edge-registry-plugin-provider.d.ts.map +1 -0
  146. package/dist/types/src/core/index.d.ts +11 -4
  147. package/dist/types/src/core/index.d.ts.map +1 -1
  148. package/dist/types/src/core/plugin-asset-cache.d.ts +71 -0
  149. package/dist/types/src/core/plugin-asset-cache.d.ts.map +1 -0
  150. package/dist/types/src/core/plugin-manager.d.ts +297 -0
  151. package/dist/types/src/core/plugin-manager.d.ts.map +1 -0
  152. package/dist/types/src/core/plugin-manager.test.d.ts +2 -0
  153. package/dist/types/src/core/plugin-manager.test.d.ts.map +1 -0
  154. package/dist/types/src/core/plugin-manifest.d.ts +101 -0
  155. package/dist/types/src/core/plugin-manifest.d.ts.map +1 -0
  156. package/dist/types/src/core/plugin-manifest.test.d.ts +2 -0
  157. package/dist/types/src/core/plugin-manifest.test.d.ts.map +1 -0
  158. package/dist/types/src/core/plugin.d.ts +276 -39
  159. package/dist/types/src/core/plugin.d.ts.map +1 -1
  160. package/dist/types/src/core/registry.d.ts +107 -0
  161. package/dist/types/src/core/registry.d.ts.map +1 -0
  162. package/dist/types/src/core/url-loader.d.ts +127 -0
  163. package/dist/types/src/core/url-loader.d.ts.map +1 -0
  164. package/dist/types/src/core/url-loader.test.d.ts +2 -0
  165. package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
  166. package/dist/types/src/helpers.d.ts.map +1 -1
  167. package/dist/types/src/index.d.ts +2 -4
  168. package/dist/types/src/index.d.ts.map +1 -1
  169. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts +3 -0
  170. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts.map +1 -0
  171. package/dist/types/src/plugin-process-manager/history/capability.d.ts +7 -0
  172. package/dist/types/src/plugin-process-manager/history/capability.d.ts.map +1 -0
  173. package/dist/types/src/plugin-process-manager/history/errors.d.ts +32 -0
  174. package/dist/types/src/plugin-process-manager/history/errors.d.ts.map +1 -0
  175. package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts +18 -0
  176. package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts.map +1 -0
  177. package/dist/types/src/plugin-process-manager/history/history-tracker.test.d.ts +2 -0
  178. package/dist/types/src/plugin-process-manager/history/history-tracker.test.d.ts.map +1 -0
  179. package/dist/types/src/plugin-process-manager/history/index.d.ts +6 -0
  180. package/dist/types/src/plugin-process-manager/history/index.d.ts.map +1 -0
  181. package/dist/types/src/plugin-process-manager/history/types.d.ts +13 -0
  182. package/dist/types/src/plugin-process-manager/history/types.d.ts.map +1 -0
  183. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts +101 -0
  184. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts.map +1 -0
  185. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts +23 -0
  186. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts.map +1 -0
  187. package/dist/types/src/plugin-process-manager/history/undo-registry.test.d.ts +2 -0
  188. package/dist/types/src/plugin-process-manager/history/undo-registry.test.d.ts.map +1 -0
  189. package/dist/types/src/plugin-process-manager/index.d.ts +3 -0
  190. package/dist/types/src/plugin-process-manager/index.d.ts.map +1 -0
  191. package/dist/types/src/plugin-process-manager/meta.d.ts +3 -0
  192. package/dist/types/src/plugin-process-manager/meta.d.ts.map +1 -0
  193. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts +8 -0
  194. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -0
  195. package/dist/types/src/plugin-process-manager/testing.d.ts +59 -0
  196. package/dist/types/src/plugin-process-manager/testing.d.ts.map +1 -0
  197. package/dist/types/src/testing/harness.d.ts +79 -0
  198. package/dist/types/src/testing/harness.d.ts.map +1 -0
  199. package/dist/types/src/testing/index.d.ts +2 -0
  200. package/dist/types/src/testing/index.d.ts.map +1 -1
  201. package/dist/types/src/testing/react.d.ts +27 -0
  202. package/dist/types/src/testing/react.d.ts.map +1 -0
  203. package/dist/types/src/testing/react.test.d.ts +2 -0
  204. package/dist/types/src/testing/react.test.d.ts.map +1 -0
  205. package/dist/types/src/testing/service.d.ts +8 -0
  206. package/dist/types/src/testing/service.d.ts.map +1 -0
  207. package/dist/types/src/testing/withPluginManager.d.ts +7 -6
  208. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  209. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  210. package/dist/types/src/ui/components/App/App.d.ts +9 -0
  211. package/dist/types/src/ui/components/App/App.d.ts.map +1 -0
  212. package/dist/types/src/ui/components/App/App.stories.d.ts +19 -0
  213. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -0
  214. package/dist/types/src/ui/components/App/index.d.ts +2 -0
  215. package/dist/types/src/ui/components/App/index.d.ts.map +1 -0
  216. package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts +64 -0
  217. package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts.map +1 -0
  218. package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts +19 -0
  219. package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts.map +1 -0
  220. package/dist/types/src/ui/components/Placeholder/index.d.ts +2 -0
  221. package/dist/types/src/ui/components/Placeholder/index.d.ts.map +1 -0
  222. package/dist/types/src/{playground/playground.stories.d.ts → ui/components/PluginManager/PluginManagerContext.stories.d.ts} +5 -3
  223. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -0
  224. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +10 -0
  225. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -0
  226. package/dist/types/src/ui/components/PluginManager/index.d.ts +2 -0
  227. package/dist/types/src/ui/components/PluginManager/index.d.ts.map +1 -0
  228. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +24 -0
  229. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -0
  230. package/dist/types/src/{components/App.stories.d.ts → ui/components/Surface/SurfaceComponent.stories.d.ts} +1 -1
  231. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -0
  232. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts +11 -0
  233. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -0
  234. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
  235. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
  236. package/dist/types/src/ui/components/Surface/context.d.ts +5 -0
  237. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -0
  238. package/dist/types/src/ui/components/Surface/index.d.ts +36 -0
  239. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -0
  240. package/dist/types/src/ui/components/Surface/types.d.ts +197 -0
  241. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -0
  242. package/dist/types/src/ui/components/Surface/types.test.d.ts +2 -0
  243. package/dist/types/src/ui/components/Surface/types.test.d.ts.map +1 -0
  244. package/dist/types/src/ui/components/index.d.ts +5 -0
  245. package/dist/types/src/ui/components/index.d.ts.map +1 -0
  246. package/dist/types/src/ui/hooks/index.d.ts +7 -0
  247. package/dist/types/src/ui/hooks/index.d.ts.map +1 -0
  248. package/dist/types/src/ui/hooks/useApp.d.ts +86 -0
  249. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -0
  250. package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
  251. package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
  252. package/dist/types/src/ui/hooks/useCapabilities.d.ts +31 -0
  253. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -0
  254. package/dist/types/src/{components → ui/hooks}/useLoading.d.ts +1 -2
  255. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -0
  256. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts +30 -0
  257. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts.map +1 -0
  258. package/dist/types/src/ui/hooks/useSettingsState.d.ts +10 -0
  259. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -0
  260. package/dist/types/src/ui/hooks/useSurface.d.ts +3 -0
  261. package/dist/types/src/ui/hooks/useSurface.d.ts.map +1 -0
  262. package/dist/types/src/ui/index.d.ts +3 -0
  263. package/dist/types/src/ui/index.d.ts.map +1 -0
  264. package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts +34 -0
  265. package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts.map +1 -0
  266. package/dist/types/src/vite-plugin/boot-loader/index.d.ts +2 -0
  267. package/dist/types/src/vite-plugin/boot-loader/index.d.ts.map +1 -0
  268. package/dist/types/src/vite-plugin/boot-loader/loader.d.ts +51 -0
  269. package/dist/types/src/vite-plugin/boot-loader/loader.d.ts.map +1 -0
  270. package/dist/types/src/vite-plugin/composer/index.d.ts +34 -0
  271. package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -0
  272. package/dist/types/src/vite-plugin/import-map/index.d.ts +28 -0
  273. package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -0
  274. package/dist/types/src/vite-plugin/index.d.ts +5 -0
  275. package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
  276. package/dist/types/src/vite-plugin/manifest.d.ts +41 -0
  277. package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -0
  278. package/dist/types/src/vite-plugin/manifest.test.d.ts +2 -0
  279. package/dist/types/src/vite-plugin/manifest.test.d.ts.map +1 -0
  280. package/dist/types/src/vite-plugin/packages.d.ts +13 -0
  281. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
  282. package/dist/types/tsconfig.tsbuildinfo +1 -1
  283. package/moon.yml +25 -6
  284. package/package.json +119 -56
  285. package/src/cli/cli.ts +102 -0
  286. package/src/{components → cli}/index.ts +1 -1
  287. package/src/common/activation-events.ts +39 -0
  288. package/src/{playground/layout/index.ts → common/annotations.ts} +0 -2
  289. package/src/common/capabilities.ts +287 -195
  290. package/src/common/index.ts +4 -8
  291. package/src/common/operations.ts +36 -0
  292. package/src/common/translations.ts +17 -9
  293. package/src/context.ts +9 -0
  294. package/src/core/{events.ts → activation-event.ts} +10 -7
  295. package/src/core/capability-manager.test.ts +151 -0
  296. package/src/core/capability-manager.ts +192 -0
  297. package/src/core/capability.ts +254 -0
  298. package/src/core/edge-registry-plugin-provider.ts +92 -0
  299. package/src/core/index.ts +11 -4
  300. package/src/core/plugin-asset-cache.ts +60 -0
  301. package/src/core/plugin-manager.test.ts +1899 -0
  302. package/src/core/plugin-manager.ts +1687 -0
  303. package/src/core/plugin-manifest.test.ts +75 -0
  304. package/src/core/plugin-manifest.ts +134 -0
  305. package/src/core/plugin.ts +415 -45
  306. package/src/core/registry.ts +163 -0
  307. package/src/core/url-loader.test.ts +221 -0
  308. package/src/core/url-loader.ts +388 -0
  309. package/src/index.ts +2 -4
  310. package/src/plugin-process-manager/ProcessManagerPlugin.ts +24 -0
  311. package/src/plugin-process-manager/history/capability.ts +36 -0
  312. package/src/plugin-process-manager/history/errors.ts +7 -0
  313. package/src/plugin-process-manager/history/history-tracker.test.ts +374 -0
  314. package/src/plugin-process-manager/history/history-tracker.ts +128 -0
  315. package/src/plugin-process-manager/history/index.ts +9 -0
  316. package/src/plugin-process-manager/history/types.ts +17 -0
  317. package/src/plugin-process-manager/history/undo-mapping.ts +135 -0
  318. package/src/plugin-process-manager/history/undo-registry.test.ts +72 -0
  319. package/src/plugin-process-manager/history/undo-registry.ts +54 -0
  320. package/src/plugin-process-manager/index.ts +6 -0
  321. package/src/plugin-process-manager/meta.ts +14 -0
  322. package/src/plugin-process-manager/process-manager-capability.ts +178 -0
  323. package/src/plugin-process-manager/testing.ts +155 -0
  324. package/src/testing/harness.ts +247 -0
  325. package/src/testing/index.ts +2 -0
  326. package/src/testing/react.test.tsx +48 -0
  327. package/src/testing/react.tsx +113 -0
  328. package/src/testing/service.ts +52 -0
  329. package/src/testing/withPluginManager.stories.tsx +8 -9
  330. package/src/testing/withPluginManager.tsx +73 -42
  331. package/src/ui/components/App/App.stories.tsx +86 -0
  332. package/src/ui/components/App/App.tsx +81 -0
  333. package/src/{playground/debug → ui/components/App}/index.ts +1 -1
  334. package/src/ui/components/Placeholder/Placeholder.stories.tsx +77 -0
  335. package/src/ui/components/Placeholder/Placeholder.tsx +156 -0
  336. package/src/{playground/logger → ui/components/Placeholder}/index.ts +1 -1
  337. package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +184 -0
  338. package/src/{react → ui/components/PluginManager}/PluginManagerProvider.ts +3 -3
  339. package/src/ui/components/PluginManager/index.ts +5 -0
  340. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +144 -0
  341. package/src/ui/components/Surface/SurfaceComponent.tsx +303 -0
  342. package/src/ui/components/Surface/SurfaceInfo.tsx +106 -0
  343. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
  344. package/src/ui/components/Surface/context.ts +12 -0
  345. package/src/ui/components/Surface/index.ts +54 -0
  346. package/src/ui/components/Surface/types.test.ts +126 -0
  347. package/src/ui/components/Surface/types.ts +269 -0
  348. package/src/ui/components/index.ts +8 -0
  349. package/src/ui/hooks/index.ts +10 -0
  350. package/src/ui/hooks/useApp.test.tsx +159 -0
  351. package/src/ui/hooks/useApp.tsx +418 -0
  352. package/src/ui/hooks/useCapabilities.ts +68 -0
  353. package/src/{components → ui/hooks}/useLoading.tsx +16 -10
  354. package/src/ui/hooks/useProcessManagerRuntime.ts +78 -0
  355. package/src/ui/hooks/useSettingsState.ts +26 -0
  356. package/src/ui/hooks/useSurface.ts +13 -0
  357. package/src/ui/index.ts +6 -0
  358. package/src/vite-plugin/boot-loader/BootLoader.stories.tsx +270 -0
  359. package/src/vite-plugin/boot-loader/boot-loader.css +320 -0
  360. package/src/vite-plugin/boot-loader/boot-loader.js +325 -0
  361. package/src/vite-plugin/boot-loader/index.ts +5 -0
  362. package/src/vite-plugin/boot-loader/loader.ts +123 -0
  363. package/src/vite-plugin/composer/index.ts +306 -0
  364. package/src/vite-plugin/import-map/index.ts +527 -0
  365. package/src/vite-plugin/index.ts +10 -0
  366. package/src/vite-plugin/manifest.test.ts +46 -0
  367. package/src/vite-plugin/manifest.ts +57 -0
  368. package/src/vite-plugin/packages.ts +187 -0
  369. package/tsconfig.json +30 -15
  370. package/tsconfig.node.json +2 -4
  371. package/typedoc.json +2 -4
  372. package/vitest.config.ts +1 -1
  373. package/.swc/plugins/linux_x86_64_19.0.0/727453fb3a62f7f1d952a41e051ca8a6f88cadc45cee43c6a4d1aa45f9b75665.wasmer-v7 +0 -0
  374. package/.swc/plugins/linux_x86_64_19.0.0/fce1bdb8e20a094e4af08bad09cc81497ed0e2e7c51223b07d371063cca18429.wasmer-v7 +0 -0
  375. package/dist/lib/browser/app-graph-builder-LG4RG2LM.mjs +0 -138
  376. package/dist/lib/browser/app-graph-builder-LG4RG2LM.mjs.map +0 -7
  377. package/dist/lib/browser/chunk-2GRQ4QXA.mjs +0 -1646
  378. package/dist/lib/browser/chunk-2GRQ4QXA.mjs.map +0 -7
  379. package/dist/lib/browser/chunk-FRUTKCPG.mjs +0 -467
  380. package/dist/lib/browser/chunk-FRUTKCPG.mjs.map +0 -7
  381. package/dist/lib/browser/chunk-SCPE4ZO2.mjs +0 -35
  382. package/dist/lib/browser/chunk-SCPE4ZO2.mjs.map +0 -7
  383. package/dist/lib/browser/intent-dispatcher-6SHA5B3N.mjs +0 -11
  384. package/dist/lib/browser/intent-resolver-UZZ4OANZ.mjs +0 -39
  385. package/dist/lib/browser/intent-resolver-UZZ4OANZ.mjs.map +0 -7
  386. package/dist/lib/browser/store-ACBEYK4B.mjs +0 -30
  387. package/dist/lib/browser/store-ACBEYK4B.mjs.map +0 -7
  388. package/dist/lib/browser/worker.mjs +0 -77
  389. package/dist/lib/node-esm/app-graph-builder-FMHVHPWA.mjs +0 -139
  390. package/dist/lib/node-esm/app-graph-builder-FMHVHPWA.mjs.map +0 -7
  391. package/dist/lib/node-esm/chunk-CXT6CYPE.mjs +0 -468
  392. package/dist/lib/node-esm/chunk-CXT6CYPE.mjs.map +0 -7
  393. package/dist/lib/node-esm/chunk-KSPOOYT3.mjs +0 -1648
  394. package/dist/lib/node-esm/chunk-KSPOOYT3.mjs.map +0 -7
  395. package/dist/lib/node-esm/chunk-ZX63QUGE.mjs +0 -37
  396. package/dist/lib/node-esm/chunk-ZX63QUGE.mjs.map +0 -7
  397. package/dist/lib/node-esm/intent-dispatcher-SIYQ5ZIU.mjs +0 -12
  398. package/dist/lib/node-esm/intent-resolver-7FYJMXAG.mjs +0 -40
  399. package/dist/lib/node-esm/intent-resolver-7FYJMXAG.mjs.map +0 -7
  400. package/dist/lib/node-esm/store-6OBLTVXC.mjs +0 -31
  401. package/dist/lib/node-esm/store-6OBLTVXC.mjs.map +0 -7
  402. package/dist/lib/node-esm/worker.mjs +0 -78
  403. package/dist/types/src/common/collaboration.d.ts +0 -20
  404. package/dist/types/src/common/collaboration.d.ts.map +0 -1
  405. package/dist/types/src/common/events.d.ts +0 -52
  406. package/dist/types/src/common/events.d.ts.map +0 -1
  407. package/dist/types/src/common/file.d.ts +0 -14
  408. package/dist/types/src/common/file.d.ts.map +0 -1
  409. package/dist/types/src/common/graph.d.ts +0 -21
  410. package/dist/types/src/common/graph.d.ts.map +0 -1
  411. package/dist/types/src/common/layout.d.ts +0 -279
  412. package/dist/types/src/common/layout.d.ts.map +0 -1
  413. package/dist/types/src/common/surface.d.ts +0 -59
  414. package/dist/types/src/common/surface.d.ts.map +0 -1
  415. package/dist/types/src/components/App.d.ts +0 -10
  416. package/dist/types/src/components/App.d.ts.map +0 -1
  417. package/dist/types/src/components/App.stories.d.ts.map +0 -1
  418. package/dist/types/src/components/DefaultFallback.d.ts +0 -8
  419. package/dist/types/src/components/DefaultFallback.d.ts.map +0 -1
  420. package/dist/types/src/components/index.d.ts +0 -2
  421. package/dist/types/src/components/index.d.ts.map +0 -1
  422. package/dist/types/src/components/useApp.d.ts +0 -44
  423. package/dist/types/src/components/useApp.d.ts.map +0 -1
  424. package/dist/types/src/components/useLoading.d.ts.map +0 -1
  425. package/dist/types/src/core/capabilities.d.ts +0 -117
  426. package/dist/types/src/core/capabilities.d.ts.map +0 -1
  427. package/dist/types/src/core/capabilities.test.d.ts +0 -2
  428. package/dist/types/src/core/capabilities.test.d.ts.map +0 -1
  429. package/dist/types/src/core/events.d.ts.map +0 -1
  430. package/dist/types/src/core/manager.d.ts +0 -126
  431. package/dist/types/src/core/manager.d.ts.map +0 -1
  432. package/dist/types/src/core/manager.test.d.ts +0 -2
  433. package/dist/types/src/core/manager.test.d.ts.map +0 -1
  434. package/dist/types/src/playground/debug/Debug.d.ts +0 -6
  435. package/dist/types/src/playground/debug/Debug.d.ts.map +0 -1
  436. package/dist/types/src/playground/debug/index.d.ts +0 -2
  437. package/dist/types/src/playground/debug/index.d.ts.map +0 -1
  438. package/dist/types/src/playground/debug/plugin.d.ts +0 -2
  439. package/dist/types/src/playground/debug/plugin.d.ts.map +0 -1
  440. package/dist/types/src/playground/generator/Main.d.ts +0 -6
  441. package/dist/types/src/playground/generator/Main.d.ts.map +0 -1
  442. package/dist/types/src/playground/generator/Toolbar.d.ts +0 -6
  443. package/dist/types/src/playground/generator/Toolbar.d.ts.map +0 -1
  444. package/dist/types/src/playground/generator/generator.d.ts +0 -7
  445. package/dist/types/src/playground/generator/generator.d.ts.map +0 -1
  446. package/dist/types/src/playground/generator/index.d.ts +0 -3
  447. package/dist/types/src/playground/generator/index.d.ts.map +0 -1
  448. package/dist/types/src/playground/generator/plugin.d.ts +0 -2
  449. package/dist/types/src/playground/generator/plugin.d.ts.map +0 -1
  450. package/dist/types/src/playground/layout/Layout.d.ts +0 -8
  451. package/dist/types/src/playground/layout/Layout.d.ts.map +0 -1
  452. package/dist/types/src/playground/layout/index.d.ts +0 -2
  453. package/dist/types/src/playground/layout/index.d.ts.map +0 -1
  454. package/dist/types/src/playground/layout/plugin.d.ts +0 -2
  455. package/dist/types/src/playground/layout/plugin.d.ts.map +0 -1
  456. package/dist/types/src/playground/logger/Toolbar.d.ts +0 -6
  457. package/dist/types/src/playground/logger/Toolbar.d.ts.map +0 -1
  458. package/dist/types/src/playground/logger/index.d.ts +0 -2
  459. package/dist/types/src/playground/logger/index.d.ts.map +0 -1
  460. package/dist/types/src/playground/logger/plugin.d.ts +0 -2
  461. package/dist/types/src/playground/logger/plugin.d.ts.map +0 -1
  462. package/dist/types/src/playground/logger/schema.d.ts +0 -13
  463. package/dist/types/src/playground/logger/schema.d.ts.map +0 -1
  464. package/dist/types/src/playground/playground.stories.d.ts.map +0 -1
  465. package/dist/types/src/plugin-intent/IntentPlugin.d.ts +0 -2
  466. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +0 -1
  467. package/dist/types/src/plugin-intent/actions.d.ts +0 -36
  468. package/dist/types/src/plugin-intent/actions.d.ts.map +0 -1
  469. package/dist/types/src/plugin-intent/errors.d.ts +0 -16
  470. package/dist/types/src/plugin-intent/errors.d.ts.map +0 -1
  471. package/dist/types/src/plugin-intent/index.d.ts +0 -6
  472. package/dist/types/src/plugin-intent/index.d.ts.map +0 -1
  473. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +0 -139
  474. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +0 -1
  475. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts +0 -2
  476. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts.map +0 -1
  477. package/dist/types/src/plugin-intent/intent.d.ts +0 -63
  478. package/dist/types/src/plugin-intent/intent.d.ts.map +0 -1
  479. package/dist/types/src/plugin-intent/meta.d.ts +0 -3
  480. package/dist/types/src/plugin-intent/meta.d.ts.map +0 -1
  481. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +0 -2
  482. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +0 -1
  483. package/dist/types/src/plugin-settings/actions.d.ts +0 -25
  484. package/dist/types/src/plugin-settings/actions.d.ts.map +0 -1
  485. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -4
  486. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  487. package/dist/types/src/plugin-settings/index.d.ts +0 -3
  488. package/dist/types/src/plugin-settings/index.d.ts.map +0 -1
  489. package/dist/types/src/plugin-settings/intent-resolver.d.ts +0 -4
  490. package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +0 -1
  491. package/dist/types/src/plugin-settings/meta.d.ts +0 -3
  492. package/dist/types/src/plugin-settings/meta.d.ts.map +0 -1
  493. package/dist/types/src/plugin-settings/store.d.ts +0 -5
  494. package/dist/types/src/plugin-settings/store.d.ts.map +0 -1
  495. package/dist/types/src/plugin-settings/translations.d.ts +0 -11
  496. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  497. package/dist/types/src/react/ErrorBoundary.d.ts +0 -30
  498. package/dist/types/src/react/ErrorBoundary.d.ts.map +0 -1
  499. package/dist/types/src/react/IntentContext.d.ts +0 -8
  500. package/dist/types/src/react/IntentContext.d.ts.map +0 -1
  501. package/dist/types/src/react/PluginManagerProvider.d.ts +0 -10
  502. package/dist/types/src/react/PluginManagerProvider.d.ts.map +0 -1
  503. package/dist/types/src/react/Surface.d.ts +0 -12
  504. package/dist/types/src/react/Surface.d.ts.map +0 -1
  505. package/dist/types/src/react/Surface.stories.d.ts +0 -17
  506. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  507. package/dist/types/src/react/common.d.ts +0 -13
  508. package/dist/types/src/react/common.d.ts.map +0 -1
  509. package/dist/types/src/react/index.d.ts +0 -7
  510. package/dist/types/src/react/index.d.ts.map +0 -1
  511. package/dist/types/src/react/useCapabilities.d.ts +0 -13
  512. package/dist/types/src/react/useCapabilities.d.ts.map +0 -1
  513. package/dist/types/src/react/useIntentResolver.d.ts +0 -3
  514. package/dist/types/src/react/useIntentResolver.d.ts.map +0 -1
  515. package/dist/types/src/worker.d.ts +0 -4
  516. package/dist/types/src/worker.d.ts.map +0 -1
  517. package/src/common/collaboration.ts +0 -18
  518. package/src/common/events.ts +0 -79
  519. package/src/common/file.ts +0 -22
  520. package/src/common/graph.ts +0 -30
  521. package/src/common/layout.ts +0 -277
  522. package/src/common/surface.ts +0 -83
  523. package/src/components/App.stories.tsx +0 -33
  524. package/src/components/App.tsx +0 -59
  525. package/src/components/DefaultFallback.tsx +0 -26
  526. package/src/components/useApp.tsx +0 -164
  527. package/src/core/capabilities.test.ts +0 -136
  528. package/src/core/capabilities.ts +0 -259
  529. package/src/core/manager.test.ts +0 -516
  530. package/src/core/manager.ts +0 -604
  531. package/src/playground/debug/Debug.tsx +0 -39
  532. package/src/playground/debug/plugin.ts +0 -16
  533. package/src/playground/generator/Main.tsx +0 -71
  534. package/src/playground/generator/Toolbar.tsx +0 -47
  535. package/src/playground/generator/generator.ts +0 -48
  536. package/src/playground/generator/index.ts +0 -6
  537. package/src/playground/generator/plugin.ts +0 -22
  538. package/src/playground/layout/Layout.tsx +0 -33
  539. package/src/playground/layout/plugin.ts +0 -18
  540. package/src/playground/logger/Toolbar.tsx +0 -30
  541. package/src/playground/logger/plugin.ts +0 -41
  542. package/src/playground/logger/schema.ts +0 -12
  543. package/src/playground/playground.stories.tsx +0 -46
  544. package/src/plugin-intent/IntentPlugin.ts +0 -20
  545. package/src/plugin-intent/actions.ts +0 -31
  546. package/src/plugin-intent/errors.ts +0 -40
  547. package/src/plugin-intent/index.ts +0 -9
  548. package/src/plugin-intent/intent-dispatcher.test.ts +0 -286
  549. package/src/plugin-intent/intent-dispatcher.ts +0 -337
  550. package/src/plugin-intent/intent.ts +0 -154
  551. package/src/plugin-intent/meta.ts +0 -10
  552. package/src/plugin-settings/SettingsPlugin.ts +0 -34
  553. package/src/plugin-settings/actions.ts +0 -25
  554. package/src/plugin-settings/app-graph-builder.ts +0 -160
  555. package/src/plugin-settings/index.ts +0 -6
  556. package/src/plugin-settings/intent-resolver.ts +0 -35
  557. package/src/plugin-settings/meta.ts +0 -10
  558. package/src/plugin-settings/store.ts +0 -33
  559. package/src/plugin-settings/translations.ts +0 -19
  560. package/src/react/ErrorBoundary.tsx +0 -56
  561. package/src/react/IntentContext.tsx +0 -35
  562. package/src/react/Surface.stories.tsx +0 -101
  563. package/src/react/Surface.tsx +0 -86
  564. package/src/react/common.ts +0 -13
  565. package/src/react/index.ts +0 -10
  566. package/src/react/useCapabilities.ts +0 -31
  567. package/src/react/useIntentResolver.ts +0 -22
  568. package/src/worker.ts +0 -11
  569. /package/dist/lib/browser/{intent-dispatcher-6SHA5B3N.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  570. /package/dist/lib/browser/{worker.mjs.map → common/activation-events.mjs.map} +0 -0
  571. /package/dist/lib/{node-esm/intent-dispatcher-SIYQ5ZIU.mjs.map → browser/common/capabilities.mjs.map} +0 -0
  572. /package/dist/lib/{node-esm/worker.mjs.map → browser/core/activation-event.mjs.map} +0 -0
@@ -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,4 +2,6 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ export * from './harness';
6
+ export * from './service';
5
7
  export * from './withPluginManager';
@@ -0,0 +1,48 @@
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 { ActivationEvents, Capabilities } from '../common';
10
+ import { Capability, Plugin } from '../core';
11
+ import { Surface } from '../ui';
12
+ import { createTestApp } from './harness';
13
+ import { render, renderSurface } from './react';
14
+
15
+ const testMeta = { id: 'org.dxos.plugin.test.react-harness', name: 'ReactHarnessTest' };
16
+
17
+ const TestPlugin = Plugin.define(testMeta).pipe(
18
+ Plugin.addModule({
19
+ id: 'surfaces',
20
+ activatesOn: ActivationEvents.SetupReactSurface,
21
+ activate: () =>
22
+ Effect.succeed(
23
+ Capability.contributes(Capabilities.ReactSurface, [
24
+ Surface.create<{ message: string }>({
25
+ id: 'greeting',
26
+ role: 'greeting',
27
+ component: ({ data }) => <span data-testid='greeting'>hello {data.message}</span>,
28
+ }),
29
+ ]),
30
+ ),
31
+ }),
32
+ Plugin.make,
33
+ );
34
+
35
+ describe('testing/react', () => {
36
+ test('render wraps ui in the harness provider tree', async ({ expect }) => {
37
+ await using harness = await createTestApp({ plugins: [TestPlugin()] });
38
+ const view = render(harness, <span data-testid='hello'>world</span>);
39
+ expect(view.getByTestId('hello').textContent).toBe('world');
40
+ });
41
+
42
+ test('renderSurface mounts a surface registered by a plugin', async ({ expect }) => {
43
+ await using harness = await createTestApp({ plugins: [TestPlugin()] });
44
+ const view = renderSurface(harness, { role: 'greeting', data: { message: 'plugins' } });
45
+ const node = await view.findByTestId('greeting');
46
+ expect(node.textContent).toBe('hello plugins');
47
+ });
48
+ });
@@ -0,0 +1,113 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { RegistryContext } from '@effect-atom/atom-react';
6
+ import { render as rtlRender, type RenderOptions, type RenderResult } from '@testing-library/react';
7
+ import React, { type FC, Fragment, type PropsWithChildren, type ReactNode } from 'react';
8
+
9
+ import { ContextProtocolProvider } from '@dxos/web-context-react';
10
+
11
+ import { Capabilities } from '../common';
12
+ import { PluginManagerContext } from '../context';
13
+ import { topologicalSort } from '../helpers';
14
+ import { PluginManagerProvider } from '../ui/components/PluginManager/PluginManagerProvider';
15
+ import { SurfaceComponent } from '../ui/components/Surface/SurfaceComponent';
16
+ import { type TestHarness } from './harness';
17
+
18
+ export type HarnessRenderOptions = Omit<RenderOptions, 'wrapper'> & {
19
+ /** Additional providers to wrap around the harness tree (applied innermost first). */
20
+ reactContexts?: FC<PropsWithChildren>[];
21
+ };
22
+
23
+ /**
24
+ * Renders `ui` wrapped in the same provider tree as `useApp` plus every contributed
25
+ * `Capabilities.ReactContext`.
26
+ */
27
+ export const render = (harness: TestHarness, ui: ReactNode, options?: HarnessRenderOptions): RenderResult => {
28
+ const { reactContexts = [], ...rest } = options ?? {};
29
+ const Wrapper = ({ children }: PropsWithChildren) => (
30
+ <HarnessProviders harness={harness} extra={reactContexts}>
31
+ {children}
32
+ </HarnessProviders>
33
+ );
34
+ return rtlRender(<>{ui}</>, { ...rest, wrapper: Wrapper });
35
+ };
36
+
37
+ export type RenderSurfaceProps = {
38
+ role: string;
39
+ data?: unknown;
40
+ limit?: number;
41
+ fallback?: FC<{ error: Error; data?: any }>;
42
+ placeholder?: ReactNode;
43
+ };
44
+
45
+ /**
46
+ * Renders a `Surface` with the given role/data inside the harness provider tree.
47
+ */
48
+ export const renderSurface = (
49
+ harness: TestHarness,
50
+ props: RenderSurfaceProps,
51
+ options?: HarnessRenderOptions,
52
+ ): RenderResult => {
53
+ const { role, data, limit, fallback, placeholder } = props;
54
+ return render(
55
+ harness,
56
+ <SurfaceComponent role={role} data={data as any} limit={limit} fallback={fallback} placeholder={placeholder} />,
57
+ options,
58
+ );
59
+ };
60
+
61
+ type HarnessProvidersProps = PropsWithChildren<{
62
+ harness: TestHarness;
63
+ extra: FC<PropsWithChildren>[];
64
+ }>;
65
+
66
+ const HarnessProviders = ({ harness, extra, children }: HarnessProvidersProps) => {
67
+ const contributed = harness.getAll(Capabilities.ReactContext);
68
+ const ContributedContext = composeContexts(contributed);
69
+ const ExtraContext = composeExtra(extra);
70
+ return (
71
+ <PluginManagerProvider value={harness.manager}>
72
+ <ContextProtocolProvider value={harness.manager} context={PluginManagerContext}>
73
+ <RegistryContext.Provider value={harness.registry}>
74
+ <ContributedContext>
75
+ <ExtraContext>{children}</ExtraContext>
76
+ </ContributedContext>
77
+ </RegistryContext.Provider>
78
+ </ContextProtocolProvider>
79
+ </PluginManagerProvider>
80
+ );
81
+ };
82
+
83
+ const composeContexts = (contexts: Capabilities.ReactContext[]): FC<PropsWithChildren> => {
84
+ if (contexts.length === 0) {
85
+ return Passthrough;
86
+ }
87
+ return topologicalSort(contexts)
88
+ .map(({ context }) => context)
89
+ .reduce((Acc, Next) => ({ children }: PropsWithChildren) => (
90
+ <Acc>
91
+ <Next>{children}</Next>
92
+ </Acc>
93
+ ));
94
+ };
95
+
96
+ // Composes in innermost-first order: the first context in the array wraps
97
+ // `children` directly; subsequent contexts wrap the accumulator.
98
+ const composeExtra = (contexts: FC<PropsWithChildren>[]): FC<PropsWithChildren> => {
99
+ if (contexts.length === 0) {
100
+ return Passthrough;
101
+ }
102
+ return contexts.reduce<FC<PropsWithChildren>>(
103
+ (Acc, Next) =>
104
+ ({ children }: PropsWithChildren) => (
105
+ <Next>
106
+ <Acc>{children}</Acc>
107
+ </Next>
108
+ ),
109
+ Passthrough,
110
+ );
111
+ };
112
+
113
+ const Passthrough: FC<PropsWithChildren> = ({ children }) => <Fragment>{children}</Fragment>;
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Layer from 'effect/Layer';
7
+
8
+ import { invariant } from '@dxos/invariant';
9
+
10
+ import { ActivationEvents, Capabilities } from '../common';
11
+ import { Plugin, PluginManager } from '../core';
12
+
13
+ /**
14
+ * Creates a Plugin.Service layer from a list of plugins.
15
+ * This is primarily used for testing.
16
+ */
17
+ export const fromPlugins = (plugins: Plugin.Plugin[]) =>
18
+ Layer.effect(
19
+ Plugin.Service,
20
+ Effect.gen(function* () {
21
+ // TODO(wittjosiah): Try to dedupe logic between here, createCliApp and useApp.
22
+
23
+ const pluginLoader = (id: string) =>
24
+ Effect.sync(() => {
25
+ const plugin = plugins.find((plugin) => plugin.meta.id === id);
26
+ invariant(plugin, `Plugin not found: ${id}`);
27
+ return { plugin };
28
+ });
29
+
30
+ const manager = PluginManager.make({
31
+ pluginLoader,
32
+ plugins,
33
+ enabled: plugins.map((plugin) => plugin.meta.id),
34
+ });
35
+
36
+ manager.capabilities.contribute({
37
+ interface: Capabilities.PluginManager,
38
+ implementation: manager,
39
+ module: 'org.dxos.app-framework.plugin-manager',
40
+ });
41
+
42
+ manager.capabilities.contribute({
43
+ interface: Capabilities.AtomRegistry,
44
+ implementation: manager.registry,
45
+ module: 'org.dxos.app-framework.atom-registry',
46
+ });
47
+
48
+ yield* manager.activate(ActivationEvents.Startup);
49
+
50
+ return manager;
51
+ }),
52
+ );
@@ -7,10 +7,9 @@ import React from 'react';
7
7
 
8
8
  import { withTheme } from '@dxos/react-ui/testing';
9
9
 
10
- import { Capabilities, createSurface } from '../common';
11
- import { contributes } from '../core';
12
- import { Surface } from '../react';
13
-
10
+ import { Capabilities } from '../common';
11
+ import { Capability } from '../core';
12
+ import { Surface } from '../ui';
14
13
  import { withPluginManager } from './withPluginManager';
15
14
 
16
15
  const DefaultStory = () => {
@@ -18,21 +17,21 @@ const DefaultStory = () => {
18
17
  return (
19
18
  <div>
20
19
  <div>Hello</div>
21
- <Surface role='main' />
20
+ <Surface.Surface role='main' />
22
21
  </div>
23
22
  );
24
23
  };
25
24
 
26
25
  const meta = {
27
- title: 'sdk/app-framework/withPluginManager',
26
+ title: 'sdk/app-framework/testing/withPluginManager',
28
27
  render: DefaultStory,
29
28
  decorators: [
30
- withTheme,
29
+ withTheme(),
31
30
  withPluginManager({
32
31
  capabilities: [
33
- contributes(
32
+ Capability.contributes(
34
33
  Capabilities.ReactSurface,
35
- createSurface({
34
+ Surface.create({
36
35
  id: 'test',
37
36
  role: 'main',
38
37
  component: ({ role }) => <span>{JSON.stringify({ role })}</span>,
@@ -2,24 +2,18 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Decorator } from '@storybook/react';
6
- import React, { useEffect, useMemo } from 'react';
5
+ import { type Decorator, type StoryContext } from '@storybook/react';
6
+ import * as Effect from 'effect/Effect';
7
+ import React, { useEffect, useState } from 'react';
7
8
 
8
9
  import { raise } from '@dxos/debug';
10
+ import { runAndForwardErrors } from '@dxos/effect';
9
11
  import { useAsyncEffect } from '@dxos/react-hooks';
10
12
  import { type MaybeProvider, getProviderValue } from '@dxos/util';
11
13
 
12
- import { Capabilities, Events } from '../common';
13
- import { type UseAppOptions, useApp } from '../components';
14
- import {
15
- type ActivationEvent,
16
- type AnyCapability,
17
- type PluginContext,
18
- PluginManager,
19
- contributes,
20
- defineModule,
21
- definePlugin,
22
- } from '../core';
14
+ import { ActivationEvents, Capabilities } from '../common';
15
+ import { type ActivationEvent, Capability, type CapabilityManager, Plugin, PluginManager } from '../core';
16
+ import { type UseAppOptions, useApp } from '../ui';
23
17
 
24
18
  /**
25
19
  * @internal
@@ -27,19 +21,21 @@ import {
27
21
  export const setupPluginManager = ({
28
22
  capabilities,
29
23
  plugins = [],
30
- core = plugins.map(({ meta }) => meta.id),
31
24
  ...options
32
25
  }: UseAppOptions & Pick<WithPluginManagerOptions, 'capabilities'> = {}) => {
33
- const pluginManager = new PluginManager({
26
+ // Auto-enable every non-system plugin so stories don't have to spell out
27
+ // enablement. System-tagged plugins are force-enabled by the manager.
28
+ const enabled = plugins.filter(({ meta }) => !meta.tags?.includes('system')).map(({ meta }) => meta.id);
29
+ const pluginManager = PluginManager.make({
34
30
  pluginLoader: () => raise(new Error('Not implemented')),
35
- plugins: [StoryPlugin(), ...plugins],
36
- core: [StoryPlugin.meta.id, ...core],
31
+ plugins: [StoryPlugin, ...plugins],
32
+ enabled,
37
33
  ...options,
38
34
  });
39
35
 
40
36
  if (capabilities) {
41
- getProviderValue(capabilities, pluginManager.context).forEach((capability) => {
42
- pluginManager.context.contributeCapability({
37
+ getProviderValue(capabilities, pluginManager.capabilities).forEach((capability) => {
38
+ pluginManager.capabilities.contribute({
43
39
  interface: capability.interface,
44
40
  implementation: capability.implementation,
45
41
  module: 'story',
@@ -50,57 +46,92 @@ export const setupPluginManager = ({
50
46
  return pluginManager;
51
47
  };
52
48
 
49
+ type ManagedPluginManagerState = {
50
+ fireEvents?: (ActivationEvent.ActivationEvent | string)[];
51
+ pluginManager: PluginManager.PluginManager;
52
+ setupEvents?: ActivationEvent.ActivationEvent[];
53
+ storyId: string;
54
+ };
55
+
53
56
  export type WithPluginManagerOptions = UseAppOptions & {
54
57
  /** @deprecated */
55
- capabilities?: MaybeProvider<AnyCapability[], PluginContext>;
58
+ capabilities?: MaybeProvider<Capability.Any[], CapabilityManager.CapabilityManager>;
56
59
  /** @deprecated */
57
- fireEvents?: (ActivationEvent | string)[];
60
+ fireEvents?: (ActivationEvent.ActivationEvent | string)[];
58
61
  };
59
62
 
63
+ export type WithPluginManagerInitializer<Args = void> =
64
+ | WithPluginManagerOptions
65
+ | ((context: StoryContext<Args>) => WithPluginManagerOptions);
66
+
60
67
  /**
61
68
  * Wraps a story with a plugin manager.
62
69
  * NOTE: This builds up and tears down the plugin manager on every render.
63
70
  */
64
- export const withPluginManager = (options: WithPluginManagerOptions = {}): Decorator => {
71
+ export const withPluginManager = <Args,>(init: WithPluginManagerInitializer<Args> = {}): Decorator => {
65
72
  return (Story, context) => {
66
- const pluginManager = useMemo(() => setupPluginManager(options), [options]);
73
+ const storyId = context.id;
74
+ const options = typeof init === 'function' ? init(context as any) : init;
75
+ const [managerState, setManagerState] = useState<ManagedPluginManagerState>();
67
76
 
68
- // Set-up root capability.
77
+ // Storybook replaces the full context object often, so key manager ownership by story id.
69
78
  useEffect(() => {
70
- const capability = contributes(Capabilities.ReactRoot, {
71
- id: context.id,
79
+ const pluginManager = setupPluginManager(options);
80
+ const capability = Capability.contributes(Capabilities.ReactRoot, {
81
+ id: storyId,
72
82
  root: () => <Story />,
73
83
  });
74
84
 
75
- pluginManager.context.contributeCapability({
85
+ pluginManager.capabilities.contribute({
76
86
  ...capability,
77
- module: 'dxos.org/app-framework/withPluginManager',
87
+ module: 'org.dxos.app-framework.with-plugin-manager',
88
+ });
89
+
90
+ setManagerState({
91
+ pluginManager,
92
+ setupEvents: options.setupEvents,
93
+ fireEvents: options.fireEvents,
94
+ storyId,
78
95
  });
79
96
 
80
97
  return () => {
81
- pluginManager.context.removeCapability(capability.interface, capability.implementation);
98
+ pluginManager.capabilities.remove(capability.interface, capability.implementation);
99
+ void runAndForwardErrors(pluginManager.shutdown());
82
100
  };
83
- }, [pluginManager, context]);
101
+ }, [storyId, init]);
84
102
 
85
- // Fire events.
86
- useAsyncEffect(async () => {
87
- await Promise.all(options.fireEvents?.map((event) => pluginManager.activate(event)) ?? []);
88
- }, [pluginManager]);
103
+ // Avoid mounting useApp with a stale manager from the previous story.
104
+ if (!managerState || managerState.storyId !== storyId) {
105
+ return <></>;
106
+ }
89
107
 
90
- // Create app.
91
- const App = useApp({ pluginManager });
92
-
93
- return <App />;
108
+ return <WithPluginManagerApp {...managerState} />;
94
109
  };
95
110
  };
96
111
 
112
+ const WithPluginManagerApp = ({ fireEvents, pluginManager, setupEvents, storyId }: ManagedPluginManagerState) => {
113
+ // Fire deprecated events only after the effect-owned manager for this story exists.
114
+ useAsyncEffect(async () => {
115
+ await Promise.all(fireEvents?.map((event) => pluginManager.activate(event)) ?? []);
116
+ }, [fireEvents, pluginManager, storyId]);
117
+
118
+ const App = useApp({ pluginManager, setupEvents });
119
+ return <App />;
120
+ };
121
+
97
122
  const storyMeta = {
98
- id: 'dxos.org/app-framework/story',
123
+ id: 'org.dxos.app-framework.story',
99
124
  name: 'Story',
125
+ tags: ['system'],
100
126
  };
101
127
 
102
128
  // No-op plugin to ensure there exists at least one plugin for the startup event.
103
129
  // This is necessary because `createApp` expects the startup event to complete before the app is ready.
104
- const StoryPlugin = definePlugin(storyMeta, () => [
105
- defineModule({ id: storyMeta.id, activatesOn: Events.Startup, activate: () => [] }),
106
- ]);
130
+ const StoryPlugin = Plugin.define(storyMeta).pipe(
131
+ Plugin.addModule({
132
+ id: 'Story',
133
+ activatesOn: ActivationEvents.Startup,
134
+ activate: () => Effect.succeed([]),
135
+ }),
136
+ Plugin.make,
137
+ )();