@dxos/app-framework 0.11.1 → 0.12.0-next-73daef452f1464b62efdbca75fb0067c1066f264

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 (314) hide show
  1. package/API.md +275 -0
  2. package/ARCHITECTURE.md +190 -0
  3. package/CHANGELOG.md +243 -0
  4. package/README.md +3 -0
  5. package/TASKS.md +25 -0
  6. package/bin/dx-plugin.mjs +7 -0
  7. package/dist/lib/chunk-SurfaceManager.mjs +106 -103
  8. package/dist/lib/chunk-SurfaceManager.mjs.map +1 -1
  9. package/dist/lib/chunk-capability.mjs +379 -10
  10. package/dist/lib/chunk-capability.mjs.map +1 -1
  11. package/dist/lib/chunk-capability2.mjs +17 -0
  12. package/dist/lib/chunk-capability2.mjs.map +1 -0
  13. package/dist/lib/chunk-devtools.mjs +110 -0
  14. package/dist/lib/chunk-devtools.mjs.map +1 -0
  15. package/dist/lib/chunk-history-tracker.mjs +4 -64
  16. package/dist/lib/chunk-history-tracker.mjs.map +1 -1
  17. package/dist/lib/chunk-plugin-manager.mjs +2225 -1147
  18. package/dist/lib/chunk-plugin-manager.mjs.map +1 -1
  19. package/dist/lib/chunk-process-manager-capability.mjs +83 -32
  20. package/dist/lib/chunk-process-manager-capability.mjs.map +1 -1
  21. package/dist/lib/chunk-ui.mjs +753 -0
  22. package/dist/lib/chunk-ui.mjs.map +1 -0
  23. package/dist/lib/cli.mjs +11 -8
  24. package/dist/lib/cli.mjs.map +1 -1
  25. package/dist/lib/common/Role.mjs +19 -0
  26. package/dist/lib/common/Role.mjs.map +1 -0
  27. package/dist/lib/common/activation-events.mjs +32 -19
  28. package/dist/lib/common/activation-events.mjs.map +1 -1
  29. package/dist/lib/common/capabilities.mjs +38 -27
  30. package/dist/lib/common/capabilities.mjs.map +1 -1
  31. package/dist/lib/core/activation-event.mjs +33 -2
  32. package/dist/lib/core/activation-event.mjs.map +1 -1
  33. package/dist/lib/core/capability-manager.mjs +203 -0
  34. package/dist/lib/core/capability-manager.mjs.map +1 -0
  35. package/dist/lib/core/capability.mjs +2 -189
  36. package/dist/lib/core/plugin-asset-cache.mjs +28 -0
  37. package/dist/lib/core/plugin-asset-cache.mjs.map +1 -0
  38. package/dist/lib/core/plugin-manager.mjs +14 -2
  39. package/dist/lib/core/plugin-manager.mjs.map +1 -0
  40. package/dist/lib/{chunk-plugin-manifest.mjs → core/plugin-manifest.mjs} +10 -9
  41. package/dist/lib/core/plugin-manifest.mjs.map +1 -0
  42. package/dist/lib/core/plugin.mjs +61 -58
  43. package/dist/lib/core/plugin.mjs.map +1 -1
  44. package/dist/lib/core/registry.mjs +80 -0
  45. package/dist/lib/core/registry.mjs.map +1 -0
  46. package/dist/lib/core/url-loader.mjs +326 -2
  47. package/dist/lib/core/url-loader.mjs.map +1 -0
  48. package/dist/lib/index.mjs +47 -45
  49. package/dist/lib/index.mjs.map +1 -1
  50. package/dist/lib/plugin-process-manager/history/history-tracker.mjs +2 -0
  51. package/dist/lib/plugin-process-manager/history/undo-mapping.mjs +47 -0
  52. package/dist/lib/plugin-process-manager/history/undo-mapping.mjs.map +1 -0
  53. package/dist/lib/plugin-process-manager/history/undo-registry.mjs +22 -0
  54. package/dist/lib/plugin-process-manager/history/undo-registry.mjs.map +1 -0
  55. package/dist/lib/testing/react.mjs +3 -3
  56. package/dist/lib/testing/react.mjs.map +1 -1
  57. package/dist/lib/testing.mjs +106 -40
  58. package/dist/lib/testing.mjs.map +1 -1
  59. package/dist/lib/ui.mjs +3 -636
  60. package/dist/lib/vite-plugin/packages.mjs +135 -0
  61. package/dist/lib/vite-plugin/packages.mjs.map +1 -0
  62. package/dist/lib/vite-plugin.mjs +51 -164
  63. package/dist/lib/vite-plugin.mjs.map +1 -1
  64. package/dist/plugin/node-esm/index.mjs +129 -76
  65. package/dist/plugin/node-esm/index.mjs.map +4 -4
  66. package/dist/plugin/node-esm/meta.json +1 -1
  67. package/dist/plugin-cli/node-esm/main.mjs +754 -0
  68. package/dist/plugin-cli/node-esm/main.mjs.map +7 -0
  69. package/dist/plugin-cli/node-esm/meta.json +1 -0
  70. package/dist/types/src/cli/cli.d.ts +8 -6
  71. package/dist/types/src/cli/cli.d.ts.map +1 -1
  72. package/dist/types/src/common/activation-events.d.ts +25 -12
  73. package/dist/types/src/common/activation-events.d.ts.map +1 -1
  74. package/dist/types/src/common/capabilities.d.ts +44 -32
  75. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  76. package/dist/types/src/common/capabilities.test.d.ts +2 -0
  77. package/dist/types/src/common/capabilities.test.d.ts.map +1 -0
  78. package/dist/types/src/common/translations.d.ts +5 -5
  79. package/dist/types/src/common/translations.d.ts.map +1 -1
  80. package/dist/types/src/core/activation-event.d.ts +28 -0
  81. package/dist/types/src/core/activation-event.d.ts.map +1 -1
  82. package/dist/types/src/core/capability-manager.d.ts +28 -2
  83. package/dist/types/src/core/capability-manager.d.ts.map +1 -1
  84. package/dist/types/src/core/capability.d.ts +309 -42
  85. package/dist/types/src/core/capability.d.ts.map +1 -1
  86. package/dist/types/src/core/capability.test.d.ts +2 -0
  87. package/dist/types/src/core/capability.test.d.ts.map +1 -0
  88. package/dist/types/src/core/errors.d.ts +230 -0
  89. package/dist/types/src/core/errors.d.ts.map +1 -0
  90. package/dist/types/src/core/index.d.ts +1 -0
  91. package/dist/types/src/core/index.d.ts.map +1 -1
  92. package/dist/types/src/core/plugin-manager/activation-graph.d.ts +83 -0
  93. package/dist/types/src/core/plugin-manager/activation-graph.d.ts.map +1 -0
  94. package/dist/types/src/core/plugin-manager/activation-graph.test.d.ts +2 -0
  95. package/dist/types/src/core/plugin-manager/activation-graph.test.d.ts.map +1 -0
  96. package/dist/types/src/core/plugin-manager/activation-scheduler.d.ts +98 -0
  97. package/dist/types/src/core/plugin-manager/activation-scheduler.d.ts.map +1 -0
  98. package/dist/types/src/core/plugin-manager/idle.d.ts +13 -0
  99. package/dist/types/src/core/plugin-manager/idle.d.ts.map +1 -0
  100. package/dist/types/src/core/plugin-manager/index.d.ts +2 -0
  101. package/dist/types/src/core/plugin-manager/index.d.ts.map +1 -0
  102. package/dist/types/src/core/plugin-manager/manager-state.d.ts +135 -0
  103. package/dist/types/src/core/plugin-manager/manager-state.d.ts.map +1 -0
  104. package/dist/types/src/core/plugin-manager/manager-types.d.ts +104 -0
  105. package/dist/types/src/core/plugin-manager/manager-types.d.ts.map +1 -0
  106. package/dist/types/src/core/plugin-manager/module-loader.d.ts +74 -0
  107. package/dist/types/src/core/plugin-manager/module-loader.d.ts.map +1 -0
  108. package/dist/types/src/core/plugin-manager/plugin-catalog.d.ts +74 -0
  109. package/dist/types/src/core/plugin-manager/plugin-catalog.d.ts.map +1 -0
  110. package/dist/types/src/core/{plugin-manager.d.ts → plugin-manager/plugin-manager.d.ts} +36 -107
  111. package/dist/types/src/core/plugin-manager/plugin-manager.d.ts.map +1 -0
  112. package/dist/types/src/core/plugin-manager/plugin-manager.test.d.ts.map +1 -0
  113. package/dist/types/src/core/plugin-manifest.d.ts +19 -19
  114. package/dist/types/src/core/plugin-manifest.d.ts.map +1 -1
  115. package/dist/types/src/core/plugin.d.ts +173 -98
  116. package/dist/types/src/core/plugin.d.ts.map +1 -1
  117. package/dist/types/src/core/plugin.test.d.ts +2 -0
  118. package/dist/types/src/core/plugin.test.d.ts.map +1 -0
  119. package/dist/types/src/core/registry.d.ts +3 -2
  120. package/dist/types/src/core/registry.d.ts.map +1 -1
  121. package/dist/types/src/devtools.d.ts +60 -0
  122. package/dist/types/src/devtools.d.ts.map +1 -0
  123. package/dist/types/src/index.d.ts +1 -0
  124. package/dist/types/src/index.d.ts.map +1 -1
  125. package/dist/types/src/plugin-cli/barrel.d.ts +21 -0
  126. package/dist/types/src/plugin-cli/barrel.d.ts.map +1 -0
  127. package/dist/types/src/plugin-cli/generate.d.ts +21 -0
  128. package/dist/types/src/plugin-cli/generate.d.ts.map +1 -0
  129. package/dist/types/src/plugin-cli/generate.test.d.ts +2 -0
  130. package/dist/types/src/plugin-cli/generate.test.d.ts.map +1 -0
  131. package/dist/types/src/plugin-cli/main.d.ts +2 -0
  132. package/dist/types/src/plugin-cli/main.d.ts.map +1 -0
  133. package/dist/types/src/plugin-cli/maker-defaults.d.ts +18 -0
  134. package/dist/types/src/plugin-cli/maker-defaults.d.ts.map +1 -0
  135. package/dist/types/src/plugin-cli/ts-util.d.ts +72 -0
  136. package/dist/types/src/plugin-cli/ts-util.d.ts.map +1 -0
  137. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts.map +1 -1
  138. package/dist/types/src/plugin-process-manager/history/capability.d.ts +1 -1
  139. package/dist/types/src/plugin-process-manager/history/types.d.ts +1 -1
  140. package/dist/types/src/plugin-process-manager/history/types.d.ts.map +1 -1
  141. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts +1 -1
  142. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts.map +1 -1
  143. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts +1 -1
  144. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts.map +1 -1
  145. package/dist/types/src/plugin-process-manager/idb-key-value-store.d.ts +1 -1
  146. package/dist/types/src/plugin-process-manager/idb-key-value-store.d.ts.map +1 -1
  147. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts +10 -1
  148. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -1
  149. package/dist/types/src/plugin-process-manager/process-manager-capability.test.d.ts +2 -0
  150. package/dist/types/src/plugin-process-manager/process-manager-capability.test.d.ts.map +1 -0
  151. package/dist/types/src/plugin-process-manager/testing.d.ts +1 -1
  152. package/dist/types/src/plugin-process-manager/testing.d.ts.map +1 -1
  153. package/dist/types/src/testing/demand-gated.d.ts +26 -0
  154. package/dist/types/src/testing/demand-gated.d.ts.map +1 -0
  155. package/dist/types/src/testing/harness.d.ts +21 -5
  156. package/dist/types/src/testing/harness.d.ts.map +1 -1
  157. package/dist/types/src/testing/index.d.ts +1 -0
  158. package/dist/types/src/testing/index.d.ts.map +1 -1
  159. package/dist/types/src/testing/operationCapture.d.ts +2 -2
  160. package/dist/types/src/testing/operationCapture.d.ts.map +1 -1
  161. package/dist/types/src/testing/withPluginManager.d.ts +8 -3
  162. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  163. package/dist/types/src/testing/withPluginManager.stories.d.ts +2 -1
  164. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  165. package/dist/types/src/testing/withSurfaceDebug.d.ts +1 -1
  166. package/dist/types/src/testing/withSurfaceDebug.d.ts.map +1 -1
  167. package/dist/types/src/ui/components/App/App.d.ts.map +1 -1
  168. package/dist/types/src/ui/components/App/App.stories.d.ts +2 -1
  169. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -1
  170. package/dist/types/src/ui/components/App/loader.d.ts +5 -0
  171. package/dist/types/src/ui/components/App/loader.d.ts.map +1 -1
  172. package/dist/types/src/ui/components/HomeSection/HomeSection.stories.d.ts +2 -1
  173. package/dist/types/src/ui/components/HomeSection/HomeSection.stories.d.ts.map +1 -1
  174. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts +2 -1
  175. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -1
  176. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +2 -3
  177. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -1
  178. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
  179. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts +3 -2
  180. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
  181. package/dist/types/src/ui/components/Surface/SurfaceDebug.d.ts.map +1 -1
  182. package/dist/types/src/ui/components/Surface/SurfaceManager.d.ts +22 -3
  183. package/dist/types/src/ui/components/Surface/SurfaceManager.d.ts.map +1 -1
  184. package/dist/types/src/ui/components/Surface/index.d.ts +16 -16
  185. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
  186. package/dist/types/src/ui/components/Surface/types.d.ts +7 -19
  187. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
  188. package/dist/types/src/ui/hooks/index.d.ts +1 -0
  189. package/dist/types/src/ui/hooks/index.d.ts.map +1 -1
  190. package/dist/types/src/ui/hooks/useActivationSignal.d.ts +9 -0
  191. package/dist/types/src/ui/hooks/useActivationSignal.d.ts.map +1 -0
  192. package/dist/types/src/ui/hooks/useApp.d.ts +0 -1
  193. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -1
  194. package/dist/types/src/ui/hooks/useCapabilities.d.ts +20 -6
  195. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
  196. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts +2 -2
  197. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts.map +1 -1
  198. package/dist/types/src/ui/hooks/useSettingsState.d.ts +1 -1
  199. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -1
  200. package/dist/types/src/vite-plugin/import-map/index.d.ts +8 -0
  201. package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -1
  202. package/dist/types/src/vite-plugin/import-map/index.test.d.ts +2 -0
  203. package/dist/types/src/vite-plugin/import-map/index.test.d.ts.map +1 -0
  204. package/dist/types/src/vite-plugin/load.d.ts +7 -5
  205. package/dist/types/src/vite-plugin/load.d.ts.map +1 -1
  206. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -1
  207. package/dist/types/tsconfig.tsbuildinfo +1 -1
  208. package/docs/activation-sequence.md +138 -0
  209. package/moon.yml +18 -1
  210. package/package.json +87 -44
  211. package/src/cli/cli.ts +14 -10
  212. package/src/common/activation-events.ts +27 -21
  213. package/src/common/capabilities.test.ts +71 -0
  214. package/src/common/capabilities.ts +65 -39
  215. package/src/common/translations.ts +10 -11
  216. package/src/core/activation-event.ts +31 -0
  217. package/src/core/capability-manager.test.ts +53 -15
  218. package/src/core/capability-manager.ts +110 -10
  219. package/src/core/capability.test.ts +124 -0
  220. package/src/core/capability.ts +530 -88
  221. package/src/core/capability.tst.ts +52 -0
  222. package/src/core/errors.ts +82 -0
  223. package/src/core/index.ts +1 -0
  224. package/src/core/plugin-manager/activation-graph.test.ts +177 -0
  225. package/src/core/plugin-manager/activation-graph.ts +269 -0
  226. package/src/core/plugin-manager/activation-scheduler.ts +1012 -0
  227. package/src/core/plugin-manager/idle.ts +67 -0
  228. package/src/core/plugin-manager/index.ts +7 -0
  229. package/src/core/plugin-manager/manager-state.ts +376 -0
  230. package/src/core/plugin-manager/manager-types.ts +68 -0
  231. package/src/core/plugin-manager/module-loader.ts +559 -0
  232. package/src/core/plugin-manager/plugin-catalog.ts +683 -0
  233. package/src/core/plugin-manager/plugin-manager.test.ts +3417 -0
  234. package/src/core/plugin-manager/plugin-manager.ts +611 -0
  235. package/src/core/plugin-manifest.ts +6 -5
  236. package/src/core/plugin.test.ts +374 -0
  237. package/src/core/plugin.ts +227 -80
  238. package/src/core/registry.ts +3 -2
  239. package/src/devtools.ts +219 -0
  240. package/src/globals.d.ts +16 -0
  241. package/src/index.ts +1 -0
  242. package/src/plugin-cli/barrel.ts +155 -0
  243. package/src/plugin-cli/generate.test.ts +171 -0
  244. package/src/plugin-cli/generate.ts +295 -0
  245. package/src/plugin-cli/main.ts +53 -0
  246. package/src/plugin-cli/maker-defaults.ts +152 -0
  247. package/src/plugin-cli/ts-util.ts +326 -0
  248. package/src/plugin-process-manager/ProcessManagerPlugin.ts +36 -13
  249. package/src/plugin-process-manager/history/capability.ts +6 -8
  250. package/src/plugin-process-manager/history/history-tracker.test.ts +17 -18
  251. package/src/plugin-process-manager/history/types.ts +1 -1
  252. package/src/plugin-process-manager/history/undo-mapping.ts +1 -1
  253. package/src/plugin-process-manager/history/undo-registry.test.ts +1 -1
  254. package/src/plugin-process-manager/history/undo-registry.ts +1 -1
  255. package/src/plugin-process-manager/idb-key-value-store.ts +3 -11
  256. package/src/plugin-process-manager/process-manager-capability.test.ts +144 -0
  257. package/src/plugin-process-manager/process-manager-capability.ts +88 -27
  258. package/src/plugin-process-manager/testing.ts +9 -9
  259. package/src/testing/demand-gated.ts +54 -0
  260. package/src/testing/harness.ts +35 -15
  261. package/src/testing/index.ts +1 -0
  262. package/src/testing/operationCapture.ts +3 -3
  263. package/src/testing/react.test.tsx +5 -5
  264. package/src/testing/react.tsx +2 -2
  265. package/src/testing/withPluginManager.stories.tsx +1 -1
  266. package/src/testing/withPluginManager.tsx +70 -21
  267. package/src/testing/withSurfaceDebug.tsx +1 -1
  268. package/src/ui/components/App/App.stories.tsx +3 -3
  269. package/src/ui/components/App/App.tsx +36 -18
  270. package/src/ui/components/App/loader.ts +5 -0
  271. package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +7 -6
  272. package/src/ui/components/PluginManager/PluginManagerProvider.ts +2 -3
  273. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +2 -2
  274. package/src/ui/components/Surface/SurfaceComponent.test.tsx +199 -18
  275. package/src/ui/components/Surface/SurfaceComponent.tsx +83 -7
  276. package/src/ui/components/Surface/SurfaceManager.ts +82 -15
  277. package/src/ui/components/Surface/types.test.ts +6 -2
  278. package/src/ui/components/Surface/types.ts +23 -27
  279. package/src/ui/hooks/index.ts +1 -0
  280. package/src/ui/hooks/useActivationSignal.ts +26 -0
  281. package/src/ui/hooks/useApp.test.tsx +7 -4
  282. package/src/ui/hooks/useApp.tsx +37 -19
  283. package/src/ui/hooks/useCapabilities.ts +32 -19
  284. package/src/ui/hooks/useProcessManagerRuntime.ts +11 -6
  285. package/src/ui/hooks/useSettingsState.ts +3 -1
  286. package/src/vite-plugin/boot-loader/loader-app/Loader.solid-stories.tsx +96 -0
  287. package/src/vite-plugin/boot-loader/loader-app/Loader.tsx +11 -0
  288. package/src/vite-plugin/boot-loader/loader-app/boot-loader.css +42 -0
  289. package/src/vite-plugin/boot-loader/loader-app/bridge.ts +1 -0
  290. package/src/vite-plugin/boot-loader/loader-app/entry.tsx +6 -0
  291. package/src/vite-plugin/boot-loader/loader-app/store.test.ts +53 -0
  292. package/src/vite-plugin/boot-loader/loader-app/store.ts +42 -2
  293. package/src/vite-plugin/boot-loader/loader-app/types.ts +10 -0
  294. package/src/vite-plugin/import-map/index.test.ts +60 -0
  295. package/src/vite-plugin/import-map/index.ts +29 -2
  296. package/src/vite-plugin/load.ts +30 -28
  297. package/src/vite-plugin/manifest.test.ts +5 -5
  298. package/src/vite-plugin/packages.ts +1 -4
  299. package/tsconfig.json +5 -10
  300. package/vite.config.ts +12 -1
  301. package/dist/lib/chunk-plugin-manifest.mjs.map +0 -1
  302. package/dist/lib/chunk-url-loader.mjs +0 -347
  303. package/dist/lib/chunk-url-loader.mjs.map +0 -1
  304. package/dist/lib/core/capability.mjs.map +0 -1
  305. package/dist/lib/ui.mjs.map +0 -1
  306. package/dist/types/src/common/annotations.d.ts +0 -1
  307. package/dist/types/src/common/annotations.d.ts.map +0 -1
  308. package/dist/types/src/core/plugin-manager.d.ts.map +0 -1
  309. package/dist/types/src/core/plugin-manager.test.d.ts.map +0 -1
  310. package/src/common/annotations.ts +0 -3
  311. package/src/core/plugin-manager.test.ts +0 -1960
  312. package/src/core/plugin-manager.ts +0 -1719
  313. package/src/vite-plugin/boot-loader/BootLoader.solid-stories.tsx +0 -198
  314. /package/dist/types/src/core/{plugin-manager.test.d.ts → plugin-manager/plugin-manager.test.d.ts} +0 -0
