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

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 (424) hide show
  1. package/.storybook/main.mts +11 -0
  2. package/.storybook/preview.mts +8 -0
  3. package/.swc/plugins/linux_x86_64_19.0.0/727453fb3a62f7f1d952a41e051ca8a6f88cadc45cee43c6a4d1aa45f9b75665.wasmer-v7 +0 -0
  4. package/dist/lib/browser/app-graph-builder-M2VPYQC6.mjs +149 -0
  5. package/dist/lib/browser/app-graph-builder-M2VPYQC6.mjs.map +7 -0
  6. package/dist/lib/browser/capability-7PCNSWBT.mjs +33 -0
  7. package/dist/lib/browser/capability-7PCNSWBT.mjs.map +7 -0
  8. package/dist/lib/browser/capability-KP3PFEXD.mjs +31 -0
  9. package/dist/lib/browser/capability-KP3PFEXD.mjs.map +7 -0
  10. package/dist/lib/browser/chunk-6Y7PZV72.mjs +77 -0
  11. package/dist/lib/browser/chunk-6Y7PZV72.mjs.map +7 -0
  12. package/dist/lib/browser/chunk-7IQHKD4U.mjs +170 -0
  13. package/dist/lib/browser/chunk-7IQHKD4U.mjs.map +7 -0
  14. package/dist/lib/browser/chunk-BLQJSGL3.mjs +732 -0
  15. package/dist/lib/browser/chunk-BLQJSGL3.mjs.map +7 -0
  16. package/dist/lib/browser/chunk-FHQTHCX7.mjs +8 -0
  17. package/dist/lib/browser/chunk-FHQTHCX7.mjs.map +7 -0
  18. package/dist/lib/browser/chunk-FMZN33N4.mjs +807 -0
  19. package/dist/lib/browser/chunk-FMZN33N4.mjs.map +7 -0
  20. package/dist/lib/browser/chunk-H4WPA7U7.mjs +77 -0
  21. package/dist/lib/browser/chunk-H4WPA7U7.mjs.map +7 -0
  22. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  23. package/dist/lib/browser/chunk-PKQT6C53.mjs +47 -0
  24. package/dist/lib/browser/chunk-PKQT6C53.mjs.map +7 -0
  25. package/dist/lib/browser/chunk-TCLLRCS3.mjs +145 -0
  26. package/dist/lib/browser/chunk-TCLLRCS3.mjs.map +7 -0
  27. package/dist/lib/browser/chunk-XYNO72GQ.mjs +746 -0
  28. package/dist/lib/browser/chunk-XYNO72GQ.mjs.map +7 -0
  29. package/dist/lib/browser/common/index.mjs +38 -0
  30. package/dist/lib/browser/core/activation-event.mjs +20 -0
  31. package/dist/lib/browser/core/capability.mjs +28 -0
  32. package/dist/lib/browser/core/plugin-manager.mjs +15 -0
  33. package/dist/lib/browser/core/plugin-manager.mjs.map +7 -0
  34. package/dist/lib/browser/core/plugin.mjs +27 -0
  35. package/dist/lib/browser/core/plugin.mjs.map +7 -0
  36. package/dist/lib/browser/index.mjs +165 -139
  37. package/dist/lib/browser/index.mjs.map +4 -4
  38. package/dist/lib/browser/invoker-capability-SZRSTHEH.mjs +32 -0
  39. package/dist/lib/browser/invoker-capability-SZRSTHEH.mjs.map +7 -0
  40. package/dist/lib/browser/meta.json +1 -1
  41. package/dist/lib/browser/operation-resolver-6MP2MYOY.mjs +64 -0
  42. package/dist/lib/browser/operation-resolver-6MP2MYOY.mjs.map +7 -0
  43. package/dist/lib/browser/react/index.mjs +46 -0
  44. package/dist/lib/browser/react/index.mjs.map +7 -0
  45. package/dist/lib/browser/testing/index.mjs +79 -37
  46. package/dist/lib/browser/testing/index.mjs.map +4 -4
  47. package/dist/lib/node-esm/app-graph-builder-LROHGJEM.mjs +150 -0
  48. package/dist/lib/node-esm/app-graph-builder-LROHGJEM.mjs.map +7 -0
  49. package/dist/lib/node-esm/capability-CFLQ2QQU.mjs +34 -0
  50. package/dist/lib/node-esm/capability-CFLQ2QQU.mjs.map +7 -0
  51. package/dist/lib/node-esm/capability-RCUNM2M7.mjs +32 -0
  52. package/dist/lib/node-esm/capability-RCUNM2M7.mjs.map +7 -0
  53. package/dist/lib/node-esm/chunk-663A54LQ.mjs +171 -0
  54. package/dist/lib/node-esm/chunk-663A54LQ.mjs.map +7 -0
  55. package/dist/lib/node-esm/chunk-6WXBT3EC.mjs +747 -0
  56. package/dist/lib/node-esm/chunk-6WXBT3EC.mjs.map +7 -0
  57. package/dist/lib/node-esm/chunk-7OWSHPYK.mjs +48 -0
  58. package/dist/lib/node-esm/chunk-7OWSHPYK.mjs.map +7 -0
  59. package/dist/lib/node-esm/chunk-GQEBIGKD.mjs +733 -0
  60. package/dist/lib/node-esm/chunk-GQEBIGKD.mjs.map +7 -0
  61. package/dist/lib/node-esm/chunk-GT6OKM5I.mjs +146 -0
  62. package/dist/lib/node-esm/chunk-GT6OKM5I.mjs.map +7 -0
  63. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  64. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  65. package/dist/lib/node-esm/chunk-STMXUEPO.mjs +78 -0
  66. package/dist/lib/node-esm/chunk-STMXUEPO.mjs.map +7 -0
  67. package/dist/lib/node-esm/chunk-UEWJDI2L.mjs +10 -0
  68. package/dist/lib/node-esm/chunk-UEWJDI2L.mjs.map +7 -0
  69. package/dist/lib/node-esm/chunk-XR6NMKEP.mjs +78 -0
  70. package/dist/lib/node-esm/chunk-XR6NMKEP.mjs.map +7 -0
  71. package/dist/lib/node-esm/chunk-XYQTBFPA.mjs +808 -0
  72. package/dist/lib/node-esm/chunk-XYQTBFPA.mjs.map +7 -0
  73. package/dist/lib/node-esm/common/index.mjs +39 -0
  74. package/dist/lib/node-esm/common/index.mjs.map +7 -0
  75. package/dist/lib/node-esm/core/activation-event.mjs +21 -0
  76. package/dist/lib/node-esm/core/activation-event.mjs.map +7 -0
  77. package/dist/lib/node-esm/core/capability.mjs +29 -0
  78. package/dist/lib/node-esm/core/capability.mjs.map +7 -0
  79. package/dist/lib/node-esm/core/plugin-manager.mjs +16 -0
  80. package/dist/lib/node-esm/core/plugin-manager.mjs.map +7 -0
  81. package/dist/lib/node-esm/core/plugin.mjs +28 -0
  82. package/dist/lib/node-esm/core/plugin.mjs.map +7 -0
  83. package/dist/lib/node-esm/index.mjs +165 -139
  84. package/dist/lib/node-esm/index.mjs.map +4 -4
  85. package/dist/lib/node-esm/invoker-capability-PNMA5JOS.mjs +33 -0
  86. package/dist/lib/node-esm/invoker-capability-PNMA5JOS.mjs.map +7 -0
  87. package/dist/lib/node-esm/meta.json +1 -1
  88. package/dist/lib/node-esm/operation-resolver-7YWDMTNU.mjs +65 -0
  89. package/dist/lib/node-esm/operation-resolver-7YWDMTNU.mjs.map +7 -0
  90. package/dist/lib/node-esm/react/index.mjs +47 -0
  91. package/dist/lib/node-esm/react/index.mjs.map +7 -0
  92. package/dist/lib/node-esm/testing/index.mjs +79 -37
  93. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  94. package/dist/types/src/cli.d.ts +39 -0
  95. package/dist/types/src/cli.d.ts.map +1 -0
  96. package/dist/types/src/common/activation-event.d.ts +66 -0
  97. package/dist/types/src/common/activation-event.d.ts.map +1 -0
  98. package/dist/types/src/common/capability.d.ts +265 -0
  99. package/dist/types/src/common/capability.d.ts.map +1 -0
  100. package/dist/types/src/common/collaboration.d.ts +24 -17
  101. package/dist/types/src/common/collaboration.d.ts.map +1 -1
  102. package/dist/types/src/common/file.d.ts +1 -1
  103. package/dist/types/src/common/file.d.ts.map +1 -1
  104. package/dist/types/src/common/graph.d.ts +2 -2
  105. package/dist/types/src/common/graph.d.ts.map +1 -1
  106. package/dist/types/src/common/index.d.ts +5 -4
  107. package/dist/types/src/common/index.d.ts.map +1 -1
  108. package/dist/types/src/common/operations.d.ts +380 -0
  109. package/dist/types/src/common/operations.d.ts.map +1 -0
  110. package/dist/types/src/common/plugin.d.ts +201 -0
  111. package/dist/types/src/common/plugin.d.ts.map +1 -0
  112. package/dist/types/src/common/surface.d.ts +50 -21
  113. package/dist/types/src/common/surface.d.ts.map +1 -1
  114. package/dist/types/src/common/translations.d.ts +10 -1
  115. package/dist/types/src/common/translations.d.ts.map +1 -1
  116. package/dist/types/src/context.d.ts +5 -0
  117. package/dist/types/src/context.d.ts.map +1 -0
  118. package/dist/types/src/core/{events.d.ts → activation-event.d.ts} +6 -6
  119. package/dist/types/src/core/activation-event.d.ts.map +1 -0
  120. package/dist/types/src/core/capability-manager.d.ts +43 -0
  121. package/dist/types/src/core/capability-manager.d.ts.map +1 -0
  122. package/dist/types/src/core/capability-manager.test.d.ts +2 -0
  123. package/dist/types/src/core/capability-manager.test.d.ts.map +1 -0
  124. package/dist/types/src/core/capability.d.ts +150 -0
  125. package/dist/types/src/core/capability.d.ts.map +1 -0
  126. package/dist/types/src/core/index.d.ts +5 -4
  127. package/dist/types/src/core/index.d.ts.map +1 -1
  128. package/dist/types/src/core/plugin-manager.d.ts +66 -0
  129. package/dist/types/src/core/plugin-manager.d.ts.map +1 -0
  130. package/dist/types/src/core/plugin-manager.test.d.ts +2 -0
  131. package/dist/types/src/core/plugin-manager.test.d.ts.map +1 -0
  132. package/dist/types/src/core/plugin.d.ts +97 -32
  133. package/dist/types/src/core/plugin.d.ts.map +1 -1
  134. package/dist/types/src/index.d.ts +5 -4
  135. package/dist/types/src/index.d.ts.map +1 -1
  136. package/dist/types/src/playground/debug/Debug.d.ts +4 -2
  137. package/dist/types/src/playground/debug/Debug.d.ts.map +1 -1
  138. package/dist/types/src/playground/debug/plugin.d.ts +2 -1
  139. package/dist/types/src/playground/debug/plugin.d.ts.map +1 -1
  140. package/dist/types/src/playground/generator/Main.d.ts +4 -2
  141. package/dist/types/src/playground/generator/Main.d.ts.map +1 -1
  142. package/dist/types/src/playground/generator/Toolbar.d.ts +4 -2
  143. package/dist/types/src/playground/generator/Toolbar.d.ts.map +1 -1
  144. package/dist/types/src/playground/generator/generator.d.ts +17 -5
  145. package/dist/types/src/playground/generator/generator.d.ts.map +1 -1
  146. package/dist/types/src/playground/generator/plugin.d.ts +2 -1
  147. package/dist/types/src/playground/generator/plugin.d.ts.map +1 -1
  148. package/dist/types/src/playground/layout/Layout.d.ts +4 -2
  149. package/dist/types/src/playground/layout/Layout.d.ts.map +1 -1
  150. package/dist/types/src/playground/layout/plugin.d.ts +2 -1
  151. package/dist/types/src/playground/layout/plugin.d.ts.map +1 -1
  152. package/dist/types/src/playground/logger/Toolbar.d.ts +4 -2
  153. package/dist/types/src/playground/logger/Toolbar.d.ts.map +1 -1
  154. package/dist/types/src/playground/logger/plugin.d.ts +2 -1
  155. package/dist/types/src/playground/logger/plugin.d.ts.map +1 -1
  156. package/dist/types/src/playground/logger/schema.d.ts +15 -1
  157. package/dist/types/src/playground/logger/schema.d.ts.map +1 -1
  158. package/dist/types/src/playground/playground.stories.d.ts +5 -4
  159. package/dist/types/src/playground/playground.stories.d.ts.map +1 -1
  160. package/dist/types/src/plugin-operation/OperationPlugin.d.ts +3 -0
  161. package/dist/types/src/plugin-operation/OperationPlugin.d.ts.map +1 -0
  162. package/dist/types/src/plugin-operation/history/capability.d.ts +7 -0
  163. package/dist/types/src/plugin-operation/history/capability.d.ts.map +1 -0
  164. package/dist/types/src/plugin-operation/history/errors.d.ts +5 -0
  165. package/dist/types/src/plugin-operation/history/errors.d.ts.map +1 -0
  166. package/dist/types/src/plugin-operation/history/history-tracker.d.ts +18 -0
  167. package/dist/types/src/plugin-operation/history/history-tracker.d.ts.map +1 -0
  168. package/dist/types/src/plugin-operation/history/history-tracker.test.d.ts +2 -0
  169. package/dist/types/src/plugin-operation/history/history-tracker.test.d.ts.map +1 -0
  170. package/dist/types/src/plugin-operation/history/index.d.ts +6 -0
  171. package/dist/types/src/plugin-operation/history/index.d.ts.map +1 -0
  172. package/dist/types/src/plugin-operation/history/types.d.ts +13 -0
  173. package/dist/types/src/plugin-operation/history/types.d.ts.map +1 -0
  174. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts +93 -0
  175. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts.map +1 -0
  176. package/dist/types/src/plugin-operation/history/undo-registry.d.ts +23 -0
  177. package/dist/types/src/plugin-operation/history/undo-registry.d.ts.map +1 -0
  178. package/dist/types/src/plugin-operation/history/undo-registry.test.d.ts +2 -0
  179. package/dist/types/src/plugin-operation/history/undo-registry.test.d.ts.map +1 -0
  180. package/dist/types/src/plugin-operation/index.d.ts +3 -0
  181. package/dist/types/src/plugin-operation/index.d.ts.map +1 -0
  182. package/dist/types/src/plugin-operation/invoker-capability.d.ts +6 -0
  183. package/dist/types/src/plugin-operation/invoker-capability.d.ts.map +1 -0
  184. package/dist/types/src/plugin-operation/meta.d.ts +3 -0
  185. package/dist/types/src/plugin-operation/meta.d.ts.map +1 -0
  186. package/dist/types/src/plugin-operation/testing.d.ts +109 -0
  187. package/dist/types/src/plugin-operation/testing.d.ts.map +1 -0
  188. package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts +3 -0
  189. package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts.map +1 -0
  190. package/dist/types/src/plugin-runtime/capability.d.ts +6 -0
  191. package/dist/types/src/plugin-runtime/capability.d.ts.map +1 -0
  192. package/dist/types/src/plugin-runtime/index.d.ts +2 -0
  193. package/dist/types/src/plugin-runtime/index.d.ts.map +1 -0
  194. package/dist/types/src/plugin-runtime/meta.d.ts +3 -0
  195. package/dist/types/src/plugin-runtime/meta.d.ts.map +1 -0
  196. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +2 -1
  197. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +1 -1
  198. package/dist/types/src/plugin-settings/actions.d.ts +41 -7
  199. package/dist/types/src/plugin-settings/actions.d.ts.map +1 -1
  200. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +4 -2
  201. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +1 -1
  202. package/dist/types/src/plugin-settings/meta.d.ts +3 -0
  203. package/dist/types/src/plugin-settings/meta.d.ts.map +1 -0
  204. package/dist/types/src/plugin-settings/operation-resolver.d.ts +6 -0
  205. package/dist/types/src/plugin-settings/operation-resolver.d.ts.map +1 -0
  206. package/dist/types/src/plugin-settings/translations.d.ts +2 -1
  207. package/dist/types/src/plugin-settings/translations.d.ts.map +1 -1
  208. package/dist/types/src/react/App.d.ts +8 -0
  209. package/dist/types/src/react/App.d.ts.map +1 -0
  210. package/dist/types/src/react/App.stories.d.ts +14 -0
  211. package/dist/types/src/react/App.stories.d.ts.map +1 -0
  212. package/dist/types/src/react/DefaultFallback.d.ts +8 -0
  213. package/dist/types/src/react/DefaultFallback.d.ts.map +1 -0
  214. package/dist/types/src/react/ErrorBoundary.d.ts +13 -14
  215. package/dist/types/src/react/ErrorBoundary.d.ts.map +1 -1
  216. package/dist/types/src/react/PluginManagerContext.stories.d.ts +13 -0
  217. package/dist/types/src/react/PluginManagerContext.stories.d.ts.map +1 -0
  218. package/dist/types/src/react/PluginManagerProvider.d.ts +2 -2
  219. package/dist/types/src/react/PluginManagerProvider.d.ts.map +1 -1
  220. package/dist/types/src/react/Surface.d.ts +9 -7
  221. package/dist/types/src/react/Surface.d.ts.map +1 -1
  222. package/dist/types/src/react/Surface.stories.d.ts +8 -10
  223. package/dist/types/src/react/Surface.stories.d.ts.map +1 -1
  224. package/dist/types/src/react/SurfaceInfo.d.ts +11 -0
  225. package/dist/types/src/react/SurfaceInfo.d.ts.map +1 -0
  226. package/dist/types/src/react/common.d.ts +13 -12
  227. package/dist/types/src/react/common.d.ts.map +1 -1
  228. package/dist/types/src/react/index.d.ts +3 -1
  229. package/dist/types/src/react/index.d.ts.map +1 -1
  230. package/dist/types/src/react/types.d.ts +12 -0
  231. package/dist/types/src/react/types.d.ts.map +1 -0
  232. package/dist/types/src/{App.d.ts → react/useApp.d.ts} +11 -9
  233. package/dist/types/src/react/useApp.d.ts.map +1 -0
  234. package/dist/types/src/react/useCapabilities.d.ts +16 -3
  235. package/dist/types/src/react/useCapabilities.d.ts.map +1 -1
  236. package/dist/types/src/react/useLoading.d.ts +18 -0
  237. package/dist/types/src/react/useLoading.d.ts.map +1 -0
  238. package/dist/types/src/react/useOperationResolver.d.ts +19 -0
  239. package/dist/types/src/react/useOperationResolver.d.ts.map +1 -0
  240. package/dist/types/src/testing/index.d.ts +1 -0
  241. package/dist/types/src/testing/index.d.ts.map +1 -1
  242. package/dist/types/src/testing/service.d.ts +8 -0
  243. package/dist/types/src/testing/service.d.ts.map +1 -0
  244. package/dist/types/src/testing/withPluginManager.d.ts +11 -10
  245. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  246. package/dist/types/src/testing/withPluginManager.stories.d.ts +9 -3
  247. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  248. package/dist/types/tsconfig.tsbuildinfo +1 -1
  249. package/moon.yml +10 -2
  250. package/package.json +103 -42
  251. package/src/cli.ts +107 -0
  252. package/src/common/activation-event.ts +99 -0
  253. package/src/common/capability.ts +343 -0
  254. package/src/common/collaboration.ts +24 -14
  255. package/src/common/file.ts +1 -1
  256. package/src/common/graph.ts +2 -2
  257. package/src/common/index.ts +5 -4
  258. package/src/common/operations.ts +412 -0
  259. package/src/common/plugin.ts +364 -0
  260. package/src/common/surface.ts +60 -26
  261. package/src/common/translations.ts +21 -1
  262. package/src/context.ts +9 -0
  263. package/src/core/{events.ts → activation-event.ts} +5 -5
  264. package/src/core/capability-manager.test.ts +151 -0
  265. package/src/core/capability-manager.ts +171 -0
  266. package/src/core/capability.ts +236 -0
  267. package/src/core/index.ts +5 -4
  268. package/src/core/plugin-manager.test.ts +845 -0
  269. package/src/core/plugin-manager.ts +696 -0
  270. package/src/core/plugin.ts +229 -36
  271. package/src/helpers.test.ts +1 -1
  272. package/src/index.ts +5 -4
  273. package/src/playground/debug/Debug.tsx +27 -17
  274. package/src/playground/debug/plugin.ts +10 -11
  275. package/src/playground/generator/Main.tsx +20 -11
  276. package/src/playground/generator/Toolbar.tsx +27 -16
  277. package/src/playground/generator/generator.ts +28 -28
  278. package/src/playground/generator/plugin.ts +15 -17
  279. package/src/playground/layout/Layout.tsx +11 -7
  280. package/src/playground/layout/plugin.ts +12 -11
  281. package/src/playground/logger/Toolbar.tsx +20 -16
  282. package/src/playground/logger/plugin.ts +33 -27
  283. package/src/playground/logger/schema.ts +11 -1
  284. package/src/playground/playground.stories.tsx +29 -17
  285. package/src/plugin-operation/OperationPlugin.ts +25 -0
  286. package/src/plugin-operation/history/capability.ts +37 -0
  287. package/src/plugin-operation/history/errors.ts +11 -0
  288. package/src/plugin-operation/history/history-tracker.test.ts +380 -0
  289. package/src/plugin-operation/history/history-tracker.ts +129 -0
  290. package/src/plugin-operation/history/index.ts +9 -0
  291. package/src/plugin-operation/history/types.ts +17 -0
  292. package/src/plugin-operation/history/undo-mapping.ts +132 -0
  293. package/src/plugin-operation/history/undo-registry.test.ts +73 -0
  294. package/src/plugin-operation/history/undo-registry.ts +54 -0
  295. package/src/plugin-operation/index.ts +6 -0
  296. package/src/plugin-operation/invoker-capability.ts +40 -0
  297. package/src/plugin-operation/meta.ts +11 -0
  298. package/src/plugin-operation/testing.ts +174 -0
  299. package/src/plugin-runtime/RuntimePlugin.ts +20 -0
  300. package/src/plugin-runtime/capability.ts +53 -0
  301. package/src/plugin-runtime/index.ts +5 -0
  302. package/src/plugin-runtime/meta.ts +11 -0
  303. package/src/plugin-settings/SettingsPlugin.ts +13 -29
  304. package/src/plugin-settings/actions.ts +45 -10
  305. package/src/plugin-settings/app-graph-builder.ts +124 -141
  306. package/src/plugin-settings/meta.ts +10 -0
  307. package/src/plugin-settings/operation-resolver.ts +55 -0
  308. package/src/plugin-settings/translations.ts +4 -4
  309. package/src/react/App.stories.tsx +63 -0
  310. package/src/react/App.tsx +60 -0
  311. package/src/react/DefaultFallback.tsx +26 -0
  312. package/src/react/ErrorBoundary.tsx +26 -15
  313. package/src/react/PluginManagerContext.stories.tsx +184 -0
  314. package/src/react/PluginManagerProvider.ts +2 -2
  315. package/src/react/Surface.stories.tsx +103 -58
  316. package/src/react/Surface.tsx +236 -46
  317. package/src/react/SurfaceInfo.tsx +107 -0
  318. package/src/react/common.ts +30 -5
  319. package/src/react/index.ts +5 -1
  320. package/src/react/types.ts +27 -0
  321. package/src/react/useApp.tsx +209 -0
  322. package/src/react/useCapabilities.ts +38 -5
  323. package/src/react/useLoading.tsx +68 -0
  324. package/src/react/useOperationResolver.ts +40 -0
  325. package/src/testing/index.ts +1 -0
  326. package/src/testing/service.ts +52 -0
  327. package/src/testing/withPluginManager.stories.tsx +14 -10
  328. package/src/testing/withPluginManager.tsx +43 -44
  329. package/tsconfig.json +27 -16
  330. package/vitest.config.ts +8 -6
  331. package/.swc/plugins/v7_linux_x86_64_13.0.0/f45bdff002284d9e8f9ef3f0be909de12da36c049cbcf261ac78fc00abb09a2d +0 -0
  332. package/.swc/plugins/v7_linux_x86_64_13.0.0/fce1bdb8e20a094e4af08bad09cc81497ed0e2e7c51223b07d371063cca18429 +0 -0
  333. package/dist/lib/browser/app-graph-builder-LYF7EKNN.mjs +0 -137
  334. package/dist/lib/browser/app-graph-builder-LYF7EKNN.mjs.map +0 -7
  335. package/dist/lib/browser/chunk-FMN65HSW.mjs +0 -1519
  336. package/dist/lib/browser/chunk-FMN65HSW.mjs.map +0 -7
  337. package/dist/lib/browser/chunk-FO2PH7M3.mjs +0 -415
  338. package/dist/lib/browser/chunk-FO2PH7M3.mjs.map +0 -7
  339. package/dist/lib/browser/chunk-ORWHM7CO.mjs +0 -32
  340. package/dist/lib/browser/chunk-ORWHM7CO.mjs.map +0 -7
  341. package/dist/lib/browser/intent-dispatcher-LSYQZSEB.mjs +0 -11
  342. package/dist/lib/browser/intent-resolver-ZTNOSO3A.mjs +0 -39
  343. package/dist/lib/browser/intent-resolver-ZTNOSO3A.mjs.map +0 -7
  344. package/dist/lib/browser/store-KML2R4IE.mjs +0 -30
  345. package/dist/lib/browser/store-KML2R4IE.mjs.map +0 -7
  346. package/dist/lib/browser/worker.mjs +0 -79
  347. package/dist/lib/node-esm/app-graph-builder-SAOWGJDK.mjs +0 -138
  348. package/dist/lib/node-esm/app-graph-builder-SAOWGJDK.mjs.map +0 -7
  349. package/dist/lib/node-esm/chunk-73HGSHKE.mjs +0 -416
  350. package/dist/lib/node-esm/chunk-73HGSHKE.mjs.map +0 -7
  351. package/dist/lib/node-esm/chunk-UMZQERLE.mjs +0 -34
  352. package/dist/lib/node-esm/chunk-UMZQERLE.mjs.map +0 -7
  353. package/dist/lib/node-esm/chunk-ZEZ4FVEU.mjs +0 -1521
  354. package/dist/lib/node-esm/chunk-ZEZ4FVEU.mjs.map +0 -7
  355. package/dist/lib/node-esm/intent-dispatcher-6CYNGPSW.mjs +0 -12
  356. package/dist/lib/node-esm/intent-resolver-W7Z7WFFM.mjs +0 -40
  357. package/dist/lib/node-esm/intent-resolver-W7Z7WFFM.mjs.map +0 -7
  358. package/dist/lib/node-esm/store-QEXGXLWZ.mjs +0 -31
  359. package/dist/lib/node-esm/store-QEXGXLWZ.mjs.map +0 -7
  360. package/dist/lib/node-esm/worker.mjs +0 -80
  361. package/dist/types/src/App.d.ts.map +0 -1
  362. package/dist/types/src/common/capabilities.d.ts +0 -124
  363. package/dist/types/src/common/capabilities.d.ts.map +0 -1
  364. package/dist/types/src/common/events.d.ts +0 -52
  365. package/dist/types/src/common/events.d.ts.map +0 -1
  366. package/dist/types/src/common/layout.d.ts +0 -281
  367. package/dist/types/src/common/layout.d.ts.map +0 -1
  368. package/dist/types/src/core/capabilities.d.ts +0 -114
  369. package/dist/types/src/core/capabilities.d.ts.map +0 -1
  370. package/dist/types/src/core/capabilities.test.d.ts +0 -2
  371. package/dist/types/src/core/capabilities.test.d.ts.map +0 -1
  372. package/dist/types/src/core/events.d.ts.map +0 -1
  373. package/dist/types/src/core/manager.d.ts +0 -122
  374. package/dist/types/src/core/manager.d.ts.map +0 -1
  375. package/dist/types/src/core/manager.test.d.ts +0 -2
  376. package/dist/types/src/core/manager.test.d.ts.map +0 -1
  377. package/dist/types/src/plugin-intent/IntentPlugin.d.ts +0 -2
  378. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +0 -1
  379. package/dist/types/src/plugin-intent/actions.d.ts +0 -38
  380. package/dist/types/src/plugin-intent/actions.d.ts.map +0 -1
  381. package/dist/types/src/plugin-intent/errors.d.ts +0 -16
  382. package/dist/types/src/plugin-intent/errors.d.ts.map +0 -1
  383. package/dist/types/src/plugin-intent/index.d.ts +0 -5
  384. package/dist/types/src/plugin-intent/index.d.ts.map +0 -1
  385. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +0 -139
  386. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +0 -1
  387. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts +0 -2
  388. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts.map +0 -1
  389. package/dist/types/src/plugin-intent/intent.d.ts +0 -63
  390. package/dist/types/src/plugin-intent/intent.d.ts.map +0 -1
  391. package/dist/types/src/plugin-settings/intent-resolver.d.ts +0 -4
  392. package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +0 -1
  393. package/dist/types/src/plugin-settings/store.d.ts +0 -5
  394. package/dist/types/src/plugin-settings/store.d.ts.map +0 -1
  395. package/dist/types/src/react/IntentContext.d.ts +0 -8
  396. package/dist/types/src/react/IntentContext.d.ts.map +0 -1
  397. package/dist/types/src/react/useIntentResolver.d.ts +0 -3
  398. package/dist/types/src/react/useIntentResolver.d.ts.map +0 -1
  399. package/dist/types/src/worker.d.ts +0 -4
  400. package/dist/types/src/worker.d.ts.map +0 -1
  401. package/src/App.tsx +0 -276
  402. package/src/common/capabilities.ts +0 -118
  403. package/src/common/events.ts +0 -77
  404. package/src/common/layout.ts +0 -278
  405. package/src/core/capabilities.test.ts +0 -136
  406. package/src/core/capabilities.ts +0 -254
  407. package/src/core/manager.test.ts +0 -515
  408. package/src/core/manager.ts +0 -519
  409. package/src/plugin-intent/IntentPlugin.ts +0 -20
  410. package/src/plugin-intent/actions.ts +0 -33
  411. package/src/plugin-intent/errors.ts +0 -39
  412. package/src/plugin-intent/index.ts +0 -8
  413. package/src/plugin-intent/intent-dispatcher.test.ts +0 -279
  414. package/src/plugin-intent/intent-dispatcher.ts +0 -333
  415. package/src/plugin-intent/intent.ts +0 -154
  416. package/src/plugin-settings/intent-resolver.ts +0 -34
  417. package/src/plugin-settings/store.ts +0 -33
  418. package/src/react/IntentContext.tsx +0 -34
  419. package/src/react/useIntentResolver.ts +0 -22
  420. package/src/worker.ts +0 -11
  421. /package/dist/lib/browser/{intent-dispatcher-LSYQZSEB.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  422. /package/dist/lib/browser/{worker.mjs.map → common/index.mjs.map} +0 -0
  423. /package/dist/lib/{node-esm/intent-dispatcher-6CYNGPSW.mjs.map → browser/core/activation-event.mjs.map} +0 -0
  424. /package/dist/lib/{node-esm/worker.mjs.map → browser/core/capability.mjs.map} +0 -0
@@ -0,0 +1,209 @@
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 { runAndForwardErrors } from '@dxos/effect';
13
+ import { invariant } from '@dxos/invariant';
14
+ import { log } from '@dxos/log';
15
+ import { useAsyncEffect, useDefaultValue } from '@dxos/react-hooks';
16
+ import { ContextProtocolProvider } from '@dxos/web-context-react';
17
+
18
+ import * as Common from '../common';
19
+ import { PluginManagerContext } from '../context';
20
+ import { type Plugin, PluginManager } from '../core';
21
+
22
+ import { App } from './App';
23
+ import { DefaultFallback } from './DefaultFallback';
24
+ import { ErrorBoundary } from './ErrorBoundary';
25
+ import { PluginManagerProvider } from './PluginManagerProvider';
26
+
27
+ const ENABLED_KEY = 'dxos.org/app-framework/enabled';
28
+
29
+ export type UseAppOptions = {
30
+ pluginManager?: PluginManager.PluginManager;
31
+ pluginLoader?: PluginManager.ManagerOptions['pluginLoader'];
32
+ plugins?: Plugin.Plugin[];
33
+ core?: string[];
34
+ defaults?: string[];
35
+ placeholder?: FC<{ stage: number }>;
36
+ fallback?: ErrorBoundary['props']['fallback'];
37
+ cacheEnabled?: boolean;
38
+ safeMode?: boolean;
39
+ debounce?: number;
40
+ timeout?: number;
41
+ };
42
+
43
+ /**
44
+ * Expected usage is for this to be the entrypoint of the application.
45
+ * Initializes plugins and renders the root components.
46
+ *
47
+ * @example
48
+ * const plugins = [LayoutPlugin(), MyPlugin()];
49
+ * const core = [LayoutPluginId];
50
+ * const default = [MyPluginId];
51
+ * const fallback = <div>Initializing Plugins...</div>;
52
+ * const App = useApp({ plugins, core, default, fallback });
53
+ * createRoot(document.getElementById('root')!).render(
54
+ * <StrictMode>
55
+ * <App />
56
+ * </StrictMode>,
57
+ * );
58
+ *
59
+ * @param params.pluginLoader A function which loads new plugins.
60
+ * @param params.plugins All plugins available to the application.
61
+ * @param params.core Core plugins which will always be enabled.
62
+ * @param params.defaults Default plugins are enabled by default but can be disabled by the user.
63
+ * @param params.placeholder Placeholder component to render during startup.
64
+ * @param params.fallback Fallback component to render if an error occurs during startup.
65
+ * @param params.cacheEnabled Whether to cache enabled plugins in localStorage.
66
+ * @param params.safeMode Whether to enable safe mode, which disables optional plugins.
67
+ */
68
+ export const useApp = ({
69
+ pluginManager,
70
+ pluginLoader: pluginLoaderProp,
71
+ plugins: pluginsProp,
72
+ core: coreProp,
73
+ defaults: defaultsProp,
74
+ placeholder,
75
+ fallback = DefaultFallback,
76
+ cacheEnabled = false,
77
+ safeMode = false,
78
+ debounce = 0,
79
+ timeout = 30_000,
80
+ }: UseAppOptions) => {
81
+ const plugins = useDefaultValue(pluginsProp, () => []);
82
+ const core = useDefaultValue(coreProp, () => plugins.map(({ meta }) => meta.id));
83
+ const defaults = useDefaultValue(defaultsProp, () => []);
84
+
85
+ // TODO(wittjosiah): Provide a custom plugin loader which supports loading via url.
86
+ const pluginLoader = useMemo(
87
+ () =>
88
+ pluginLoaderProp ??
89
+ ((id: string) =>
90
+ Effect.sync(() => {
91
+ const plugin = plugins.find((plugin) => plugin.meta.id === id);
92
+ invariant(plugin, `Plugin not found: ${id}`);
93
+ return plugin;
94
+ })),
95
+ [pluginLoaderProp, plugins],
96
+ );
97
+
98
+ const readyRef = useRef(false);
99
+ const [ready, setReady] = useState(false);
100
+ const errorRef = useRef<unknown>(null);
101
+ const [error, setError] = useState<unknown>(null);
102
+ // TODO(wittjosiah): Migrate to Atom.kvs for isomorphic storage.
103
+ const cached: string[] = useMemo(() => JSON.parse(localStorage.getItem(ENABLED_KEY) ?? '[]'), []);
104
+ const enabled = useMemo(
105
+ () => (safeMode ? [] : cacheEnabled && cached.length > 0 ? cached : defaults),
106
+ [safeMode, cacheEnabled, cached, defaults],
107
+ );
108
+ const manager = useMemo(
109
+ () => pluginManager ?? PluginManager.make({ pluginLoader, plugins, core, enabled }),
110
+ [pluginManager, pluginLoader, plugins, core, enabled],
111
+ );
112
+
113
+ useEffect(() => {
114
+ if (!cacheEnabled) {
115
+ return;
116
+ }
117
+ return manager.registry.subscribe(manager.enabled, (value) => {
118
+ localStorage.setItem(ENABLED_KEY, JSON.stringify(value));
119
+ });
120
+ }, [cacheEnabled, manager]);
121
+
122
+ useEffect(() => {
123
+ setupDevtools(manager);
124
+ }, [manager]);
125
+
126
+ useAsyncEffect(async () => {
127
+ manager.capabilities.contribute({
128
+ interface: Common.Capability.PluginManager,
129
+ implementation: manager,
130
+ module: 'dxos.org/app-framework/plugin-manager',
131
+ });
132
+
133
+ manager.capabilities.contribute({
134
+ interface: Common.Capability.AtomRegistry,
135
+ implementation: manager.registry,
136
+ module: 'dxos.org/app-framework/atom-registry',
137
+ });
138
+
139
+ const fiber = Effect.gen(function* () {
140
+ const queue = yield* PubSub.subscribe(manager.activation);
141
+ const listener = yield* Effect.forkDaemon(
142
+ Queue.take(queue).pipe(
143
+ Effect.tap(({ event, state, error: error$ }) =>
144
+ Effect.sync(() => {
145
+ if (event === Common.ActivationEvent.Startup.id && state === 'activated') {
146
+ clearTimeout(timeoutId);
147
+ setReady(true);
148
+ readyRef.current = true;
149
+ }
150
+ if (error$ && !readyRef.current) {
151
+ setError(error$);
152
+ errorRef.current = error$;
153
+ }
154
+ }),
155
+ ),
156
+ Effect.forever,
157
+ ),
158
+ );
159
+
160
+ yield* Effect.all([
161
+ manager.activate(Common.ActivationEvent.SetupSettings),
162
+ manager.activate(Common.ActivationEvent.SetupReactSurface),
163
+ manager.activate(Common.ActivationEvent.Startup),
164
+ ]);
165
+
166
+ return yield* Fiber.join(listener);
167
+ }).pipe(Effect.scoped, Effect.runFork);
168
+
169
+ // Set up a timeout for startup.
170
+ const timeoutId = setTimeout(() => {
171
+ if (!readyRef.current && !errorRef.current) {
172
+ log.warn('startup timeout diagnostic', {
173
+ eventsFired: manager.getEventsFired(),
174
+ activeModules: manager.getActive(),
175
+ pendingReset: manager.getPendingReset(),
176
+ });
177
+ void runAndForwardErrors(Fiber.interrupt(fiber));
178
+ setError(new Error(`Startup timed out after ${timeout}ms`));
179
+ }
180
+ }, timeout);
181
+
182
+ return () => {
183
+ clearTimeout(timeoutId);
184
+ void runAndForwardErrors(Fiber.interrupt(fiber));
185
+ manager.capabilities.remove(Common.Capability.PluginManager, manager);
186
+ manager.capabilities.remove(Common.Capability.AtomRegistry, manager.registry);
187
+ };
188
+ }, [manager]);
189
+
190
+ return useCallback(
191
+ () => (
192
+ <ErrorBoundary fallback={fallback}>
193
+ <PluginManagerProvider value={manager}>
194
+ <ContextProtocolProvider value={manager} context={PluginManagerContext}>
195
+ <RegistryContext.Provider value={manager.registry}>
196
+ <App placeholder={placeholder} ready={ready} error={error} debounce={debounce} />
197
+ </RegistryContext.Provider>
198
+ </ContextProtocolProvider>
199
+ </PluginManagerProvider>
200
+ </ErrorBoundary>
201
+ ),
202
+ [fallback, manager, placeholder, ready, error],
203
+ );
204
+ };
205
+
206
+ const setupDevtools = (manager: PluginManager.PluginManager) => {
207
+ (globalThis as any).composer ??= {};
208
+ (globalThis as any).composer.manager = manager;
209
+ };
@@ -2,20 +2,23 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { useRxValue } from '@effect-rx/rx-react';
5
+ import { type Atom, useAtomValue } from '@effect-atom/atom-react';
6
+ import { useCallback } from 'react';
6
7
 
7
8
  import { invariant } from '@dxos/invariant';
8
9
 
10
+ import * as Common from '../common';
11
+ import { type Capability } from '../core';
12
+
9
13
  import { usePluginManager } from './PluginManagerProvider';
10
- import { type InterfaceDef } from '../core';
11
14
 
12
15
  /**
13
16
  * Hook to request capabilities from the plugin context.
14
17
  * @returns An array of capabilities.
15
18
  */
16
- export const useCapabilities = <T>(interfaceDef: InterfaceDef<T>) => {
19
+ export const useCapabilities = <T>(interfaceDef: Capability.InterfaceDef<T>) => {
17
20
  const manager = usePluginManager();
18
- return useRxValue(manager.context.capabilities(interfaceDef));
21
+ return useAtomValue(manager.capabilities.atom(interfaceDef));
19
22
  };
20
23
 
21
24
  /**
@@ -23,8 +26,38 @@ export const useCapabilities = <T>(interfaceDef: InterfaceDef<T>) => {
23
26
  * @returns The capability.
24
27
  * @throws If no capability is found.
25
28
  */
26
- export const useCapability = <T>(interfaceDef: InterfaceDef<T>) => {
29
+ export const useCapability = <T>(interfaceDef: Capability.InterfaceDef<T>) => {
27
30
  const capabilities = useCapabilities(interfaceDef);
28
31
  invariant(capabilities.length > 0, `No capability found for ${interfaceDef.identifier}`);
29
32
  return capabilities[0];
30
33
  };
34
+
35
+ /**
36
+ * Hook to get the current value of an atom capability.
37
+ * Automatically subscribes to changes.
38
+ * @example const settings = useAtomCapability(ThreadCapabilities.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(ThreadCapabilities.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(Common.Capability.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
+ };
@@ -0,0 +1,68 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useEffect, useState } from 'react';
6
+
7
+ export enum LoadingState {
8
+ Loading = 0,
9
+ FadeIn = 1,
10
+ FadeOut = 2,
11
+ Done = 3,
12
+ }
13
+
14
+ /**
15
+ * To avoid "flashing" the placeholder, we wait a period of time before starting the loading animation.
16
+ * If loading completes during this time the placehoder is not shown, otherwise is it displayed for a minimum period of time.
17
+ *
18
+ * States:
19
+ * 0: Loading - Wait for a period of time before starting the loading animation.
20
+ * 1: Fade-in - Display a loading animation.
21
+ * 2: Fade-out - Fade out the loading animation.
22
+ * 3: Done - Remove the placeholder.
23
+ */
24
+ export const useLoading = (ready: boolean, debounce = 0) => {
25
+ const [stage, setStage] = useState<LoadingState>(LoadingState.Loading);
26
+ useEffect(() => {
27
+ if (!debounce) {
28
+ return;
29
+ }
30
+
31
+ const i = setInterval(() => {
32
+ setStage((stage) => {
33
+ switch (stage) {
34
+ case LoadingState.Loading: {
35
+ if (!ready) {
36
+ return LoadingState.FadeIn;
37
+ } else {
38
+ clearInterval(i);
39
+ return LoadingState.Done;
40
+ }
41
+ }
42
+
43
+ case LoadingState.FadeIn: {
44
+ if (ready) {
45
+ return LoadingState.FadeOut;
46
+ }
47
+ break;
48
+ }
49
+
50
+ case LoadingState.FadeOut: {
51
+ clearInterval(i);
52
+ return LoadingState.Done;
53
+ }
54
+ }
55
+
56
+ return stage;
57
+ });
58
+ }, debounce);
59
+
60
+ return () => clearInterval(i);
61
+ }, [debounce]);
62
+
63
+ if (!debounce) {
64
+ return ready ? LoadingState.Done : LoadingState.Loading;
65
+ }
66
+
67
+ return stage;
68
+ };
@@ -0,0 +1,40 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useEffect, useMemo } from 'react';
6
+
7
+ import * as Common from '../common';
8
+ import { usePluginManager } from '../react';
9
+
10
+ /**
11
+ * Hook to dynamically register an operation resolver (handler) within a React component.
12
+ * The resolver is added when the component mounts and removed when it unmounts.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * const scrollHandler = useMemo(() => OperationResolver.make({
17
+ * operation: LayoutOperation.ScrollIntoView,
18
+ * handler: (input) => Effect.sync(() => {
19
+ * // Handle scroll
20
+ * }),
21
+ * }), [deps]);
22
+ *
23
+ * useOperationResolver(meta.id, scrollHandler);
24
+ * ```
25
+ */
26
+ export const useOperationResolver = (module: string, resolver: Common.Capability.OperationResolver) => {
27
+ const manager = usePluginManager();
28
+ // Wrap single resolver in array as the capability expects an array.
29
+ const resolverArray = useMemo(() => [resolver], [resolver]);
30
+
31
+ useEffect(() => {
32
+ manager.capabilities.contribute({
33
+ module,
34
+ interface: Common.Capability.OperationResolver,
35
+ implementation: resolverArray,
36
+ });
37
+
38
+ return () => manager.capabilities.remove(Common.Capability.OperationResolver, resolverArray);
39
+ }, [module, resolverArray]);
40
+ };
@@ -2,4 +2,5 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ export * from './service';
5
6
  export * from './withPluginManager';
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Layer from 'effect/Layer';
7
+
8
+ import { invariant } from '@dxos/invariant';
9
+
10
+ import * as Common from '../common';
11
+ import { Plugin, PluginManager } from '../core';
12
+
13
+ /**
14
+ * Creates a Plugin.Service layer from a list of plugins.
15
+ * This is primarily used for testing.
16
+ */
17
+ export const fromPlugins = (plugins: Plugin.Plugin[]) =>
18
+ Layer.effect(
19
+ Plugin.Service,
20
+ Effect.gen(function* () {
21
+ // TODO(wittjosiah): Try to dedupe logic between here, createCliApp and useApp.
22
+
23
+ const pluginLoader = (id: string) =>
24
+ Effect.sync(() => {
25
+ const plugin = plugins.find((plugin) => plugin.meta.id === id);
26
+ invariant(plugin, `Plugin not found: ${id}`);
27
+ return plugin;
28
+ });
29
+
30
+ const manager = PluginManager.make({
31
+ pluginLoader,
32
+ plugins,
33
+ core: plugins.map((plugin) => plugin.meta.id),
34
+ });
35
+
36
+ manager.capabilities.contribute({
37
+ interface: Common.Capability.PluginManager,
38
+ implementation: manager,
39
+ module: 'dxos.org/app-framework/plugin-manager',
40
+ });
41
+
42
+ manager.capabilities.contribute({
43
+ interface: Common.Capability.AtomRegistry,
44
+ implementation: manager.registry,
45
+ module: 'dxos.org/app-framework/atom-registry',
46
+ });
47
+
48
+ yield* manager.activate(Common.ActivationEvent.Startup);
49
+
50
+ return manager;
51
+ }),
52
+ );
@@ -2,15 +2,17 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
5
6
  import React from 'react';
6
7
 
7
- import { withTheme, type Meta } from '@dxos/storybook-utils';
8
+ import { withTheme } from '@dxos/react-ui/testing';
8
9
 
9
- import { withPluginManager } from './withPluginManager';
10
- import { Capabilities, createSurface } from '../common';
11
- import { contributes } from '../core';
10
+ import * as Common from '../common';
11
+ import { Capability } from '../core';
12
12
  import { Surface } from '../react';
13
13
 
14
+ import { withPluginManager } from './withPluginManager';
15
+
14
16
  const DefaultStory = () => {
15
17
  console.log('Render');
16
18
  return (
@@ -21,16 +23,16 @@ const DefaultStory = () => {
21
23
  );
22
24
  };
23
25
 
24
- const meta: Meta = {
26
+ const meta = {
25
27
  title: 'sdk/app-framework/withPluginManager',
26
28
  render: DefaultStory,
27
29
  decorators: [
28
30
  withTheme,
29
31
  withPluginManager({
30
32
  capabilities: [
31
- contributes(
32
- Capabilities.ReactSurface,
33
- createSurface({
33
+ Capability.contributes(
34
+ Common.Capability.ReactSurface,
35
+ Common.createSurface({
34
36
  id: 'test',
35
37
  role: 'main',
36
38
  component: ({ role }) => <span>{JSON.stringify({ role })}</span>,
@@ -39,8 +41,10 @@ const meta: Meta = {
39
41
  ],
40
42
  }),
41
43
  ],
42
- };
44
+ } satisfies Meta<typeof DefaultStory>;
43
45
 
44
46
  export default meta;
45
47
 
46
- export const Default = {};
48
+ type Story = StoryObj<typeof meta>;
49
+
50
+ export const Default: Story = {};
@@ -2,29 +2,17 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Decorator } from '@storybook/react';
5
+ import { type Decorator, type StoryContext } from '@storybook/react';
6
+ import * as Effect from 'effect/Effect';
6
7
  import React, { useEffect, useMemo } from 'react';
7
8
 
8
9
  import { raise } from '@dxos/debug';
10
+ import { useAsyncEffect } from '@dxos/react-hooks';
11
+ import { type MaybeProvider, getProviderValue } from '@dxos/util';
9
12
 
10
- import { useApp, type CreateAppOptions } from '../App';
11
- import { Capabilities, Events } from '../common';
12
- import {
13
- contributes,
14
- defineModule,
15
- definePlugin,
16
- type ActivationEvent,
17
- type AnyCapability,
18
- PluginManager,
19
- type PluginContext,
20
- } from '../core';
21
-
22
- // TODO(burdon): Factor out (use consistently in plugin framework?)
23
- export type Provider<C, R> = (context: C) => R;
24
- export type ProviderOrValue<C, R> = Provider<C, R> | R;
25
- export const getValue = <C, R>(providerOrValue: ProviderOrValue<C, R>, context: C): R => {
26
- return typeof providerOrValue === 'function' ? (providerOrValue as Provider<C, R>)(context) : providerOrValue;
27
- };
13
+ import * as Common from '../common';
14
+ import { type ActivationEvent, Capability, type CapabilityManager, Plugin, PluginManager } from '../core';
15
+ import { type UseAppOptions, useApp } from '../react';
28
16
 
29
17
  /**
30
18
  * @internal
@@ -34,17 +22,17 @@ export const setupPluginManager = ({
34
22
  plugins = [],
35
23
  core = plugins.map(({ meta }) => meta.id),
36
24
  ...options
37
- }: CreateAppOptions & Pick<WithPluginManagerOptions, 'capabilities'> = {}) => {
38
- const pluginManager = new PluginManager({
25
+ }: UseAppOptions & Pick<WithPluginManagerOptions, 'capabilities'> = {}) => {
26
+ const pluginManager = PluginManager.make({
39
27
  pluginLoader: () => raise(new Error('Not implemented')),
40
- plugins: [storyPlugin(), ...plugins],
41
- core: [STORY_PLUGIN, ...core],
28
+ plugins: [StoryPlugin, ...plugins],
29
+ core: [StoryPlugin.meta.id, ...core],
42
30
  ...options,
43
31
  });
44
32
 
45
33
  if (capabilities) {
46
- getValue(capabilities, pluginManager.context).forEach((capability) => {
47
- pluginManager.context.contributeCapability({
34
+ getProviderValue(capabilities, pluginManager.capabilities).forEach((capability) => {
35
+ pluginManager.capabilities.contribute({
48
36
  interface: capability.interface,
49
37
  implementation: capability.implementation,
50
38
  module: 'story',
@@ -55,43 +43,46 @@ export const setupPluginManager = ({
55
43
  return pluginManager;
56
44
  };
57
45
 
58
- export type WithPluginManagerOptions = CreateAppOptions & {
59
- capabilities?: ProviderOrValue<PluginContext, AnyCapability[]>;
60
- fireEvents?: (ActivationEvent | string)[];
46
+ export type WithPluginManagerOptions = UseAppOptions & {
47
+ /** @deprecated */
48
+ capabilities?: MaybeProvider<Capability.Any[], CapabilityManager.CapabilityManager>;
49
+ /** @deprecated */
50
+ fireEvents?: (ActivationEvent.ActivationEvent | string)[];
61
51
  };
62
52
 
53
+ export type WithPluginManagerInitializer<Args = void> =
54
+ | WithPluginManagerOptions
55
+ | ((context: StoryContext<Args>) => WithPluginManagerOptions);
56
+
63
57
  /**
64
58
  * Wraps a story with a plugin manager.
65
59
  * NOTE: This builds up and tears down the plugin manager on every render.
66
60
  */
67
- export const withPluginManager = (options: WithPluginManagerOptions = {}): Decorator => {
61
+ export const withPluginManager = <Args,>(init: WithPluginManagerInitializer<Args> = {}): Decorator => {
68
62
  return (Story, context) => {
69
- const pluginManager = useMemo(() => setupPluginManager(options), [options]);
63
+ const options = typeof init === 'function' ? init(context as any) : init;
64
+ const pluginManager = useMemo(() => setupPluginManager(options), [init]);
70
65
 
71
66
  // Set-up root capability.
72
67
  useEffect(() => {
73
- const capability = contributes(Capabilities.ReactRoot, {
68
+ const capability = Capability.contributes(Common.Capability.ReactRoot, {
74
69
  id: context.id,
75
70
  root: () => <Story />,
76
71
  });
77
72
 
78
- pluginManager.context.contributeCapability({
73
+ pluginManager.capabilities.contribute({
79
74
  ...capability,
80
75
  module: 'dxos.org/app-framework/withPluginManager',
81
76
  });
82
77
 
83
78
  return () => {
84
- pluginManager.context.removeCapability(capability.interface, capability.implementation);
79
+ pluginManager.capabilities.remove(capability.interface, capability.implementation);
85
80
  };
86
81
  }, [pluginManager, context]);
87
82
 
88
83
  // Fire events.
89
- useEffect(() => {
90
- const timeout = setTimeout(async () => {
91
- await Promise.all(options.fireEvents?.map((event) => pluginManager.activate(event)) ?? []);
92
- });
93
-
94
- return () => clearTimeout(timeout);
84
+ useAsyncEffect(async () => {
85
+ await Promise.all(options.fireEvents?.map((event) => pluginManager.activate(event)) ?? []);
95
86
  }, [pluginManager]);
96
87
 
97
88
  // Create app.
@@ -101,10 +92,18 @@ export const withPluginManager = (options: WithPluginManagerOptions = {}): Decor
101
92
  };
102
93
  };
103
94
 
95
+ const storyMeta = {
96
+ id: 'dxos.org/app-framework/story',
97
+ name: 'Story',
98
+ };
99
+
104
100
  // No-op plugin to ensure there exists at least one plugin for the startup event.
105
101
  // This is necessary because `createApp` expects the startup event to complete before the app is ready.
106
- const STORY_PLUGIN = 'dxos.org/app-framework/story';
107
- const storyPlugin = () =>
108
- definePlugin({ id: STORY_PLUGIN, name: 'Story' }, [
109
- defineModule({ id: STORY_PLUGIN, activatesOn: Events.Startup, activate: () => [] }),
110
- ]);
102
+ const StoryPlugin = Plugin.define(storyMeta).pipe(
103
+ Plugin.addModule({
104
+ id: 'Story',
105
+ activatesOn: Common.ActivationEvent.Startup,
106
+ activate: () => Effect.succeed([]),
107
+ }),
108
+ Plugin.make,
109
+ )();