@dxos/app-framework 0.8.4-main.fd6878d → 0.8.4-staging.60fe92afc8

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 (556) hide show
  1. package/.storybook/main.mts +9 -0
  2. package/.storybook/preview.mts +8 -0
  3. package/LICENSE +102 -5
  4. package/README.md +1 -1
  5. package/dist/lib/browser/capability-BOPAKKWG.mjs +35 -0
  6. package/dist/lib/browser/capability-BOPAKKWG.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-66IXTIVK.mjs +48 -0
  10. package/dist/lib/browser/chunk-66IXTIVK.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-CO3XLNUX.mjs +95 -0
  12. package/dist/lib/browser/chunk-CO3XLNUX.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-DC3WRPBV.mjs +227 -0
  14. package/dist/lib/browser/chunk-DC3WRPBV.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-HFLKXMT7.mjs +587 -0
  20. package/dist/lib/browser/chunk-HFLKXMT7.mjs.map +7 -0
  21. package/dist/lib/browser/chunk-IW44C7UL.mjs +83 -0
  22. package/dist/lib/browser/chunk-IW44C7UL.mjs.map +7 -0
  23. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  24. package/dist/lib/browser/chunk-KZUDO43J.mjs +422 -0
  25. package/dist/lib/browser/chunk-KZUDO43J.mjs.map +7 -0
  26. package/dist/lib/browser/chunk-Q2GLJTVV.mjs +12 -0
  27. package/dist/lib/browser/chunk-Q2GLJTVV.mjs.map +7 -0
  28. package/dist/lib/browser/chunk-SYXIYT6T.mjs +143 -0
  29. package/dist/lib/browser/chunk-SYXIYT6T.mjs.map +7 -0
  30. package/dist/lib/browser/chunk-XHS5KDNX.mjs +1471 -0
  31. package/dist/lib/browser/chunk-XHS5KDNX.mjs.map +7 -0
  32. package/dist/lib/browser/chunk-Y66ELD4U.mjs +476 -0
  33. package/dist/lib/browser/chunk-Y66ELD4U.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 +41 -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 -157
  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-GXNUO7AR.mjs +132 -0
  51. package/dist/lib/browser/process-manager-capability-GXNUO7AR.mjs.map +7 -0
  52. package/dist/lib/browser/testing/index.mjs +321 -56
  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 +52 -0
  57. package/dist/lib/browser/ui/index.mjs.map +7 -0
  58. package/dist/lib/node-esm/capability-KZWRTX7R.mjs +36 -0
  59. package/dist/lib/node-esm/capability-KZWRTX7R.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-A5CHGAZE.mjs +588 -0
  63. package/dist/lib/node-esm/chunk-A5CHGAZE.mjs.map +7 -0
  64. package/dist/lib/node-esm/chunk-COHOWGGJ.mjs +144 -0
  65. package/dist/lib/node-esm/chunk-COHOWGGJ.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-FPW45EZH.mjs +14 -0
  69. package/dist/lib/node-esm/chunk-FPW45EZH.mjs.map +7 -0
  70. package/dist/lib/node-esm/chunk-FSVGKTF6.mjs +477 -0
  71. package/dist/lib/node-esm/chunk-FSVGKTF6.mjs.map +7 -0
  72. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  73. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  74. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs +29 -0
  75. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs.map +7 -0
  76. package/dist/lib/node-esm/chunk-NULBHQYS.mjs +96 -0
  77. package/dist/lib/node-esm/chunk-NULBHQYS.mjs.map +7 -0
  78. package/dist/lib/node-esm/chunk-SX5NVETP.mjs +1472 -0
  79. package/dist/lib/node-esm/chunk-SX5NVETP.mjs.map +7 -0
  80. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs +70 -0
  81. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs.map +7 -0
  82. package/dist/lib/node-esm/chunk-XGBUKRCK.mjs +423 -0
  83. package/dist/lib/node-esm/chunk-XGBUKRCK.mjs.map +7 -0
  84. package/dist/lib/node-esm/chunk-XIGPWXCQ.mjs +228 -0
  85. package/dist/lib/node-esm/chunk-XIGPWXCQ.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 +42 -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 -157
  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-TX5TA6YN.mjs +133 -0
  108. package/dist/lib/node-esm/process-manager-capability-TX5TA6YN.mjs.map +7 -0
  109. package/dist/lib/node-esm/testing/index.mjs +321 -56
  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 +53 -0
  114. package/dist/lib/node-esm/ui/index.mjs.map +7 -0
  115. package/dist/plugin/node-esm/index.mjs +977 -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 -195
  127. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  128. package/dist/types/src/common/index.d.ts +3 -8
  129. package/dist/types/src/common/index.d.ts.map +1 -1
  130. package/dist/types/src/common/translations.d.ts +8 -8
  131. package/dist/types/src/common/translations.d.ts.map +1 -1
  132. package/dist/types/src/context.d.ts +5 -0
  133. package/dist/types/src/context.d.ts.map +1 -0
  134. package/dist/types/src/core/{events.d.ts → activation-event.d.ts} +11 -11
  135. package/dist/types/src/core/activation-event.d.ts.map +1 -0
  136. package/dist/types/src/core/capability-manager.d.ts +52 -0
  137. package/dist/types/src/core/capability-manager.d.ts.map +1 -0
  138. package/dist/types/src/core/capability-manager.test.d.ts +2 -0
  139. package/dist/types/src/core/capability-manager.test.d.ts.map +1 -0
  140. package/dist/types/src/core/capability.d.ts +161 -0
  141. package/dist/types/src/core/capability.d.ts.map +1 -0
  142. package/dist/types/src/core/edge-registry-plugin-provider.d.ts +30 -0
  143. package/dist/types/src/core/edge-registry-plugin-provider.d.ts.map +1 -0
  144. package/dist/types/src/core/index.d.ts +11 -4
  145. package/dist/types/src/core/index.d.ts.map +1 -1
  146. package/dist/types/src/core/plugin-asset-cache.d.ts +71 -0
  147. package/dist/types/src/core/plugin-asset-cache.d.ts.map +1 -0
  148. package/dist/types/src/core/plugin-manager.d.ts +297 -0
  149. package/dist/types/src/core/plugin-manager.d.ts.map +1 -0
  150. package/dist/types/src/core/plugin-manager.test.d.ts +2 -0
  151. package/dist/types/src/core/plugin-manager.test.d.ts.map +1 -0
  152. package/dist/types/src/core/plugin-manifest.d.ts +101 -0
  153. package/dist/types/src/core/plugin-manifest.d.ts.map +1 -0
  154. package/dist/types/src/core/plugin-manifest.test.d.ts +2 -0
  155. package/dist/types/src/core/plugin-manifest.test.d.ts.map +1 -0
  156. package/dist/types/src/core/plugin.d.ts +308 -41
  157. package/dist/types/src/core/plugin.d.ts.map +1 -1
  158. package/dist/types/src/core/registry.d.ts +107 -0
  159. package/dist/types/src/core/registry.d.ts.map +1 -0
  160. package/dist/types/src/core/url-loader.d.ts +127 -0
  161. package/dist/types/src/core/url-loader.d.ts.map +1 -0
  162. package/dist/types/src/core/url-loader.test.d.ts +2 -0
  163. package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
  164. package/dist/types/src/helpers.d.ts.map +1 -1
  165. package/dist/types/src/index.d.ts +2 -4
  166. package/dist/types/src/index.d.ts.map +1 -1
  167. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts +3 -0
  168. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts.map +1 -0
  169. package/dist/types/src/plugin-process-manager/history/capability.d.ts +7 -0
  170. package/dist/types/src/plugin-process-manager/history/capability.d.ts.map +1 -0
  171. package/dist/types/src/plugin-process-manager/history/errors.d.ts +32 -0
  172. package/dist/types/src/plugin-process-manager/history/errors.d.ts.map +1 -0
  173. package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts +32 -0
  174. package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts.map +1 -0
  175. package/dist/types/src/plugin-process-manager/history/history-tracker.test.d.ts +2 -0
  176. package/dist/types/src/plugin-process-manager/history/history-tracker.test.d.ts.map +1 -0
  177. package/dist/types/src/plugin-process-manager/history/index.d.ts +6 -0
  178. package/dist/types/src/plugin-process-manager/history/index.d.ts.map +1 -0
  179. package/dist/types/src/plugin-process-manager/history/types.d.ts +13 -0
  180. package/dist/types/src/plugin-process-manager/history/types.d.ts.map +1 -0
  181. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts +101 -0
  182. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts.map +1 -0
  183. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts +23 -0
  184. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts.map +1 -0
  185. package/dist/types/src/plugin-process-manager/history/undo-registry.test.d.ts +2 -0
  186. package/dist/types/src/plugin-process-manager/history/undo-registry.test.d.ts.map +1 -0
  187. package/dist/types/src/plugin-process-manager/idb-key-value-store.d.ts +10 -0
  188. package/dist/types/src/plugin-process-manager/idb-key-value-store.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 +3 -0
  200. package/dist/types/src/testing/index.d.ts.map +1 -1
  201. package/dist/types/src/testing/operationCapture.d.ts +64 -0
  202. package/dist/types/src/testing/operationCapture.d.ts.map +1 -0
  203. package/dist/types/src/testing/react.d.ts +27 -0
  204. package/dist/types/src/testing/react.d.ts.map +1 -0
  205. package/dist/types/src/testing/react.test.d.ts +2 -0
  206. package/dist/types/src/testing/react.test.d.ts.map +1 -0
  207. package/dist/types/src/testing/service.d.ts +8 -0
  208. package/dist/types/src/testing/service.d.ts.map +1 -0
  209. package/dist/types/src/testing/withPluginManager.d.ts +9 -10
  210. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  211. package/dist/types/src/testing/withPluginManager.stories.d.ts +9 -3
  212. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  213. package/dist/types/src/ui/components/App/App.d.ts +41 -0
  214. package/dist/types/src/ui/components/App/App.d.ts.map +1 -0
  215. package/dist/types/src/ui/components/App/App.stories.d.ts +19 -0
  216. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -0
  217. package/dist/types/src/ui/components/App/index.d.ts +2 -0
  218. package/dist/types/src/ui/components/App/index.d.ts.map +1 -0
  219. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts +13 -0
  220. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -0
  221. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +10 -0
  222. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -0
  223. package/dist/types/src/ui/components/PluginManager/index.d.ts +2 -0
  224. package/dist/types/src/ui/components/PluginManager/index.d.ts.map +1 -0
  225. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +24 -0
  226. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -0
  227. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts +14 -0
  228. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -0
  229. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts +11 -0
  230. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -0
  231. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
  232. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
  233. package/dist/types/src/ui/components/Surface/context.d.ts +5 -0
  234. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -0
  235. package/dist/types/src/ui/components/Surface/index.d.ts +36 -0
  236. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -0
  237. package/dist/types/src/ui/components/Surface/types.d.ts +197 -0
  238. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -0
  239. package/dist/types/src/ui/components/Surface/types.test.d.ts +2 -0
  240. package/dist/types/src/ui/components/Surface/types.test.d.ts.map +1 -0
  241. package/dist/types/src/ui/components/index.d.ts +4 -0
  242. package/dist/types/src/ui/components/index.d.ts.map +1 -0
  243. package/dist/types/src/ui/hooks/index.d.ts +7 -0
  244. package/dist/types/src/ui/hooks/index.d.ts.map +1 -0
  245. package/dist/types/src/ui/hooks/useApp.d.ts +80 -0
  246. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -0
  247. package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
  248. package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
  249. package/dist/types/src/ui/hooks/useCapabilities.d.ts +31 -0
  250. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -0
  251. package/dist/types/src/ui/hooks/useLoading.d.ts +18 -0
  252. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -0
  253. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts +30 -0
  254. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts.map +1 -0
  255. package/dist/types/src/ui/hooks/useSettingsState.d.ts +10 -0
  256. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -0
  257. package/dist/types/src/ui/hooks/useSurface.d.ts +3 -0
  258. package/dist/types/src/ui/hooks/useSurface.d.ts.map +1 -0
  259. package/dist/types/src/ui/index.d.ts +3 -0
  260. package/dist/types/src/ui/index.d.ts.map +1 -0
  261. package/dist/types/src/vite-plugin/boot-loader/index.d.ts +2 -0
  262. package/dist/types/src/vite-plugin/boot-loader/index.d.ts.map +1 -0
  263. package/dist/types/src/vite-plugin/boot-loader/loader.d.ts +59 -0
  264. package/dist/types/src/vite-plugin/boot-loader/loader.d.ts.map +1 -0
  265. package/dist/types/src/vite-plugin/composer/index.d.ts +34 -0
  266. package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -0
  267. package/dist/types/src/vite-plugin/import-map/index.d.ts +28 -0
  268. package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -0
  269. package/dist/types/src/vite-plugin/index.d.ts +5 -0
  270. package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
  271. package/dist/types/src/vite-plugin/manifest.d.ts +41 -0
  272. package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -0
  273. package/dist/types/src/vite-plugin/manifest.test.d.ts +2 -0
  274. package/dist/types/src/vite-plugin/manifest.test.d.ts.map +1 -0
  275. package/dist/types/src/vite-plugin/packages.d.ts +13 -0
  276. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
  277. package/dist/types/tsconfig.tsbuildinfo +1 -1
  278. package/moon.yml +26 -3
  279. package/package.json +125 -55
  280. package/src/cli/cli.ts +102 -0
  281. package/src/{playground/layout → cli}/index.ts +1 -1
  282. package/src/common/activation-events.ts +39 -0
  283. package/src/{playground/debug/index.ts → common/annotations.ts} +0 -2
  284. package/src/common/capabilities.ts +287 -184
  285. package/src/common/index.ts +3 -8
  286. package/src/common/translations.ts +18 -10
  287. package/src/context.ts +9 -0
  288. package/src/core/{events.ts → activation-event.ts} +10 -7
  289. package/src/core/capability-manager.test.ts +154 -0
  290. package/src/core/capability-manager.ts +213 -0
  291. package/src/core/capability.ts +254 -0
  292. package/src/core/edge-registry-plugin-provider.ts +92 -0
  293. package/src/core/index.ts +11 -4
  294. package/src/core/plugin-asset-cache.ts +60 -0
  295. package/src/core/plugin-manager.test.ts +1929 -0
  296. package/src/core/plugin-manager.ts +1696 -0
  297. package/src/core/plugin-manifest.test.ts +75 -0
  298. package/src/core/plugin-manifest.ts +134 -0
  299. package/src/core/plugin.ts +458 -46
  300. package/src/core/registry.ts +163 -0
  301. package/src/core/url-loader.test.ts +222 -0
  302. package/src/core/url-loader.ts +388 -0
  303. package/src/index.ts +2 -4
  304. package/src/plugin-process-manager/ProcessManagerPlugin.ts +24 -0
  305. package/src/plugin-process-manager/history/capability.ts +36 -0
  306. package/src/plugin-process-manager/history/errors.ts +7 -0
  307. package/src/plugin-process-manager/history/history-tracker.test.ts +353 -0
  308. package/src/plugin-process-manager/history/history-tracker.ts +144 -0
  309. package/src/plugin-process-manager/history/index.ts +9 -0
  310. package/src/plugin-process-manager/history/types.ts +17 -0
  311. package/src/plugin-process-manager/history/undo-mapping.ts +135 -0
  312. package/src/plugin-process-manager/history/undo-registry.test.ts +74 -0
  313. package/src/plugin-process-manager/history/undo-registry.ts +54 -0
  314. package/src/plugin-process-manager/idb-key-value-store.ts +64 -0
  315. package/src/plugin-process-manager/index.ts +6 -0
  316. package/src/plugin-process-manager/meta.ts +16 -0
  317. package/src/plugin-process-manager/process-manager-capability.ts +178 -0
  318. package/src/plugin-process-manager/testing.ts +156 -0
  319. package/src/testing/harness.ts +247 -0
  320. package/src/testing/index.ts +3 -0
  321. package/src/testing/operationCapture.ts +144 -0
  322. package/src/testing/react.test.tsx +50 -0
  323. package/src/testing/react.tsx +113 -0
  324. package/src/testing/service.ts +52 -0
  325. package/src/testing/withPluginManager.stories.tsx +15 -13
  326. package/src/testing/withPluginManager.tsx +81 -56
  327. package/src/ui/components/App/App.stories.tsx +84 -0
  328. package/src/ui/components/App/App.tsx +144 -0
  329. package/src/{playground/logger → ui/components/App}/index.ts +1 -1
  330. package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +179 -0
  331. package/src/{react → ui/components/PluginManager}/PluginManagerProvider.ts +3 -3
  332. package/src/ui/components/PluginManager/index.ts +5 -0
  333. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +144 -0
  334. package/src/ui/components/Surface/SurfaceComponent.tsx +303 -0
  335. package/src/ui/components/Surface/SurfaceInfo.tsx +106 -0
  336. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
  337. package/src/ui/components/Surface/context.ts +12 -0
  338. package/src/ui/components/Surface/index.ts +54 -0
  339. package/src/ui/components/Surface/types.test.ts +126 -0
  340. package/src/ui/components/Surface/types.ts +290 -0
  341. package/src/ui/components/index.ts +7 -0
  342. package/src/ui/hooks/index.ts +10 -0
  343. package/src/ui/hooks/useApp.test.tsx +161 -0
  344. package/src/ui/hooks/useApp.tsx +404 -0
  345. package/src/ui/hooks/useCapabilities.ts +68 -0
  346. package/src/ui/hooks/useLoading.tsx +76 -0
  347. package/src/ui/hooks/useProcessManagerRuntime.ts +78 -0
  348. package/src/ui/hooks/useSettingsState.ts +26 -0
  349. package/src/ui/hooks/useSurface.ts +13 -0
  350. package/src/ui/index.ts +6 -0
  351. package/src/vite-plugin/boot-loader/BootLoader.solid-stories.tsx +198 -0
  352. package/src/vite-plugin/boot-loader/index.ts +5 -0
  353. package/src/vite-plugin/boot-loader/loader-app/Loader.tsx +166 -0
  354. package/src/vite-plugin/boot-loader/loader-app/boot-loader.css +311 -0
  355. package/src/vite-plugin/boot-loader/loader-app/bridge.ts +25 -0
  356. package/src/vite-plugin/boot-loader/loader-app/entry.tsx +21 -0
  357. package/src/vite-plugin/boot-loader/loader-app/mount.tsx +70 -0
  358. package/src/vite-plugin/boot-loader/loader-app/store.test.ts +137 -0
  359. package/src/vite-plugin/boot-loader/loader-app/store.ts +149 -0
  360. package/src/vite-plugin/boot-loader/loader-app/tsconfig.json +11 -0
  361. package/src/vite-plugin/boot-loader/loader-app/types.ts +78 -0
  362. package/src/vite-plugin/boot-loader/loader.ts +204 -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 +55 -0
  367. package/src/vite-plugin/manifest.ts +63 -0
  368. package/src/vite-plugin/packages.ts +187 -0
  369. package/tsconfig.json +31 -24
  370. package/tsconfig.node.json +2 -4
  371. package/typedoc.json +2 -4
  372. package/vitest.config.ts +8 -6
  373. package/.swc/plugins/v7_linux_x86_64_13.0.0/c614d7475354583212fbd7669acbae95b9832c305bf51bdaabe2e6de05abb6bf +0 -0
  374. package/.swc/plugins/v7_linux_x86_64_13.0.0/fce1bdb8e20a094e4af08bad09cc81497ed0e2e7c51223b07d371063cca18429 +0 -0
  375. package/dist/lib/browser/app-graph-builder-MOVKFH3J.mjs +0 -137
  376. package/dist/lib/browser/app-graph-builder-MOVKFH3J.mjs.map +0 -7
  377. package/dist/lib/browser/chunk-NKCIDYDI.mjs +0 -1598
  378. package/dist/lib/browser/chunk-NKCIDYDI.mjs.map +0 -7
  379. package/dist/lib/browser/chunk-ORWHM7CO.mjs +0 -32
  380. package/dist/lib/browser/chunk-ORWHM7CO.mjs.map +0 -7
  381. package/dist/lib/browser/chunk-OSBZFKMO.mjs +0 -428
  382. package/dist/lib/browser/chunk-OSBZFKMO.mjs.map +0 -7
  383. package/dist/lib/browser/intent-dispatcher-FTTJLVGN.mjs +0 -11
  384. package/dist/lib/browser/intent-resolver-ZCGEAG3E.mjs +0 -39
  385. package/dist/lib/browser/intent-resolver-ZCGEAG3E.mjs.map +0 -7
  386. package/dist/lib/browser/store-3QB6Q2BC.mjs +0 -30
  387. package/dist/lib/browser/store-3QB6Q2BC.mjs.map +0 -7
  388. package/dist/lib/browser/worker.mjs +0 -79
  389. package/dist/lib/node-esm/app-graph-builder-ODE4B5GT.mjs +0 -138
  390. package/dist/lib/node-esm/app-graph-builder-ODE4B5GT.mjs.map +0 -7
  391. package/dist/lib/node-esm/chunk-UMZQERLE.mjs +0 -34
  392. package/dist/lib/node-esm/chunk-UMZQERLE.mjs.map +0 -7
  393. package/dist/lib/node-esm/chunk-WU3QN5B6.mjs +0 -429
  394. package/dist/lib/node-esm/chunk-WU3QN5B6.mjs.map +0 -7
  395. package/dist/lib/node-esm/chunk-YEN7NKTF.mjs +0 -1600
  396. package/dist/lib/node-esm/chunk-YEN7NKTF.mjs.map +0 -7
  397. package/dist/lib/node-esm/intent-dispatcher-YQIQ55LJ.mjs +0 -12
  398. package/dist/lib/node-esm/intent-resolver-KG27L7EQ.mjs +0 -40
  399. package/dist/lib/node-esm/intent-resolver-KG27L7EQ.mjs.map +0 -7
  400. package/dist/lib/node-esm/store-TIJAVO3D.mjs +0 -31
  401. package/dist/lib/node-esm/store-TIJAVO3D.mjs.map +0 -7
  402. package/dist/lib/node-esm/worker.mjs +0 -80
  403. package/dist/types/src/App.d.ts +0 -43
  404. package/dist/types/src/App.d.ts.map +0 -1
  405. package/dist/types/src/common/collaboration.d.ts +0 -19
  406. package/dist/types/src/common/collaboration.d.ts.map +0 -1
  407. package/dist/types/src/common/events.d.ts +0 -52
  408. package/dist/types/src/common/events.d.ts.map +0 -1
  409. package/dist/types/src/common/file.d.ts +0 -14
  410. package/dist/types/src/common/file.d.ts.map +0 -1
  411. package/dist/types/src/common/graph.d.ts +0 -21
  412. package/dist/types/src/common/graph.d.ts.map +0 -1
  413. package/dist/types/src/common/layout.d.ts +0 -281
  414. package/dist/types/src/common/layout.d.ts.map +0 -1
  415. package/dist/types/src/common/surface.d.ts +0 -65
  416. package/dist/types/src/common/surface.d.ts.map +0 -1
  417. package/dist/types/src/core/capabilities.d.ts +0 -114
  418. package/dist/types/src/core/capabilities.d.ts.map +0 -1
  419. package/dist/types/src/core/capabilities.test.d.ts +0 -2
  420. package/dist/types/src/core/capabilities.test.d.ts.map +0 -1
  421. package/dist/types/src/core/events.d.ts.map +0 -1
  422. package/dist/types/src/core/manager.d.ts +0 -126
  423. package/dist/types/src/core/manager.d.ts.map +0 -1
  424. package/dist/types/src/core/manager.test.d.ts +0 -2
  425. package/dist/types/src/core/manager.test.d.ts.map +0 -1
  426. package/dist/types/src/playground/debug/Debug.d.ts +0 -6
  427. package/dist/types/src/playground/debug/Debug.d.ts.map +0 -1
  428. package/dist/types/src/playground/debug/index.d.ts +0 -2
  429. package/dist/types/src/playground/debug/index.d.ts.map +0 -1
  430. package/dist/types/src/playground/debug/plugin.d.ts +0 -2
  431. package/dist/types/src/playground/debug/plugin.d.ts.map +0 -1
  432. package/dist/types/src/playground/generator/Main.d.ts +0 -6
  433. package/dist/types/src/playground/generator/Main.d.ts.map +0 -1
  434. package/dist/types/src/playground/generator/Toolbar.d.ts +0 -6
  435. package/dist/types/src/playground/generator/Toolbar.d.ts.map +0 -1
  436. package/dist/types/src/playground/generator/generator.d.ts +0 -7
  437. package/dist/types/src/playground/generator/generator.d.ts.map +0 -1
  438. package/dist/types/src/playground/generator/index.d.ts +0 -3
  439. package/dist/types/src/playground/generator/index.d.ts.map +0 -1
  440. package/dist/types/src/playground/generator/plugin.d.ts +0 -2
  441. package/dist/types/src/playground/generator/plugin.d.ts.map +0 -1
  442. package/dist/types/src/playground/layout/Layout.d.ts +0 -8
  443. package/dist/types/src/playground/layout/Layout.d.ts.map +0 -1
  444. package/dist/types/src/playground/layout/index.d.ts +0 -2
  445. package/dist/types/src/playground/layout/index.d.ts.map +0 -1
  446. package/dist/types/src/playground/layout/plugin.d.ts +0 -2
  447. package/dist/types/src/playground/layout/plugin.d.ts.map +0 -1
  448. package/dist/types/src/playground/logger/Toolbar.d.ts +0 -6
  449. package/dist/types/src/playground/logger/Toolbar.d.ts.map +0 -1
  450. package/dist/types/src/playground/logger/index.d.ts +0 -2
  451. package/dist/types/src/playground/logger/index.d.ts.map +0 -1
  452. package/dist/types/src/playground/logger/plugin.d.ts +0 -2
  453. package/dist/types/src/playground/logger/plugin.d.ts.map +0 -1
  454. package/dist/types/src/playground/logger/schema.d.ts +0 -13
  455. package/dist/types/src/playground/logger/schema.d.ts.map +0 -1
  456. package/dist/types/src/playground/playground.stories.d.ts +0 -10
  457. package/dist/types/src/playground/playground.stories.d.ts.map +0 -1
  458. package/dist/types/src/plugin-intent/IntentPlugin.d.ts +0 -2
  459. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +0 -1
  460. package/dist/types/src/plugin-intent/actions.d.ts +0 -38
  461. package/dist/types/src/plugin-intent/actions.d.ts.map +0 -1
  462. package/dist/types/src/plugin-intent/errors.d.ts +0 -16
  463. package/dist/types/src/plugin-intent/errors.d.ts.map +0 -1
  464. package/dist/types/src/plugin-intent/index.d.ts +0 -5
  465. package/dist/types/src/plugin-intent/index.d.ts.map +0 -1
  466. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +0 -139
  467. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +0 -1
  468. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts +0 -2
  469. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts.map +0 -1
  470. package/dist/types/src/plugin-intent/intent.d.ts +0 -63
  471. package/dist/types/src/plugin-intent/intent.d.ts.map +0 -1
  472. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +0 -2
  473. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +0 -1
  474. package/dist/types/src/plugin-settings/actions.d.ts +0 -27
  475. package/dist/types/src/plugin-settings/actions.d.ts.map +0 -1
  476. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -4
  477. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  478. package/dist/types/src/plugin-settings/index.d.ts +0 -3
  479. package/dist/types/src/plugin-settings/index.d.ts.map +0 -1
  480. package/dist/types/src/plugin-settings/intent-resolver.d.ts +0 -4
  481. package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +0 -1
  482. package/dist/types/src/plugin-settings/store.d.ts +0 -5
  483. package/dist/types/src/plugin-settings/store.d.ts.map +0 -1
  484. package/dist/types/src/plugin-settings/translations.d.ts +0 -10
  485. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  486. package/dist/types/src/react/ErrorBoundary.d.ts +0 -30
  487. package/dist/types/src/react/ErrorBoundary.d.ts.map +0 -1
  488. package/dist/types/src/react/IntentContext.d.ts +0 -8
  489. package/dist/types/src/react/IntentContext.d.ts.map +0 -1
  490. package/dist/types/src/react/PluginManagerProvider.d.ts +0 -10
  491. package/dist/types/src/react/PluginManagerProvider.d.ts.map +0 -1
  492. package/dist/types/src/react/Surface.d.ts +0 -12
  493. package/dist/types/src/react/Surface.d.ts.map +0 -1
  494. package/dist/types/src/react/Surface.stories.d.ts +0 -16
  495. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  496. package/dist/types/src/react/common.d.ts +0 -13
  497. package/dist/types/src/react/common.d.ts.map +0 -1
  498. package/dist/types/src/react/index.d.ts +0 -7
  499. package/dist/types/src/react/index.d.ts.map +0 -1
  500. package/dist/types/src/react/useCapabilities.d.ts +0 -13
  501. package/dist/types/src/react/useCapabilities.d.ts.map +0 -1
  502. package/dist/types/src/react/useIntentResolver.d.ts +0 -3
  503. package/dist/types/src/react/useIntentResolver.d.ts.map +0 -1
  504. package/dist/types/src/worker.d.ts +0 -4
  505. package/dist/types/src/worker.d.ts.map +0 -1
  506. package/src/App.tsx +0 -284
  507. package/src/common/collaboration.ts +0 -21
  508. package/src/common/events.ts +0 -79
  509. package/src/common/file.ts +0 -22
  510. package/src/common/graph.ts +0 -30
  511. package/src/common/layout.ts +0 -278
  512. package/src/common/surface.ts +0 -86
  513. package/src/core/capabilities.test.ts +0 -136
  514. package/src/core/capabilities.ts +0 -255
  515. package/src/core/manager.test.ts +0 -516
  516. package/src/core/manager.ts +0 -597
  517. package/src/playground/debug/Debug.tsx +0 -39
  518. package/src/playground/debug/plugin.ts +0 -17
  519. package/src/playground/generator/Main.tsx +0 -71
  520. package/src/playground/generator/Toolbar.tsx +0 -47
  521. package/src/playground/generator/generator.ts +0 -48
  522. package/src/playground/generator/index.ts +0 -6
  523. package/src/playground/generator/plugin.ts +0 -23
  524. package/src/playground/layout/Layout.tsx +0 -33
  525. package/src/playground/layout/plugin.ts +0 -17
  526. package/src/playground/logger/Toolbar.tsx +0 -30
  527. package/src/playground/logger/plugin.ts +0 -37
  528. package/src/playground/logger/schema.ts +0 -12
  529. package/src/playground/playground.stories.tsx +0 -43
  530. package/src/plugin-intent/IntentPlugin.ts +0 -21
  531. package/src/plugin-intent/actions.ts +0 -33
  532. package/src/plugin-intent/errors.ts +0 -39
  533. package/src/plugin-intent/index.ts +0 -8
  534. package/src/plugin-intent/intent-dispatcher.test.ts +0 -279
  535. package/src/plugin-intent/intent-dispatcher.ts +0 -334
  536. package/src/plugin-intent/intent.ts +0 -154
  537. package/src/plugin-settings/SettingsPlugin.ts +0 -36
  538. package/src/plugin-settings/actions.ts +0 -29
  539. package/src/plugin-settings/app-graph-builder.ts +0 -158
  540. package/src/plugin-settings/index.ts +0 -6
  541. package/src/plugin-settings/intent-resolver.ts +0 -35
  542. package/src/plugin-settings/store.ts +0 -33
  543. package/src/plugin-settings/translations.ts +0 -19
  544. package/src/react/ErrorBoundary.tsx +0 -54
  545. package/src/react/IntentContext.tsx +0 -35
  546. package/src/react/Surface.stories.tsx +0 -97
  547. package/src/react/Surface.tsx +0 -78
  548. package/src/react/common.ts +0 -13
  549. package/src/react/index.ts +0 -10
  550. package/src/react/useCapabilities.ts +0 -31
  551. package/src/react/useIntentResolver.ts +0 -22
  552. package/src/worker.ts +0 -11
  553. /package/dist/lib/browser/{intent-dispatcher-FTTJLVGN.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  554. /package/dist/lib/browser/{worker.mjs.map → common/activation-events.mjs.map} +0 -0
  555. /package/dist/lib/{node-esm/intent-dispatcher-YQIQ55LJ.mjs.map → browser/common/capabilities.mjs.map} +0 -0
  556. /package/dist/lib/{node-esm/worker.mjs.map → browser/core/activation-event.mjs.map} +0 -0
@@ -0,0 +1,10 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './useApp';
6
+ export * from './useCapabilities';
7
+ export * from './useLoading';
8
+ export * from './useProcessManagerRuntime';
9
+ export * from './useSettingsState';
10
+ export * from './useSurface';
@@ -0,0 +1,161 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { assert, describe, it } from '@effect/vitest';
6
+ import { render, waitFor } from '@testing-library/react';
7
+ import * as Effect from 'effect/Effect';
8
+ import React from 'react';
9
+
10
+ import { DXN } from '@dxos/keys';
11
+
12
+ import { ActivationEvents, Capabilities } from '../../common';
13
+ import { Capability, Plugin, PluginManager } from '../../core';
14
+ import { useApp } from './useApp';
15
+
16
+ const String = Capability.make<{ string: string }>('org.dxos.test.string');
17
+ const testMeta = Plugin.makeMeta({ key: DXN.make('org.dxos.plugin.test'), name: 'Test', tags: ['system'] });
18
+
19
+ const pluginLoader = (plugins: Plugin.Plugin[]) =>
20
+ Effect.fn(function* (id: string) {
21
+ const plugin = plugins.find((plugin) => plugin.meta.id === id);
22
+ if (!plugin) {
23
+ return yield* Effect.fail(new Error(`Plugin not found: ${id}`));
24
+ }
25
+ return { plugin };
26
+ });
27
+
28
+ const TestHost = ({ manager }: { manager: PluginManager.PluginManager }) => {
29
+ const App = useApp({ pluginManager: manager });
30
+ return <App />;
31
+ };
32
+
33
+ describe('useApp cleanup integration', () => {
34
+ it.effect('external manager is not shut down when useApp does not own it', () =>
35
+ Effect.gen(function* () {
36
+ const plugin = Plugin.define(testMeta).pipe(
37
+ Plugin.addModule({
38
+ id: 'Hello',
39
+ activatesOn: ActivationEvents.Startup,
40
+ activate: () => Effect.succeed(Capability.contributes(String, { string: 'hello' })),
41
+ }),
42
+ Plugin.make,
43
+ )();
44
+
45
+ const manager = PluginManager.make({
46
+ pluginLoader: pluginLoader([plugin]),
47
+ plugins: [plugin],
48
+ });
49
+
50
+ manager.capabilities.contribute({
51
+ interface: Capabilities.PluginManager,
52
+ implementation: manager,
53
+ module: 'org.dxos.app-framework.plugin-manager',
54
+ });
55
+ manager.capabilities.contribute({
56
+ interface: Capabilities.AtomRegistry,
57
+ implementation: manager.registry,
58
+ module: 'org.dxos.app-framework.atom-registry',
59
+ });
60
+
61
+ const view = yield* Effect.promise(() => Promise.resolve(render(<TestHost manager={manager} />)));
62
+ yield* Effect.promise(() =>
63
+ waitFor(() => {
64
+ assert.strictEqual(manager.capabilities.getAll(Capabilities.PluginManager).length, 1);
65
+ assert.strictEqual(manager.capabilities.getAll(Capabilities.AtomRegistry).length, 1);
66
+ assert.strictEqual(manager.capabilities.getAll(String).length, 1);
67
+ assert.isTrue(manager.getActive().length > 0);
68
+ }),
69
+ );
70
+
71
+ yield* Effect.promise(() => Promise.resolve(view.unmount()));
72
+ yield* Effect.promise(() =>
73
+ waitFor(() => {
74
+ assert.strictEqual(manager.capabilities.getAll(Capabilities.PluginManager).length, 1);
75
+ assert.strictEqual(manager.capabilities.getAll(Capabilities.AtomRegistry).length, 1);
76
+ assert.strictEqual(manager.capabilities.getAll(String).length, 1);
77
+ assert.isTrue(manager.getActive().length > 0);
78
+ }),
79
+ );
80
+
81
+ yield* manager.shutdown();
82
+
83
+ assert.strictEqual(manager.capabilities.getAll(Capabilities.PluginManager).length, 1);
84
+ assert.strictEqual(manager.capabilities.getAll(Capabilities.AtomRegistry).length, 1);
85
+ assert.strictEqual(manager.capabilities.getAll(String).length, 0);
86
+ assert.deepStrictEqual(manager.getActive(), []);
87
+ }),
88
+ );
89
+
90
+ it.effect('shutdown deactivates modules and clears bookkeeping', () =>
91
+ Effect.gen(function* () {
92
+ const plugin = Plugin.define(testMeta).pipe(
93
+ Plugin.addModule({
94
+ id: 'Hello',
95
+ activatesOn: ActivationEvents.Startup,
96
+ activate: () => Effect.succeed(Capability.contributes(String, { string: 'hello' })),
97
+ }),
98
+ Plugin.make,
99
+ )();
100
+
101
+ const manager = PluginManager.make({
102
+ pluginLoader: pluginLoader([plugin]),
103
+ plugins: [plugin],
104
+ });
105
+
106
+ manager.capabilities.contribute({
107
+ interface: Capabilities.PluginManager,
108
+ implementation: manager,
109
+ module: 'org.dxos.app-framework.plugin-manager',
110
+ });
111
+ manager.capabilities.contribute({
112
+ interface: Capabilities.AtomRegistry,
113
+ implementation: manager.registry,
114
+ module: 'org.dxos.app-framework.atom-registry',
115
+ });
116
+ yield* manager.activate(ActivationEvents.Startup);
117
+
118
+ assert.strictEqual(manager.capabilities.getAll(String).length, 1);
119
+ assert.isTrue(manager.getActive().length > 0);
120
+
121
+ yield* manager.shutdown();
122
+
123
+ assert.strictEqual(manager.capabilities.getAll(String).length, 0);
124
+ assert.deepStrictEqual(manager.getActive(), []);
125
+ assert.deepStrictEqual(manager.getEventsFired(), []);
126
+ }),
127
+ );
128
+
129
+ it.effect('shutdown is idempotent when called multiple times', () =>
130
+ Effect.gen(function* () {
131
+ const plugin = Plugin.define(testMeta).pipe(
132
+ Plugin.addModule({
133
+ id: 'Hello',
134
+ activatesOn: ActivationEvents.Startup,
135
+ activate: () => Effect.succeed(Capability.contributes(String, { string: 'hello' })),
136
+ }),
137
+ Plugin.make,
138
+ )();
139
+
140
+ const manager = PluginManager.make({
141
+ pluginLoader: pluginLoader([plugin]),
142
+ plugins: [plugin],
143
+ });
144
+
145
+ manager.capabilities.contribute({
146
+ interface: Capabilities.PluginManager,
147
+ implementation: manager,
148
+ module: 'org.dxos.app-framework.plugin-manager',
149
+ });
150
+ yield* manager.activate(ActivationEvents.Startup);
151
+
152
+ yield* manager.shutdown();
153
+ assert.deepStrictEqual(manager.getActive(), []);
154
+
155
+ // Second shutdown should succeed without error.
156
+ const result = yield* manager.shutdown();
157
+ assert.isTrue(result);
158
+ assert.deepStrictEqual(manager.getActive(), []);
159
+ }),
160
+ );
161
+ });
@@ -0,0 +1,404 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { RegistryContext } from '@effect-atom/atom-react';
6
+ import * as Effect from 'effect/Effect';
7
+ import * as Fiber from 'effect/Fiber';
8
+ import * as PubSub from 'effect/PubSub';
9
+ import * as Queue from 'effect/Queue';
10
+ import React, { type FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
11
+
12
+ import { EffectEx } from '@dxos/effect';
13
+ import { invariant } from '@dxos/invariant';
14
+ import { log } from '@dxos/log';
15
+ import { ErrorBoundary, ErrorFallback, type FallbackProps } from '@dxos/react-error-boundary';
16
+ import { useAsyncEffect, useDefaultValue } from '@dxos/react-hooks';
17
+ import { ContextProtocolProvider } from '@dxos/web-context-react';
18
+
19
+ import { ActivationEvents, Capabilities } from '../../common';
20
+ import { PluginManagerContext } from '../../context';
21
+ import { type ActivationEvent, type Plugin, PluginManager } from '../../core';
22
+ import { App, PluginManagerProvider } from '../components';
23
+
24
+ const ENABLED_KEY = 'org.dxos.app-framework.enabled';
25
+
26
+ export type StartupProgress = {
27
+ /** Number of modules that have been activated. */
28
+ activated: number;
29
+ /** Total number of modules registered. */
30
+ total: number;
31
+ /** Fractional progress (0-1). */
32
+ progress: number;
33
+ /**
34
+ * Raw activation event key (e.g. `org.dxos.app-framework.event.startup`).
35
+ * Set on event-level transitions, *and* on module-level transitions where
36
+ * it carries the parent activation event that first triggered the
37
+ * module's load (plumbed through `_loadCapabilitiesForModules` →
38
+ * `_loadModule`). Consumers can use this either as the primary id (when
39
+ * {@link module} is absent) or as an extra "context" field alongside
40
+ * {@link module}.
41
+ */
42
+ event?: string;
43
+ /**
44
+ * Raw module id (e.g. `org.dxos.plugin.observability.module.ReactSurface`)
45
+ * when the in-flight activation is module-level. When present,
46
+ * {@link event} may also be set, identifying the parent activation that
47
+ * triggered this module's load.
48
+ */
49
+ module?: string;
50
+ /**
51
+ * Pre-humanized label for the currently surfaced transition (module
52
+ * label if {@link module} is set, otherwise the event label), supplied
53
+ * for consumers that want a sensible default. Hosts that prefer to
54
+ * render their own label can read the raw {@link event}/{@link module}
55
+ * fields and ignore this — the framework leaves the policy choice
56
+ * (which transitions to surface, how to format them, whether to drop
57
+ * sub-modules entirely) to the host's `Placeholder`.
58
+ */
59
+ humanizedName?: string;
60
+ };
61
+
62
+ export type UseAppOptions = {
63
+ pluginManager?: PluginManager.PluginManager;
64
+ pluginLoader?: PluginManager.ManagerOptions['pluginLoader'];
65
+ onPluginRemove?: PluginManager.ManagerOptions['onRemove'];
66
+ pluginRegistryProvider?: PluginManager.ManagerOptions['pluginRegistryProvider'];
67
+ plugins?: Plugin.Plugin[];
68
+ defaults?: string[];
69
+ /**
70
+ * Additional activation events to fire before startup.
71
+ * These are fired alongside SetupReactSurface before the Startup event.
72
+ */
73
+ setupEvents?: ActivationEvent.ActivationEvent[];
74
+ cacheEnabled?: boolean;
75
+ safeMode?: boolean;
76
+ debounce?: number;
77
+ timeout?: number;
78
+ fallback?: FC<FallbackProps>;
79
+ };
80
+
81
+ /**
82
+ * Expected usage is for this to be the entrypoint of the application.
83
+ * Initializes plugins and renders the root components.
84
+ *
85
+ * @example
86
+ * const plugins = [LayoutPlugin(), MyPlugin()];
87
+ * const defaults = [MyPluginId];
88
+ * const fallback = () => <div>Initializing Plugins...</div>;
89
+ * const App = useApp({ plugins, defaults, fallback });
90
+ * createRoot(document.getElementById('root')!).render(
91
+ * <StrictMode>
92
+ * <App />
93
+ * </StrictMode>,
94
+ * );
95
+ *
96
+ * @param params.pluginLoader A function which loads new plugins.
97
+ * @param params.plugins All plugins available to the application. Plugins whose `meta.tags` includes `'system'` are treated as core (force-enabled, not user-toggleable).
98
+ * @param params.defaults Default plugins are enabled by default but can be disabled by the user.
99
+ * @param params.cacheEnabled Whether to cache enabled plugins in localStorage.
100
+ * @param params.safeMode Whether to enable safe mode, which disables optional plugins.
101
+ * @param params.fallback Fallback component to render if an error occurs during startup.
102
+ */
103
+ export const useApp = ({
104
+ pluginManager,
105
+ pluginLoader: pluginLoaderProp,
106
+ onPluginRemove,
107
+ pluginRegistryProvider,
108
+ plugins: pluginsProp,
109
+ defaults: defaultsProp,
110
+ setupEvents: setupEventsProp,
111
+ fallback = ErrorFallback,
112
+ cacheEnabled = false,
113
+ safeMode = false,
114
+ debounce = 0,
115
+ timeout = 30_000,
116
+ }: UseAppOptions) => {
117
+ const plugins = useDefaultValue(pluginsProp, () => []);
118
+ const defaults = useDefaultValue(defaultsProp, () => []);
119
+ const setupEvents = useDefaultValue(setupEventsProp, () => []);
120
+
121
+ const pluginLoader = useMemo(
122
+ () =>
123
+ pluginLoaderProp ??
124
+ ((id: string) =>
125
+ Effect.sync(() => {
126
+ const plugin = plugins.find((plugin) => plugin.meta.id === id);
127
+ invariant(plugin, `Plugin not found: ${id}`);
128
+ return { plugin };
129
+ })),
130
+ [pluginLoaderProp, plugins],
131
+ );
132
+
133
+ const readyRef = useRef(false);
134
+ const [ready, setReady] = useState(false);
135
+ const errorRef = useRef<unknown>(null);
136
+ const [error, setError] = useState<unknown>(null);
137
+ const [startupProgress, setStartupProgress] = useState<StartupProgress>({
138
+ activated: 0,
139
+ total: 0,
140
+ progress: 0,
141
+ });
142
+ // TODO(wittjosiah): Migrate to Atom.kvs for isomorphic storage.
143
+ const cached: string[] = useMemo(() => JSON.parse(localStorage.getItem(ENABLED_KEY) ?? '[]'), []);
144
+ const enabled = useMemo(
145
+ () => (safeMode ? [] : cacheEnabled && cached.length > 0 ? cached : defaults),
146
+ [safeMode, cacheEnabled, cached, defaults],
147
+ );
148
+ const isExternalManager = !!pluginManager;
149
+ const manager = useMemo(() => {
150
+ const mgr =
151
+ pluginManager ??
152
+ PluginManager.make({
153
+ pluginLoader,
154
+ plugins,
155
+ enabled,
156
+ onRemove: onPluginRemove,
157
+ pluginRegistryProvider,
158
+ });
159
+ log('useApp: useMemo created/reused manager', { provided: !!pluginManager });
160
+ return mgr;
161
+ }, [pluginManager, pluginLoader, plugins, enabled, onPluginRemove, pluginRegistryProvider]);
162
+
163
+ useEffect(() => {
164
+ if (!cacheEnabled) {
165
+ return;
166
+ }
167
+ return manager.registry.subscribe(manager.enabled, (value) => {
168
+ localStorage.setItem(ENABLED_KEY, JSON.stringify(value));
169
+ });
170
+ }, [cacheEnabled, manager]);
171
+
172
+ useEffect(() => {
173
+ setupDevtools(manager);
174
+ }, [manager]);
175
+
176
+ useAsyncEffect(async () => {
177
+ log('useApp: effect mount');
178
+
179
+ manager.capabilities.contribute({
180
+ interface: Capabilities.PluginManager,
181
+ implementation: manager,
182
+ module: 'org.dxos.app-framework.plugin-manager',
183
+ });
184
+
185
+ manager.capabilities.contribute({
186
+ interface: Capabilities.AtomRegistry,
187
+ implementation: manager.registry,
188
+ module: 'org.dxos.app-framework.atom-registry',
189
+ });
190
+
191
+ const fiber = Effect.gen(function* () {
192
+ const queue = yield* PubSub.subscribe(manager.activation);
193
+ const listener = yield* Effect.forkDaemon(
194
+ Queue.take(queue).pipe(
195
+ Effect.tap(({ event, state, module, error: error$ }) =>
196
+ Effect.sync(() => {
197
+ // Event-level Startup activated (no `module` field) fires once,
198
+ // after every module triggered by Startup has finished. Module
199
+ // activations now also carry their parent event id (so the trace
200
+ // can attribute a module to its triggering event), which means
201
+ // each module activated under Startup publishes
202
+ // `{ event: 'startup', state: 'activated', module: <id> }`. Without
203
+ // the `!module` guard the listener would mark the app ready on
204
+ // the *first* such module rather than waiting for the event-level
205
+ // completion — leaving downstream capabilities (operation-invoker,
206
+ // app-graph, …) un-registered when the boot loader dismisses.
207
+ if (event === ActivationEvents.Startup.id && state === 'activated' && !module) {
208
+ clearTimeout(timeoutId);
209
+ setReady(true);
210
+ readyRef.current = true;
211
+ // Trigger startup profiler dump if available.
212
+ (globalThis as any).composer?.profiler?.dump();
213
+ // Notify any host observability layer that startup completed.
214
+ // A `CustomEvent` keeps this generic — app-framework doesn't
215
+ // import a provider, and consumers can capture the startup
216
+ // summary without us picking one.
217
+ if (typeof window !== 'undefined') {
218
+ window.dispatchEvent(new CustomEvent('app-framework:startup-activated'));
219
+ }
220
+ return;
221
+ }
222
+ // `activating` is the start-of-load signal. Surface the raw
223
+ // `module` (or `event`) plus a pre-humanized label so the
224
+ // boot loader can decide how to render each transition — show
225
+ // everything, suppress noisy sub-modules, group by plugin,
226
+ // or apply its own formatting. We intentionally do NOT touch
227
+ // these fields on `activated`: pairing the two would cause
228
+ // back-to-back identical updates to the host's effect, which
229
+ // the boot loader treats as a re-trigger because
230
+ // `progress.progress` moved. Leaving the label alone on
231
+ // completion keeps it accurate ("now activating X") until
232
+ // the next module starts.
233
+ if (module && state === 'activating' && !readyRef.current) {
234
+ setStartupProgress((current) => ({
235
+ ...current,
236
+ // `event` here is the activation event that first
237
+ // triggered this module load (plumbed through
238
+ // `_loadCapabilitiesForModules` → `_loadModule`).
239
+ // Falsy/empty falls back to undefined so consumers can
240
+ // tell "no parent context" from "parent context: <X>".
241
+ event: event || undefined,
242
+ module,
243
+ humanizedName: humanizeModuleId(module),
244
+ }));
245
+ }
246
+ // Update the activation count when a module commits. The
247
+ // ring's fraction comes from this; `event`/`module`/
248
+ // `humanizedName` were set by the matching `activating`
249
+ // message above and are left alone so the count can advance
250
+ // without re-firing the host's status callback.
251
+ if (module && state === 'activated' && !readyRef.current) {
252
+ const active = manager.getActive();
253
+ const total = manager.getModules().length;
254
+ setStartupProgress((current) => ({
255
+ ...current,
256
+ activated: active.length,
257
+ total,
258
+ progress: total > 0 ? active.length / total : 0,
259
+ }));
260
+ }
261
+ // Event-level `activating` (no `module`) — fired at the start
262
+ // of `_activateModulesForEvent` and recursively for each
263
+ // before/after event. Surfaces a label during the gap before
264
+ // the first module-level message lands; subsequent module
265
+ // updates immediately overwrite this with a more specific
266
+ // label.
267
+ if (event && !module && state === 'activating' && !readyRef.current) {
268
+ setStartupProgress((current) => ({
269
+ ...current,
270
+ event,
271
+ module: undefined,
272
+ humanizedName: humanizeEventKey(event),
273
+ }));
274
+ }
275
+ if (error$ && !readyRef.current) {
276
+ setError(error$);
277
+ errorRef.current = error$;
278
+ }
279
+ }),
280
+ ),
281
+ Effect.forever,
282
+ ),
283
+ );
284
+
285
+ yield* Effect.all([
286
+ ...setupEvents.map((event) => manager.activate(event)),
287
+ manager.activate(ActivationEvents.SetupReactSurface),
288
+ manager.activate(ActivationEvents.Startup),
289
+ ]);
290
+
291
+ return yield* Fiber.join(listener);
292
+ }).pipe(Effect.scoped, Effect.runFork);
293
+
294
+ // Set up a timeout for startup.
295
+ const timeoutId = setTimeout(() => {
296
+ if (!readyRef.current && !errorRef.current) {
297
+ log.warn('startup timeout diagnostic', {
298
+ eventsFired: manager.getEventsFired(),
299
+ activeModules: manager.getActive(),
300
+ pendingReset: manager.getPendingReset(),
301
+ });
302
+ void EffectEx.runAndForwardErrors(Fiber.interrupt(fiber));
303
+ setError(new Error(`Startup timed out after ${timeout}ms`));
304
+ }
305
+ }, timeout);
306
+
307
+ return () => {
308
+ log('useApp: effect cleanup');
309
+ clearTimeout(timeoutId);
310
+ void EffectEx.runAndForwardErrors(Fiber.interrupt(fiber));
311
+ if (!isExternalManager) {
312
+ void EffectEx.runAndForwardErrors(manager.shutdown());
313
+ }
314
+ };
315
+ }, [manager]);
316
+
317
+ const progressRef = useRef(startupProgress);
318
+ progressRef.current = startupProgress;
319
+
320
+ return useCallback(
321
+ () => (
322
+ <ErrorBoundary name='app' FallbackComponent={fallback}>
323
+ <PluginManagerProvider value={manager}>
324
+ <ContextProtocolProvider value={manager} context={PluginManagerContext}>
325
+ <RegistryContext.Provider value={manager.registry}>
326
+ <App ready={ready} error={error} debounce={debounce} progress={progressRef.current} />
327
+ </RegistryContext.Provider>
328
+ </ContextProtocolProvider>
329
+ </PluginManagerProvider>
330
+ </ErrorBoundary>
331
+ ),
332
+ [fallback, manager, ready, error],
333
+ );
334
+ };
335
+
336
+ const setupDevtools = (manager: PluginManager.PluginManager) => {
337
+ (globalThis as any).composer ??= {};
338
+ (globalThis as any).composer.manager = manager;
339
+ };
340
+
341
+ /**
342
+ * Extracts a human-readable label from a module ID.
343
+ *
344
+ * Module IDs follow `org.dxos.plugin.<plugin-slug>.module.<module-name>`,
345
+ * where `<plugin-slug>` is kebab-case and `<module-name>` is either an
346
+ * explicit string (often kebab-case, e.g. `'observability'`, `'namespace'`)
347
+ * or a capability tag in PascalCase from `Capability.getModuleTag(...)`
348
+ * (e.g. `'ReactSurface'`, `'AppGraphBuilder'`). The output is
349
+ * `"Title Case Plugin: kebab-module"` so the visible status names both the
350
+ * plugin and the aspect being activated, helping disambiguate the multiple
351
+ * modules a plugin contributes.
352
+ *
353
+ * Examples:
354
+ * - "org.dxos.plugin.markdown.module.ReactSurface" → "Markdown: react-surface"
355
+ * - "org.dxos.plugin.observability.module.AppGraphBuilder" → "Observability: app-graph-builder"
356
+ * - "org.dxos.plugin.observability.module.observability" → "Observability"
357
+ * (the module name matches the plugin slug — collapsed to avoid
358
+ * "Observability: observability" noise.)
359
+ */
360
+ const humanizeModuleId = (moduleId: string): string => {
361
+ const match = moduleId.match(/\.plugin\.([^.]+)\.module\.(.+)$/);
362
+ if (!match) {
363
+ // Fallback: use the last segment.
364
+ const parts = moduleId.split('.');
365
+ return parts[parts.length - 1];
366
+ }
367
+ const [, pluginSlug, moduleName] = match;
368
+ const pluginLabel = pluginSlug
369
+ .split('-')
370
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
371
+ .join(' ');
372
+ // Normalise the module name to kebab-case so PascalCase capability tags
373
+ // ("ReactSurface") read consistently with explicit kebab IDs
374
+ // ("operation-handler"). The two-step substitution handles consecutive
375
+ // uppercase runs (`URLLoader` → `url-loader`) without splitting them
376
+ // mid-acronym.
377
+ const moduleLabel = moduleName
378
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
379
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
380
+ .toLowerCase();
381
+ // Capability modules whose name matches the plugin slug (e.g. the
382
+ // observability plugin's `observability` capability module) would render
383
+ // as "Observability: observability" — drop the redundant suffix.
384
+ if (moduleLabel === pluginSlug) {
385
+ return pluginLabel;
386
+ }
387
+ return `${pluginLabel}: ${moduleLabel}`;
388
+ };
389
+
390
+ /**
391
+ * Extracts a human-readable label from an activation event key.
392
+ * E.g., "org.dxos.app-framework.event.setup-react-surface" → "Setup React Surface".
393
+ */
394
+ const humanizeEventKey = (eventKey: string): string => {
395
+ // Strip a leading specifier (composite key form: "<id>:<specifier>").
396
+ const id = eventKey.split(':')[0];
397
+ // Match the trailing segment after `.event.`.
398
+ const match = id.match(/\.event\.(.+)$/);
399
+ const slug = match ? match[1] : (id.split('.').pop() ?? id);
400
+ return slug
401
+ .split('-')
402
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
403
+ .join(' ');
404
+ };
@@ -0,0 +1,68 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Atom, useAtomValue } from '@effect-atom/atom-react';
6
+ import { useCallback } from 'react';
7
+
8
+ import { invariant } from '@dxos/invariant';
9
+
10
+ import { Capabilities } from '../../common';
11
+ import { type Capability } from '../../core';
12
+ import { usePluginManager } from '../components';
13
+
14
+ /**
15
+ * Hook to request capabilities from the plugin context.
16
+ * @returns An array of capabilities.
17
+ */
18
+ export const useCapabilities = <T>(interfaceDef: Capability.InterfaceDef<T>) => {
19
+ const manager = usePluginManager();
20
+ return useAtomValue(manager.capabilities.atom(interfaceDef));
21
+ };
22
+
23
+ /**
24
+ * Hook to request a capability from the plugin context.
25
+ * @returns The capability.
26
+ * @throws If no capability is found.
27
+ */
28
+ // TODO(burdon): Option not to throw?
29
+ export const useCapability = <T>(interfaceDef: Capability.InterfaceDef<T>) => {
30
+ const capabilities = useCapabilities(interfaceDef);
31
+ invariant(capabilities.length > 0, `No capability found for ${interfaceDef.identifier}`);
32
+ return capabilities[0];
33
+ };
34
+
35
+ /**
36
+ * Hook to get the current value of an atom capability.
37
+ * Automatically subscribes to changes.
38
+ * @example const settings = useAtomCapability(CommentCapabilities.Settings);
39
+ */
40
+ export const useAtomCapability = <T>(atomCapability: Capability.InterfaceDef<Atom.Atom<T>>): T => {
41
+ const atom = useCapability(atomCapability);
42
+ return useAtomValue(atom);
43
+ };
44
+
45
+ /**
46
+ * Hook to get value and updater for an atom capability.
47
+ * Returns [currentValue, updateFn] similar to useState.
48
+ * @example const [settings, updateSettings] = useAtomCapabilityState(CommentCapabilities.Settings);
49
+ */
50
+ export const useAtomCapabilityState = <T>(
51
+ atomCapability: Capability.InterfaceDef<Atom.Writable<T>>,
52
+ ): [T, (fn: (current: T) => T) => void] => {
53
+ const registry = useCapability(Capabilities.AtomRegistry);
54
+ const atom = useCapability(atomCapability);
55
+ const value = useAtomValue(atom);
56
+ const update = useCallback(
57
+ (fn: (current: T) => T) => {
58
+ registry.set(atom, fn(registry.get(atom)));
59
+ },
60
+ [registry, atom],
61
+ );
62
+ return [value, update];
63
+ };
64
+
65
+ /**
66
+ * Hook to get the operation invoker capability.
67
+ */
68
+ export const useOperationInvoker = (): Capabilities.OperationInvoker => useCapability(Capabilities.OperationInvoker);