package/API.md ADDED
@@ -0,0 +1,275 @@
1
+ # DXOS App Framework API
2
+
3
+ Companion to [ARCHITECTURE.md](./ARCHITECTURE.md), which covers how the pieces relate. This is the
4
+ API surface.
5
+
6
+ ## Imports
7
+
8
+ ```ts
9
+ import {
10
+ ActivationEvent, // Runtime activation events (make/oneOf/allOf)
11
+ ActivationEvents, // Well-known framework events (Startup, ...)
12
+ Capabilities, // Well-known capability tags (ReactSurface, OperationHandler, ...)
13
+ Capability, // Capability tags, contributions, module authoring
14
+ Plugin, // Plugin definition + builder
15
+ PluginManager, // Manager type (usually obtained, not constructed)
16
+ } from '@dxos/app-framework';
17
+ import { Surface, useApp, useCapabilities, useCapability } from '@dxos/app-framework/ui';
18
+ import { withPluginManager } from '@dxos/app-framework/testing';
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Defining a capability
24
+
25
+ A capability is a typed, NSID-keyed slot. **Arity is chosen at definition** and decides what
26
+ consumers get.
27
+
28
+ ```ts
29
+ // Multi (the default): an open registry many modules contribute to.
30
+ export const Template = Capability.make<Template>()('org.dxos.plugin.projects.capability.template');
31
+
32
+ // Singleton: exactly one provider.
33
+ export const Client = Capability.makeSingleton<ClientApi>()('org.dxos.plugin.client.capability.client');
34
+ ```
35
+
36
+ Both are curried — `make<T>()(nsid)` — so the NSID string literal is captured and brands the
37
+ identifier. NSIDs must be camelCase (`DXN.Name`). The single-call form `make<T>(nsid)` still compiles
38
+ but widens the NSID to `string`, making the compile-time check vacuous; prefer the curried form.
39
+
40
+ | | `makeSingleton` → `Tag<T>` | `make` → `MultiTag<T>` |
41
+ | ------------------ | ------------------------------------ | ----------------------------------------- |
42
+ | `yield* tag` gives | `T` | `Contributions<T>` (live view) |
43
+ | Requiring it | gates activation on its one provider | never gates — the collection may be empty |
44
+ | Two providers | `DuplicateProviderError` | normal |
45
+
46
+ ---
47
+
48
+ ## Authoring a module
49
+
50
+ A module is a body plus a declaration of what it `requires` and `provides`.
51
+
52
+ ```ts
53
+ // Code-split (the common case) — the chunk loads when the module activates.
54
+ export const Coordinator = Capability.lazyModule(
55
+ 'ConnectorCoordinator',
56
+ { requires: [ClientCapabilities.Client], provides: [ConnectorCoordinator] },
57
+ () => import('./connector-coordinator'),
58
+ );
59
+
60
+ // Eager — body defined inline, no separate chunk.
61
+ export const Extractor = Capability.inlineModule(
62
+ 'SummarizeExtractor',
63
+ { provides: [InboxCapabilities.ObjectExtractor] },
64
+ () => Effect.succeed(Capability.contribute(InboxCapabilities.ObjectExtractor, extractor)),
65
+ );
66
+ ```
67
+
68
+ The body is written with `Capability.makeModule` and yields its declared requirements:
69
+
70
+ ```ts
71
+ export default Capability.makeModule(
72
+ Effect.fnUntraced(function* () {
73
+ const client = yield* ClientCapabilities.Client; // declared in `requires`
74
+ const coordinator = new Coordinator(client);
75
+ return Capability.contribute(ConnectorCoordinator, coordinator);
76
+ }),
77
+ );
78
+ ```
79
+
80
+ Yielding a tag that is not in `requires` is a type error (it escapes the `R` channel); failing to
81
+ contribute a declared `provides` is also a type error.
82
+
83
+ **Makers.** Capability owners export a maker so call sites don't repeat `provides`.
84
+ `@dxos/app-toolkit` ships them for the common capabilities:
85
+
86
+ ```ts
87
+ export const ReactSurface = AppCapability.surface(() => import('./react-surface'));
88
+ export const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('./app-graph-builder'), {
89
+ requires: [SomeCapabilities.Thing],
90
+ });
91
+ ```
92
+
93
+ Build your own with `Capability.moduleMaker(name, tag)`.
94
+
95
+ ---
96
+
97
+ ## Composing a plugin
98
+
99
+ ```ts
100
+ export const FooPlugin = Plugin.define(meta).pipe(
101
+ Plugin.addModule(ReactSurface),
102
+ Plugin.addModule(Coordinator),
103
+ Plugin.addModule(AppCapability.translations(translations)),
104
+ Plugin.addModule(AppCapability.schema([Foo.Foo])),
105
+ Plugin.make,
106
+ );
107
+ ```
108
+
109
+ `Plugin.define(meta)` starts a builder; each `addModule` adds one module; `Plugin.make` seals it.
110
+ When the plugin takes options, `addModule` also accepts `(options) => module` and makers accept a
111
+ `props` mapping from plugin options to body props. If every option is optional, calling
112
+ `FooPlugin()` with no argument is allowed.
113
+
114
+ ---
115
+
116
+ ## Consuming capabilities
117
+
118
+ Three access paths, for three situations.
119
+
120
+ **1. Inside a module body** — declared, type-checked, ordering-aware.
121
+
122
+ ```ts
123
+ Effect.fnUntraced(function* () {
124
+ const client = yield* ClientCapabilities.Client; // singleton → T
125
+ const templates = yield* ProjectCapabilities.Template; // multi → Contributions<T>
126
+ });
127
+ ```
128
+
129
+ **2. Outside a module** (operations, callbacks, non-module code) — dynamic, string-keyed.
130
+
131
+ ```ts
132
+ Effect.gen(function* () {
133
+ const handlers = yield* Capability.getAll(Capabilities.OperationHandler);
134
+ const maybe = yield* Capability.getOption(AppCapabilities.ProgressRegistry);
135
+ const surfaces = yield* Capability.atom(Capabilities.ReactSurface); // reactive
136
+ const client = yield* Capability.waitFor(ClientCapabilities.Client); // resolves when contributed
137
+ });
138
+ ```
139
+
140
+ **3. React.**
141
+
142
+ ```tsx
143
+ const surfaces = useCapabilities(Capabilities.ReactSurface);
144
+ const client = useCapability(ClientCapabilities.Client);
145
+ ```
146
+
147
+ > In graph-extension atom callbacks always use `Capability.atom`, never a synchronous
148
+ > `Capability.get` — a sync read inside an atom body caches a defect fallback with no reactive
149
+ > dependency.
150
+
151
+ ---
152
+
153
+ ## Contributing values
154
+
155
+ A module returns its contributions from `activate`. `contribute` carries one value, `contributeAll`
156
+ carries several for the same capability; both produce a single `Contribution`.
157
+
158
+ ```ts
159
+ return [
160
+ Capability.contribute(Capabilities.ReactSurface, surface),
161
+ Capability.contributeAll(Capabilities.LayerSpec, [clientSpec, databaseSpec]),
162
+ ];
163
+ ```
164
+
165
+ A module providing exactly one capability may return the `Contribution` directly, without the array.
166
+ An optional third argument is a `deactivate` hook, run once when the module is deactivated.
167
+
168
+ The return is checked against the module's declared `provides`: omitting a declared capability is a
169
+ type error, and contributing an undeclared one fails at runtime.
170
+
171
+ ## Reading a multi capability
172
+
173
+ A multi capability has no single value, and its membership changes as plugins are enabled and
174
+ disabled. Reading one therefore gives a live `Contributions<T>` view rather than an array:
175
+
176
+ ```ts
177
+ Effect.fnUntraced(function* () {
178
+ const templates = yield* ProjectCapabilities.Template; // Contributions<Template>
179
+
180
+ templates.get(); // readonly Template[] — snapshot as of now
181
+ templates.subscribe((values) => setTemplates(values)); // → unsubscribe
182
+ templates.atom; // Atom<Template[]> for Atom-based composition
183
+ });
184
+ ```
185
+
186
+ `get()` is a point-in-time snapshot: hold onto it and it will not reflect capabilities contributed
187
+ later. Consume the collection reactively — via `subscribe`, `atom`, or the React hooks — unless the
188
+ value is used immediately and discarded.
189
+
190
+ ### `Contribution` vs `Contributions`
191
+
192
+ Two types one letter apart, on either side of the registry:
193
+
194
+ | | `Contribution` | `Contributions<T>` |
195
+ | ----------- | ----------------------------------------- | ------------------------------------------------------------ |
196
+ | Direction | what a module **produces** | what a consumer **reads** |
197
+ | Produced by | `Capability.contribute` / `contributeAll` | `yield*` on a `MultiTag`, or `Capability.contributions(tag)` |
198
+ | Shape | `{ capability, values, deactivate? }` | `{ atom, get(), subscribe() }` |
199
+ | Scope | one module's values for one capability | every module's values for one capability |
200
+
201
+ ---
202
+
203
+ ## Activation
204
+
205
+ A module activates in one of two modes, normalized onto `PluginModule.activation`:
206
+
207
+ - **Dependency mode** (the default) — declared `requires`/`provides`. The manager topologically
208
+ orders modules so providers run before consumers. A module with no `requires` is a startup root.
209
+ - **Event mode** — `activatesOn` a genuine runtime event; `requires` are pulled on demand when it
210
+ fires.
211
+
212
+ ```ts
213
+ Capability.lazyModule(
214
+ 'OnSpaceCreated',
215
+ { activatesOn: SpaceEvents.SpaceCreated, provides: [] },
216
+ () => import('./on-space-created'),
217
+ );
218
+ ```
219
+
220
+ Surviving events are runtime occurrences only — `ActivationEvents.Startup`, `SpacesReady`,
221
+ `SpaceCreated`, `IdentityCreated`, `TypeAdded`, plus parameterized `createStateEvent` /
222
+ `createSettingsEvent`. Ordering-only `Setup*`/`*Ready` events were removed; express ordering as
223
+ `requires`/`provides`.
224
+
225
+ Structural problems isolate rather than abort startup: a dependency cycle, duplicate singleton
226
+ provider, or unsatisfiable requirement puts the owning plugin in an error state
227
+ (`DependencyCycleError`, `DuplicateProviderError`, `MissingProviderError`,
228
+ `ProvidesMismatchError`) and everything else proceeds.
229
+
230
+ ---
231
+
232
+ ## Well-known capabilities
233
+
234
+ `Capabilities` (framework) — `ReactSurface`, `ReactContext`, `ReactRoot`, `OperationHandler`,
235
+ `OperationInvoker`, `UndoMapping`, `Command`, `Layer`, `LayerSpec`, `TraceSink`, `AtomRegistry`,
236
+ `ServiceResolver`, `ProcessManagerRuntime`, `ProcessMonitor`, `PluginManager`.
237
+
238
+ `AppCapabilities` (`@dxos/app-toolkit`) — `Translations`, `Schema`, `Settings`, `AppGraph`,
239
+ `AppGraphBuilder`, `SkillDefinition`, `PluginAsset`, `Toolkit`, `NavigationTargetResolver`,
240
+ `NavigationHandler`, `TextContent`, `CommentConfig`, `AnchorSort`, `AnchorResolver`, `Layout`.
241
+
242
+ ---
243
+
244
+ ## Testing
245
+
246
+ ```ts
247
+ withPluginManager({
248
+ plugins: [ClientPlugin(), FooPlugin()],
249
+ capabilities: [Capability.contribute(SomeCapability, stub)], // takes Contribution[]
250
+ });
251
+ ```
252
+
253
+ `@dxos/app-framework/testing` also exports `harness` (headless activation assertions) and
254
+ `createComposerTestApp`.
255
+
256
+ ---
257
+
258
+ ## Type reference
259
+
260
+ | Type | Meaning |
261
+ | ----------------------------- | -------------------------------------------------------------- |
262
+ | `Capability.Tag<T, S>` | Singleton tag; `yield*` → `T` |
263
+ | `Capability.MultiTag<T, S>` | Multi tag; `yield*` → `Contributions<T>` |
264
+ | `Capability.AnyTag` | `Tag \| MultiTag` |
265
+ | `Capability.Contribution` | One branded contribution (capability + n values) |
266
+ | `Capability.Contributions<T>` | Live view: `{ atom, get(), subscribe() }` |
267
+ | `Capability.Any` | A registry entry: `{ interface, implementation, deactivate? }` |
268
+ | `Capability.Module<Options>` | An authored module, opaque except for its options type |
269
+ | `Plugin.Plugin` | `{ meta, modules }` |
270
+ | `Plugin.PluginModule` | `{ id, activation, activate() }` |
271
+ | `Plugin.ActivationSpec` | `dependency \| event` discriminated union |
272
+
273
+ `Contribution` → `Capability.Any` is a 1-to-n expansion performed by the manager
274
+ (`CapabilityManager.expandContributions`); see
275
+ [ARCHITECTURE.md](./ARCHITECTURE.md#the-two-layer-split).
@@ -0,0 +1,190 @@
1
+ # Architecture
2
+
3
+ How plugins, modules, capabilities and contributions relate.
4
+
5
+ The short version: a **plugin** is a bag of **modules**; a module declares which **capabilities** it
6
+ `requires` and `provides`, and its body returns **contributions**; the manager topologically orders
7
+ activation from those declarations and expands each contribution into the flat entries the
8
+ **capability registry** stores.
9
+
10
+ ## Domain model
11
+
12
+ ```mermaid
13
+ classDiagram
14
+ direction TB
15
+
16
+ class Plugin {
17
+ +Meta meta
18
+ +PluginModule[] modules
19
+ }
20
+
21
+ class PluginModule {
22
+ +string id
23
+ +ActivationSpec activation
24
+ +activate(props) Effect
25
+ }
26
+
27
+ class ActivationSpec {
28
+ +mode dependency | event
29
+ +AnyTag[] requires
30
+ +AnyTag[] provides
31
+ +Events activatesOn
32
+ }
33
+
34
+ class Module {
35
+ +AnyTag[] requires
36
+ +AnyTag[] provides
37
+ +Events activatesOn
38
+ +call(options) Effect
39
+ }
40
+
41
+ class Tag {
42
+ +arity single
43
+ +yield* gives T
44
+ }
45
+
46
+ class MultiTag {
47
+ +arity multi
48
+ +yield* gives Contributions
49
+ }
50
+
51
+ class Contribution {
52
+ +AnyTag capability
53
+ +unknown[] values
54
+ +deactivate()
55
+ }
56
+
57
+ class CapabilityEntry {
58
+ +InterfaceDef interface
59
+ +T implementation
60
+ +deactivate()
61
+ }
62
+
63
+ class Contributions {
64
+ +Atom atom
65
+ +get() T[]
66
+ +subscribe(cb)
67
+ }
68
+
69
+ class CapabilityManager {
70
+ +contribute(entry)
71
+ +get(tag) T
72
+ +getAll(tag) T[]
73
+ +atom(tag) Atom
74
+ +contributions(tag) Contributions
75
+ }
76
+
77
+ class PluginManager {
78
+ +start()
79
+ +activate(event)
80
+ }
81
+
82
+ Plugin "1" *-- "0..n" PluginModule : modules
83
+ PluginModule --> ActivationSpec : activation
84
+ Module ..> PluginModule : Plugin.addModule()
85
+ ActivationSpec ..> Tag : requires / provides
86
+ ActivationSpec ..> MultiTag : requires / provides
87
+ Tag ..> Contribution : Capability.contribute()
88
+ MultiTag ..> Contribution : Capability.contributeAll()
89
+ Contribution ..> CapabilityEntry : expandContributions() 1 to n
90
+ CapabilityManager "1" o-- "0..n" CapabilityEntry : registry keyed by NSID
91
+ CapabilityManager ..> Contributions : live view for a MultiTag
92
+ PluginManager --> PluginModule : orders and activates
93
+ PluginManager --> CapabilityManager : owns
94
+ ```
95
+
96
+ ### The two-layer split
97
+
98
+ `Contribution` and `CapabilityEntry` (exported as `Capability.Any`) sit on either side of the
99
+ registry boundary — the authoring layer and the storage layer:
100
+
101
+ | | `Contribution` (authoring) | `Capability.Any` (registry) |
102
+ | ------------ | ---------------------------------------------------------------------------------------------- | --------------------------------------- |
103
+ | Produced by | `Capability.contribute` / `contributeAll` | `CapabilityManager.expandContributions` |
104
+ | Holds | **n** values for one capability | exactly **one** implementation |
105
+ | Identity | branded by capability identity (NSID + arity) — powers the `EnsureProvides` completeness check | the `InterfaceDef` only |
106
+ | Service type | erased to `AnyTag`, so a body's service type never leaks into `.d.ts` emit | names `T` directly |
107
+
108
+ `expandContributions` is the one-way bridge: a `contributeAll(tag, [a, b, c])` is one `Contribution`
109
+ that becomes three registry entries, with the `deactivate` hook pinned to the first so it runs
110
+ exactly once.
111
+
112
+ ## Activation
113
+
114
+ ```mermaid
115
+ flowchart TB
116
+ subgraph authoring["Authoring (compile time)"]
117
+ A1["Capability.make / makeSingleton<br/>defines a Tag"]
118
+ A2["Capability.lazyModule / inlineModule<br/>or an AppCapability maker<br/>→ Capability.Module"]
119
+ A3["Plugin.define(meta).pipe(<br/>Plugin.addModule(...), Plugin.make)<br/>→ Plugin"]
120
+ A1 --> A2 --> A3
121
+ end
122
+
123
+ subgraph ordering["Ordering (PluginManager.start)"]
124
+ B1["Collect every enabled plugin's modules"]
125
+ B2{"activation.mode"}
126
+ B3["dependency:<br/>edges from requires → provides<br/>Kahn topological waves"]
127
+ B4["event:<br/>parked until activatesOn fires,<br/>requires pulled on demand"]
128
+ B1 --> B2
129
+ B2 -->|dependency| B3
130
+ B2 -->|event| B4
131
+ end
132
+
133
+ subgraph runtime["Activation + registry"]
134
+ C1["Build the module's Context<br/>from its requires"]
135
+ C2["activate(props) → Contribution[]"]
136
+ C3["Validate against declared provides"]
137
+ C4["expandContributions → Capability.Any[]"]
138
+ C5["CapabilityManager.contribute(entry)"]
139
+ C1 --> C2 --> C3 --> C4 --> C5
140
+ end
141
+
142
+ subgraph consume["Consumption"]
143
+ D1["In a module body:<br/>yield* Tag"]
144
+ D2["Dynamically:<br/>Capability.get / getAll / atom"]
145
+ D3["Reactively:<br/>Contributions.atom"]
146
+ end
147
+
148
+ A3 --> B1
149
+ B3 --> C1
150
+ B4 --> C1
151
+ C5 --> D1
152
+ C5 --> D2
153
+ C5 --> D3
154
+ ```
155
+
156
+ Failure modes are structural rather than fatal: a dependency cycle, a duplicate singleton provider,
157
+ or an unsatisfiable `requires` puts the owning plugin into an error state and excludes it from
158
+ further rounds, while everything else proceeds. A consumer whose provider is event-gated **waits**
159
+ rather than erroring, and activates in a later round once the provider contributes.
160
+
161
+ ### Singleton vs multi
162
+
163
+ Arity is a property of the tag and decides what `yield*` gives you:
164
+
165
+ - `Capability.makeSingleton<T>()(nsid)` → `Tag`. `yield* tag` gives `T`. Requiring one gates
166
+ activation on its single provider; two providers is a `DuplicateProviderError`.
167
+ - `Capability.make<T>()(nsid)` → `MultiTag` (the default). `yield* tag` gives a live
168
+ `Contributions<T>` collection. Providers never gate consumers, so consume it reactively — a
169
+ one-shot snapshot silently misses late contributions.
170
+
171
+ Both forms are curried so the NSID string literal is captured and brands the identifier; the NSID
172
+ must be camelCase (`DXN.Name`).
173
+
174
+ ## Where things live
175
+
176
+ | Concept | File |
177
+ | -------------------------------------------------------------------- | -------------------------------------------------------- |
178
+ | Tags, arity, `Contribution`, `contribute`, module makers | `src/core/capability.ts` |
179
+ | `Plugin`, `PluginModule`, `ActivationSpec`, the builder | `src/core/plugin.ts` |
180
+ | Public manager API, unit composition, shutdown, failure policy | `src/core/plugin-manager/plugin-manager.ts` |
181
+ | Shared substrate: atoms, status channel, fibers (`ManagerState`) | `src/core/plugin-manager/manager-state.ts` |
182
+ | Catalog: add/enable/disable, lazy resolution, dependency closure | `src/core/plugin-manager/plugin-catalog.ts` |
183
+ | Lifecycle engine: start/activate/deactivate/reset, rounds, waves | `src/core/plugin-manager/activation-scheduler.ts` |
184
+ | Ordering logic (runnable selection, waves, cycles), on `@dxos/graph` | `src/core/plugin-manager/activation-graph.ts` |
185
+ | Memoized module loads, provides validation, deactivation | `src/core/plugin-manager/module-loader.ts` |
186
+ | The NSID-keyed registry and its reactive views | `src/core/capability-manager.ts` |
187
+ | Tagged errors (cycle, missing/duplicate provider, mismatch) | `src/core/errors.ts` |
188
+ | Per-capability module makers (`surface`, `settings`, …) | `@dxos/app-toolkit` `src/app-framework/AppCapability.ts` |
189
+
190
+ Worked examples: `@dxos/plugin-client` and `@dxos/plugin-markdown`.