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

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 (421) hide show
  1. package/.storybook/main.mts +1 -3
  2. package/dist/lib/browser/{capability-7PCNSWBT.mjs → capability-4NSF2SOO.mjs} +16 -11
  3. package/dist/lib/browser/capability-4NSF2SOO.mjs.map +7 -0
  4. package/dist/lib/browser/capability-EB3UKSKA.mjs +35 -0
  5. package/dist/lib/browser/capability-EB3UKSKA.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-FMZN33N4.mjs → chunk-27FZETIA.mjs} +324 -181
  7. package/dist/lib/browser/chunk-27FZETIA.mjs.map +7 -0
  8. package/dist/lib/browser/chunk-CV7I2AAB.mjs +80 -0
  9. package/dist/lib/browser/chunk-CV7I2AAB.mjs.map +7 -0
  10. package/dist/lib/browser/{chunk-6Y7PZV72.mjs → chunk-FL2XTEJH.mjs} +3 -4
  11. package/dist/lib/browser/chunk-FL2XTEJH.mjs.map +7 -0
  12. package/dist/lib/browser/chunk-H7OMDDGW.mjs +42 -0
  13. package/dist/lib/browser/chunk-H7OMDDGW.mjs.map +7 -0
  14. package/dist/lib/browser/chunk-HDQXX5DC.mjs +157 -0
  15. package/dist/lib/browser/chunk-HDQXX5DC.mjs.map +7 -0
  16. package/dist/lib/browser/chunk-I34GF4NG.mjs +34 -0
  17. package/dist/lib/browser/chunk-I34GF4NG.mjs.map +7 -0
  18. package/dist/lib/browser/chunk-KNBRTZVK.mjs +892 -0
  19. package/dist/lib/browser/chunk-KNBRTZVK.mjs.map +7 -0
  20. package/dist/lib/browser/{chunk-7IQHKD4U.mjs → chunk-NO7R7QHA.mjs} +4 -7
  21. package/dist/lib/browser/chunk-NO7R7QHA.mjs.map +7 -0
  22. package/dist/lib/browser/{chunk-TCLLRCS3.mjs → chunk-P2E7VMRF.mjs} +10 -7
  23. package/dist/lib/browser/chunk-P2E7VMRF.mjs.map +7 -0
  24. package/dist/lib/browser/{chunk-PKQT6C53.mjs → chunk-QSXYHXCE.mjs} +3 -2
  25. package/dist/lib/browser/chunk-QSXYHXCE.mjs.map +7 -0
  26. package/dist/lib/browser/chunk-RFSO3JRG.mjs +1 -0
  27. package/dist/lib/browser/chunk-TGX63LTL.mjs +8 -0
  28. package/dist/lib/browser/{chunk-FHQTHCX7.mjs.map → chunk-TGX63LTL.mjs.map} +1 -1
  29. package/dist/lib/browser/cli/index.mjs +90 -0
  30. package/dist/lib/browser/cli/index.mjs.map +7 -0
  31. package/dist/lib/browser/common/activation-events.mjs +24 -0
  32. package/dist/lib/browser/common/capabilities.mjs +46 -0
  33. package/dist/lib/browser/core/activation-event.mjs +1 -1
  34. package/dist/lib/browser/core/capability.mjs +1 -1
  35. package/dist/lib/browser/core/plugin-manager.mjs +4 -4
  36. package/dist/lib/browser/core/plugin.mjs +6 -4
  37. package/dist/lib/browser/core/url-loader.mjs +12 -0
  38. package/dist/lib/browser/index.mjs +40 -131
  39. package/dist/lib/browser/index.mjs.map +4 -4
  40. package/dist/lib/browser/invoker-capability-P7KPBTP3.mjs +43 -0
  41. package/dist/lib/browser/invoker-capability-P7KPBTP3.mjs.map +7 -0
  42. package/dist/lib/browser/meta.json +1 -1
  43. package/dist/lib/browser/testing/index.mjs +56 -34
  44. package/dist/lib/browser/testing/index.mjs.map +3 -3
  45. package/dist/lib/browser/{react → ui}/index.mjs +19 -21
  46. package/dist/lib/browser/ui/index.mjs.map +7 -0
  47. package/dist/lib/node-esm/{capability-CFLQ2QQU.mjs → capability-CB3MNEI3.mjs} +16 -11
  48. package/dist/lib/node-esm/capability-CB3MNEI3.mjs.map +7 -0
  49. package/dist/lib/node-esm/capability-CMROGK7R.mjs +36 -0
  50. package/dist/lib/node-esm/capability-CMROGK7R.mjs.map +7 -0
  51. package/dist/lib/node-esm/{chunk-STMXUEPO.mjs → chunk-37NG7SIN.mjs} +3 -4
  52. package/dist/lib/node-esm/chunk-37NG7SIN.mjs.map +7 -0
  53. package/dist/lib/node-esm/chunk-7JPKC7OM.mjs +893 -0
  54. package/dist/lib/node-esm/chunk-7JPKC7OM.mjs.map +7 -0
  55. package/dist/lib/node-esm/chunk-7PPVTBYR.mjs +81 -0
  56. package/dist/lib/node-esm/chunk-7PPVTBYR.mjs.map +7 -0
  57. package/dist/lib/node-esm/chunk-BQ56U4QX.mjs +43 -0
  58. package/dist/lib/node-esm/chunk-BQ56U4QX.mjs.map +7 -0
  59. package/dist/lib/node-esm/{chunk-GT6OKM5I.mjs → chunk-CG6UBBZZ.mjs} +10 -7
  60. package/dist/lib/node-esm/chunk-CG6UBBZZ.mjs.map +7 -0
  61. package/dist/lib/node-esm/chunk-EL3R25OQ.mjs +2 -0
  62. package/dist/lib/node-esm/chunk-EL3R25OQ.mjs.map +7 -0
  63. package/dist/lib/node-esm/{chunk-663A54LQ.mjs → chunk-EXYTXQ47.mjs} +4 -7
  64. package/dist/lib/node-esm/chunk-EXYTXQ47.mjs.map +7 -0
  65. package/dist/lib/node-esm/{chunk-UEWJDI2L.mjs → chunk-FKE4Z3D6.mjs} +2 -2
  66. package/dist/lib/node-esm/{chunk-UEWJDI2L.mjs.map → chunk-FKE4Z3D6.mjs.map} +1 -1
  67. package/dist/lib/node-esm/chunk-OXXXRCQX.mjs +158 -0
  68. package/dist/lib/node-esm/chunk-OXXXRCQX.mjs.map +7 -0
  69. package/dist/lib/node-esm/chunk-WZCSOX5Q.mjs +35 -0
  70. package/dist/lib/node-esm/chunk-WZCSOX5Q.mjs.map +7 -0
  71. package/dist/lib/node-esm/{chunk-XYQTBFPA.mjs → chunk-YH44RHP6.mjs} +324 -181
  72. package/dist/lib/node-esm/chunk-YH44RHP6.mjs.map +7 -0
  73. package/dist/lib/node-esm/{chunk-7OWSHPYK.mjs → chunk-ZZ7CKK6W.mjs} +3 -2
  74. package/dist/lib/node-esm/chunk-ZZ7CKK6W.mjs.map +7 -0
  75. package/dist/lib/node-esm/cli/index.mjs +91 -0
  76. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  77. package/dist/lib/node-esm/common/activation-events.mjs +25 -0
  78. package/dist/lib/node-esm/common/activation-events.mjs.map +7 -0
  79. package/dist/lib/node-esm/common/capabilities.mjs +47 -0
  80. package/dist/lib/node-esm/common/capabilities.mjs.map +7 -0
  81. package/dist/lib/node-esm/core/activation-event.mjs +1 -1
  82. package/dist/lib/node-esm/core/capability.mjs +1 -1
  83. package/dist/lib/node-esm/core/plugin-manager.mjs +4 -4
  84. package/dist/lib/node-esm/core/plugin.mjs +6 -4
  85. package/dist/lib/node-esm/core/url-loader.mjs +13 -0
  86. package/dist/lib/node-esm/core/url-loader.mjs.map +7 -0
  87. package/dist/lib/node-esm/index.mjs +40 -131
  88. package/dist/lib/node-esm/index.mjs.map +4 -4
  89. package/dist/lib/node-esm/invoker-capability-3C5H46ZY.mjs +44 -0
  90. package/dist/lib/node-esm/invoker-capability-3C5H46ZY.mjs.map +7 -0
  91. package/dist/lib/node-esm/meta.json +1 -1
  92. package/dist/lib/node-esm/testing/index.mjs +56 -34
  93. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  94. package/dist/lib/node-esm/{react → ui}/index.mjs +19 -21
  95. package/dist/lib/node-esm/ui/index.mjs.map +7 -0
  96. package/dist/plugin/node-esm/index.mjs +384 -0
  97. package/dist/plugin/node-esm/index.mjs.map +7 -0
  98. package/dist/plugin/node-esm/meta.json +1 -0
  99. package/dist/types/src/{cli.d.ts → cli/cli.d.ts} +2 -2
  100. package/dist/types/src/cli/cli.d.ts.map +1 -0
  101. package/dist/types/src/cli/index.d.ts +2 -0
  102. package/dist/types/src/cli/index.d.ts.map +1 -0
  103. package/dist/types/src/common/activation-events.d.ts +27 -0
  104. package/dist/types/src/common/activation-events.d.ts.map +1 -0
  105. package/dist/types/src/common/capabilities.d.ts +110 -0
  106. package/dist/types/src/common/capabilities.d.ts.map +1 -0
  107. package/dist/types/src/common/index.d.ts +4 -9
  108. package/dist/types/src/common/index.d.ts.map +1 -1
  109. package/dist/types/src/common/operations.d.ts +8 -369
  110. package/dist/types/src/common/operations.d.ts.map +1 -1
  111. package/dist/types/src/common/translations.d.ts +0 -9
  112. package/dist/types/src/common/translations.d.ts.map +1 -1
  113. package/dist/types/src/core/activation-event.d.ts +1 -1
  114. package/dist/types/src/core/activation-event.d.ts.map +1 -1
  115. package/dist/types/src/core/capability.d.ts +7 -7
  116. package/dist/types/src/core/capability.d.ts.map +1 -1
  117. package/dist/types/src/core/index.d.ts +1 -0
  118. package/dist/types/src/core/index.d.ts.map +1 -1
  119. package/dist/types/src/core/plugin-manager.d.ts +9 -2
  120. package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
  121. package/dist/types/src/core/plugin.d.ts +6 -1
  122. package/dist/types/src/core/plugin.d.ts.map +1 -1
  123. package/dist/types/src/core/url-loader.d.ts +25 -0
  124. package/dist/types/src/core/url-loader.d.ts.map +1 -0
  125. package/dist/types/src/core/url-loader.test.d.ts +2 -0
  126. package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
  127. package/dist/types/src/index.d.ts +1 -3
  128. package/dist/types/src/index.d.ts.map +1 -1
  129. package/dist/types/src/plugin-operation/history/capability.d.ts +1 -1
  130. package/dist/types/src/plugin-operation/history/errors.d.ts +30 -3
  131. package/dist/types/src/plugin-operation/history/errors.d.ts.map +1 -1
  132. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts +11 -3
  133. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts.map +1 -1
  134. package/dist/types/src/plugin-operation/invoker-capability.d.ts +1 -1
  135. package/dist/types/src/plugin-operation/invoker-capability.d.ts.map +1 -1
  136. package/dist/types/src/plugin-operation/testing.d.ts +26 -77
  137. package/dist/types/src/plugin-operation/testing.d.ts.map +1 -1
  138. package/dist/types/src/plugin-runtime/capability.d.ts +2 -2
  139. package/dist/types/src/plugin-runtime/capability.d.ts.map +1 -1
  140. package/dist/types/src/testing/withPluginManager.d.ts +1 -1
  141. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  142. package/dist/types/src/{react → ui/components/App}/App.d.ts +3 -2
  143. package/dist/types/src/ui/components/App/App.d.ts.map +1 -0
  144. package/dist/types/src/{react/Surface.stories.d.ts → ui/components/App/App.stories.d.ts} +7 -2
  145. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -0
  146. package/dist/types/src/ui/components/App/index.d.ts +2 -0
  147. package/dist/types/src/ui/components/App/index.d.ts.map +1 -0
  148. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -0
  149. package/dist/types/src/{react → ui/components/PluginManager}/PluginManagerProvider.d.ts +1 -1
  150. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -0
  151. package/dist/types/src/ui/components/PluginManager/index.d.ts +2 -0
  152. package/dist/types/src/ui/components/PluginManager/index.d.ts.map +1 -0
  153. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +12 -0
  154. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -0
  155. package/dist/types/src/{react/App.stories.d.ts → ui/components/Surface/SurfaceComponent.stories.d.ts} +1 -1
  156. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -0
  157. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -0
  158. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
  159. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
  160. package/dist/types/src/ui/components/Surface/context.d.ts +5 -0
  161. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -0
  162. package/dist/types/src/ui/components/Surface/index.d.ts +26 -0
  163. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -0
  164. package/dist/types/src/{common/surface.d.ts → ui/components/Surface/types.d.ts} +20 -18
  165. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -0
  166. package/dist/types/src/ui/components/index.d.ts +4 -0
  167. package/dist/types/src/ui/components/index.d.ts.map +1 -0
  168. package/dist/types/src/ui/hooks/index.d.ts +6 -0
  169. package/dist/types/src/ui/hooks/index.d.ts.map +1 -0
  170. package/dist/types/src/{react → ui/hooks}/useApp.d.ts +26 -9
  171. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -0
  172. package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
  173. package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
  174. package/dist/types/src/{react → ui/hooks}/useCapabilities.d.ts +6 -1
  175. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -0
  176. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -0
  177. package/dist/types/src/{react/common.d.ts → ui/hooks/useSettingsState.d.ts} +1 -5
  178. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -0
  179. package/dist/types/src/ui/hooks/useSurface.d.ts +3 -0
  180. package/dist/types/src/ui/hooks/useSurface.d.ts.map +1 -0
  181. package/dist/types/src/ui/index.d.ts +3 -0
  182. package/dist/types/src/ui/index.d.ts.map +1 -0
  183. package/dist/types/src/vite-plugin/composer-plugin.d.ts +18 -0
  184. package/dist/types/src/vite-plugin/composer-plugin.d.ts.map +1 -0
  185. package/dist/types/src/vite-plugin/import-map-plugin.d.ts +16 -0
  186. package/dist/types/src/vite-plugin/import-map-plugin.d.ts.map +1 -0
  187. package/dist/types/src/vite-plugin/index.d.ts +3 -0
  188. package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
  189. package/dist/types/src/vite-plugin/packages.d.ts +7 -0
  190. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
  191. package/dist/types/tsconfig.tsbuildinfo +1 -1
  192. package/moon.yml +20 -6
  193. package/package.json +91 -64
  194. package/src/{cli.ts → cli/cli.ts} +10 -10
  195. package/src/{playground/debug → cli}/index.ts +1 -1
  196. package/src/common/activation-events.ts +44 -0
  197. package/src/common/capabilities.ts +172 -0
  198. package/src/common/index.ts +4 -9
  199. package/src/common/operations.ts +6 -382
  200. package/src/common/translations.ts +0 -12
  201. package/src/context.ts +1 -1
  202. package/src/core/activation-event.ts +5 -2
  203. package/src/core/capability-manager.ts +1 -1
  204. package/src/core/capability.ts +11 -10
  205. package/src/core/index.ts +1 -0
  206. package/src/core/plugin-manager.test.ts +313 -44
  207. package/src/core/plugin-manager.ts +344 -157
  208. package/src/core/plugin.ts +10 -2
  209. package/src/core/url-loader.test.ts +79 -0
  210. package/src/core/url-loader.ts +148 -0
  211. package/src/index.ts +1 -3
  212. package/src/plugin-operation/OperationPlugin.ts +5 -5
  213. package/src/plugin-operation/history/capability.ts +5 -5
  214. package/src/plugin-operation/history/errors.ts +2 -6
  215. package/src/plugin-operation/history/history-tracker.test.ts +36 -42
  216. package/src/plugin-operation/history/undo-mapping.ts +6 -3
  217. package/src/plugin-operation/history/undo-registry.test.ts +3 -3
  218. package/src/plugin-operation/invoker-capability.ts +21 -7
  219. package/src/plugin-operation/meta.ts +1 -1
  220. package/src/plugin-operation/testing.ts +25 -45
  221. package/src/plugin-runtime/RuntimePlugin.ts +4 -4
  222. package/src/plugin-runtime/capability.ts +5 -5
  223. package/src/plugin-runtime/meta.ts +1 -1
  224. package/src/testing/service.ts +6 -6
  225. package/src/testing/withPluginManager.stories.tsx +6 -6
  226. package/src/testing/withPluginManager.tsx +46 -19
  227. package/src/ui/components/App/App.stories.tsx +92 -0
  228. package/src/{react → ui/components/App}/App.tsx +9 -11
  229. package/src/{playground/layout → ui/components/App}/index.ts +1 -1
  230. package/src/{react → ui/components/PluginManager}/PluginManagerContext.stories.tsx +13 -14
  231. package/src/{react → ui/components/PluginManager}/PluginManagerProvider.ts +1 -1
  232. package/src/ui/components/PluginManager/index.ts +5 -0
  233. package/src/{react/Surface.stories.tsx → ui/components/Surface/SurfaceComponent.stories.tsx} +28 -24
  234. package/src/{react/Surface.tsx → ui/components/Surface/SurfaceComponent.tsx} +48 -58
  235. package/src/{react → ui/components/Surface}/SurfaceInfo.tsx +2 -2
  236. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
  237. package/src/ui/components/Surface/context.ts +12 -0
  238. package/src/ui/components/Surface/index.ts +35 -0
  239. package/src/{common/surface.ts → ui/components/Surface/types.ts} +22 -25
  240. package/src/ui/components/index.ts +7 -0
  241. package/src/ui/hooks/index.ts +9 -0
  242. package/src/ui/hooks/useApp.test.tsx +159 -0
  243. package/src/{react → ui/hooks}/useApp.tsx +110 -30
  244. package/src/{react → ui/hooks}/useCapabilities.ts +9 -5
  245. package/src/{react/common.ts → ui/hooks/useSettingsState.ts} +0 -11
  246. package/src/ui/hooks/useSurface.ts +13 -0
  247. package/src/ui/index.ts +6 -0
  248. package/src/vite-plugin/composer-plugin.ts +128 -0
  249. package/src/vite-plugin/import-map-plugin.ts +315 -0
  250. package/src/vite-plugin/index.ts +6 -0
  251. package/src/vite-plugin/packages.ts +29 -0
  252. package/tsconfig.json +4 -28
  253. package/tsconfig.node.json +2 -4
  254. package/typedoc.json +2 -4
  255. package/vitest.config.ts +1 -1
  256. package/dist/lib/browser/app-graph-builder-M2VPYQC6.mjs +0 -149
  257. package/dist/lib/browser/app-graph-builder-M2VPYQC6.mjs.map +0 -7
  258. package/dist/lib/browser/capability-7PCNSWBT.mjs.map +0 -7
  259. package/dist/lib/browser/capability-KP3PFEXD.mjs +0 -31
  260. package/dist/lib/browser/capability-KP3PFEXD.mjs.map +0 -7
  261. package/dist/lib/browser/chunk-6Y7PZV72.mjs.map +0 -7
  262. package/dist/lib/browser/chunk-7IQHKD4U.mjs.map +0 -7
  263. package/dist/lib/browser/chunk-BLQJSGL3.mjs +0 -732
  264. package/dist/lib/browser/chunk-BLQJSGL3.mjs.map +0 -7
  265. package/dist/lib/browser/chunk-FHQTHCX7.mjs +0 -8
  266. package/dist/lib/browser/chunk-FMZN33N4.mjs.map +0 -7
  267. package/dist/lib/browser/chunk-H4WPA7U7.mjs +0 -77
  268. package/dist/lib/browser/chunk-H4WPA7U7.mjs.map +0 -7
  269. package/dist/lib/browser/chunk-PKQT6C53.mjs.map +0 -7
  270. package/dist/lib/browser/chunk-TCLLRCS3.mjs.map +0 -7
  271. package/dist/lib/browser/chunk-XYNO72GQ.mjs +0 -746
  272. package/dist/lib/browser/chunk-XYNO72GQ.mjs.map +0 -7
  273. package/dist/lib/browser/common/index.mjs +0 -38
  274. package/dist/lib/browser/invoker-capability-SZRSTHEH.mjs +0 -32
  275. package/dist/lib/browser/invoker-capability-SZRSTHEH.mjs.map +0 -7
  276. package/dist/lib/browser/operation-resolver-6MP2MYOY.mjs +0 -64
  277. package/dist/lib/browser/operation-resolver-6MP2MYOY.mjs.map +0 -7
  278. package/dist/lib/node-esm/app-graph-builder-LROHGJEM.mjs +0 -150
  279. package/dist/lib/node-esm/app-graph-builder-LROHGJEM.mjs.map +0 -7
  280. package/dist/lib/node-esm/capability-CFLQ2QQU.mjs.map +0 -7
  281. package/dist/lib/node-esm/capability-RCUNM2M7.mjs +0 -32
  282. package/dist/lib/node-esm/capability-RCUNM2M7.mjs.map +0 -7
  283. package/dist/lib/node-esm/chunk-663A54LQ.mjs.map +0 -7
  284. package/dist/lib/node-esm/chunk-6WXBT3EC.mjs +0 -747
  285. package/dist/lib/node-esm/chunk-6WXBT3EC.mjs.map +0 -7
  286. package/dist/lib/node-esm/chunk-7OWSHPYK.mjs.map +0 -7
  287. package/dist/lib/node-esm/chunk-GQEBIGKD.mjs +0 -733
  288. package/dist/lib/node-esm/chunk-GQEBIGKD.mjs.map +0 -7
  289. package/dist/lib/node-esm/chunk-GT6OKM5I.mjs.map +0 -7
  290. package/dist/lib/node-esm/chunk-STMXUEPO.mjs.map +0 -7
  291. package/dist/lib/node-esm/chunk-XR6NMKEP.mjs +0 -78
  292. package/dist/lib/node-esm/chunk-XR6NMKEP.mjs.map +0 -7
  293. package/dist/lib/node-esm/chunk-XYQTBFPA.mjs.map +0 -7
  294. package/dist/lib/node-esm/common/index.mjs +0 -39
  295. package/dist/lib/node-esm/invoker-capability-PNMA5JOS.mjs +0 -33
  296. package/dist/lib/node-esm/invoker-capability-PNMA5JOS.mjs.map +0 -7
  297. package/dist/lib/node-esm/operation-resolver-7YWDMTNU.mjs +0 -65
  298. package/dist/lib/node-esm/operation-resolver-7YWDMTNU.mjs.map +0 -7
  299. package/dist/types/src/cli.d.ts.map +0 -1
  300. package/dist/types/src/common/activation-event.d.ts +0 -66
  301. package/dist/types/src/common/activation-event.d.ts.map +0 -1
  302. package/dist/types/src/common/capability.d.ts +0 -265
  303. package/dist/types/src/common/capability.d.ts.map +0 -1
  304. package/dist/types/src/common/collaboration.d.ts +0 -26
  305. package/dist/types/src/common/collaboration.d.ts.map +0 -1
  306. package/dist/types/src/common/file.d.ts +0 -14
  307. package/dist/types/src/common/file.d.ts.map +0 -1
  308. package/dist/types/src/common/graph.d.ts +0 -21
  309. package/dist/types/src/common/graph.d.ts.map +0 -1
  310. package/dist/types/src/common/plugin.d.ts +0 -201
  311. package/dist/types/src/common/plugin.d.ts.map +0 -1
  312. package/dist/types/src/common/surface.d.ts.map +0 -1
  313. package/dist/types/src/playground/debug/Debug.d.ts +0 -8
  314. package/dist/types/src/playground/debug/Debug.d.ts.map +0 -1
  315. package/dist/types/src/playground/debug/index.d.ts +0 -2
  316. package/dist/types/src/playground/debug/index.d.ts.map +0 -1
  317. package/dist/types/src/playground/debug/plugin.d.ts +0 -3
  318. package/dist/types/src/playground/debug/plugin.d.ts.map +0 -1
  319. package/dist/types/src/playground/generator/Main.d.ts +0 -8
  320. package/dist/types/src/playground/generator/Main.d.ts.map +0 -1
  321. package/dist/types/src/playground/generator/Toolbar.d.ts +0 -8
  322. package/dist/types/src/playground/generator/Toolbar.d.ts.map +0 -1
  323. package/dist/types/src/playground/generator/generator.d.ts +0 -19
  324. package/dist/types/src/playground/generator/generator.d.ts.map +0 -1
  325. package/dist/types/src/playground/generator/index.d.ts +0 -3
  326. package/dist/types/src/playground/generator/index.d.ts.map +0 -1
  327. package/dist/types/src/playground/generator/plugin.d.ts +0 -3
  328. package/dist/types/src/playground/generator/plugin.d.ts.map +0 -1
  329. package/dist/types/src/playground/layout/Layout.d.ts +0 -10
  330. package/dist/types/src/playground/layout/Layout.d.ts.map +0 -1
  331. package/dist/types/src/playground/layout/index.d.ts +0 -2
  332. package/dist/types/src/playground/layout/index.d.ts.map +0 -1
  333. package/dist/types/src/playground/layout/plugin.d.ts +0 -3
  334. package/dist/types/src/playground/layout/plugin.d.ts.map +0 -1
  335. package/dist/types/src/playground/logger/Toolbar.d.ts +0 -8
  336. package/dist/types/src/playground/logger/Toolbar.d.ts.map +0 -1
  337. package/dist/types/src/playground/logger/index.d.ts +0 -2
  338. package/dist/types/src/playground/logger/index.d.ts.map +0 -1
  339. package/dist/types/src/playground/logger/plugin.d.ts +0 -3
  340. package/dist/types/src/playground/logger/plugin.d.ts.map +0 -1
  341. package/dist/types/src/playground/logger/schema.d.ts +0 -27
  342. package/dist/types/src/playground/logger/schema.d.ts.map +0 -1
  343. package/dist/types/src/playground/playground.stories.d.ts +0 -11
  344. package/dist/types/src/playground/playground.stories.d.ts.map +0 -1
  345. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +0 -3
  346. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +0 -1
  347. package/dist/types/src/plugin-settings/actions.d.ts +0 -61
  348. package/dist/types/src/plugin-settings/actions.d.ts.map +0 -1
  349. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -6
  350. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  351. package/dist/types/src/plugin-settings/index.d.ts +0 -3
  352. package/dist/types/src/plugin-settings/index.d.ts.map +0 -1
  353. package/dist/types/src/plugin-settings/meta.d.ts +0 -3
  354. package/dist/types/src/plugin-settings/meta.d.ts.map +0 -1
  355. package/dist/types/src/plugin-settings/operation-resolver.d.ts +0 -6
  356. package/dist/types/src/plugin-settings/operation-resolver.d.ts.map +0 -1
  357. package/dist/types/src/plugin-settings/translations.d.ts +0 -11
  358. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  359. package/dist/types/src/react/App.d.ts.map +0 -1
  360. package/dist/types/src/react/App.stories.d.ts.map +0 -1
  361. package/dist/types/src/react/DefaultFallback.d.ts +0 -8
  362. package/dist/types/src/react/DefaultFallback.d.ts.map +0 -1
  363. package/dist/types/src/react/ErrorBoundary.d.ts +0 -30
  364. package/dist/types/src/react/ErrorBoundary.d.ts.map +0 -1
  365. package/dist/types/src/react/PluginManagerContext.stories.d.ts.map +0 -1
  366. package/dist/types/src/react/PluginManagerProvider.d.ts.map +0 -1
  367. package/dist/types/src/react/Surface.d.ts +0 -14
  368. package/dist/types/src/react/Surface.d.ts.map +0 -1
  369. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  370. package/dist/types/src/react/SurfaceInfo.d.ts.map +0 -1
  371. package/dist/types/src/react/common.d.ts.map +0 -1
  372. package/dist/types/src/react/index.d.ts +0 -9
  373. package/dist/types/src/react/index.d.ts.map +0 -1
  374. package/dist/types/src/react/types.d.ts +0 -12
  375. package/dist/types/src/react/types.d.ts.map +0 -1
  376. package/dist/types/src/react/useApp.d.ts.map +0 -1
  377. package/dist/types/src/react/useCapabilities.d.ts.map +0 -1
  378. package/dist/types/src/react/useLoading.d.ts.map +0 -1
  379. package/dist/types/src/react/useOperationResolver.d.ts +0 -19
  380. package/dist/types/src/react/useOperationResolver.d.ts.map +0 -1
  381. package/src/common/activation-event.ts +0 -99
  382. package/src/common/capability.ts +0 -343
  383. package/src/common/collaboration.ts +0 -31
  384. package/src/common/file.ts +0 -22
  385. package/src/common/graph.ts +0 -30
  386. package/src/common/plugin.ts +0 -364
  387. package/src/playground/debug/Debug.tsx +0 -49
  388. package/src/playground/debug/plugin.ts +0 -16
  389. package/src/playground/generator/Main.tsx +0 -80
  390. package/src/playground/generator/Toolbar.tsx +0 -57
  391. package/src/playground/generator/generator.ts +0 -48
  392. package/src/playground/generator/index.ts +0 -6
  393. package/src/playground/generator/plugin.ts +0 -21
  394. package/src/playground/layout/Layout.tsx +0 -37
  395. package/src/playground/layout/plugin.ts +0 -18
  396. package/src/playground/logger/Toolbar.tsx +0 -33
  397. package/src/playground/logger/index.ts +0 -5
  398. package/src/playground/logger/plugin.ts +0 -42
  399. package/src/playground/logger/schema.ts +0 -22
  400. package/src/playground/playground.stories.tsx +0 -54
  401. package/src/plugin-settings/SettingsPlugin.ts +0 -19
  402. package/src/plugin-settings/actions.ts +0 -64
  403. package/src/plugin-settings/app-graph-builder.ts +0 -140
  404. package/src/plugin-settings/index.ts +0 -6
  405. package/src/plugin-settings/meta.ts +0 -10
  406. package/src/plugin-settings/operation-resolver.ts +0 -55
  407. package/src/plugin-settings/translations.ts +0 -19
  408. package/src/react/App.stories.tsx +0 -63
  409. package/src/react/DefaultFallback.tsx +0 -26
  410. package/src/react/ErrorBoundary.tsx +0 -56
  411. package/src/react/index.ts +0 -14
  412. package/src/react/types.ts +0 -27
  413. package/src/react/useOperationResolver.ts +0 -40
  414. /package/dist/lib/{node-esm/react/index.mjs.map → browser/chunk-RFSO3JRG.mjs.map} +0 -0
  415. /package/dist/lib/{node-esm/common/index.mjs.map → browser/common/activation-events.mjs.map} +0 -0
  416. /package/dist/lib/browser/{react/index.mjs.map → common/capabilities.mjs.map} +0 -0
  417. /package/dist/lib/browser/{common/index.mjs.map → core/url-loader.mjs.map} +0 -0
  418. /package/dist/types/src/{react → ui/components/PluginManager}/PluginManagerContext.stories.d.ts +0 -0
  419. /package/dist/types/src/{react → ui/components/Surface}/SurfaceInfo.d.ts +0 -0
  420. /package/dist/types/src/{react → ui/hooks}/useLoading.d.ts +0 -0
  421. /package/src/{react → ui/hooks}/useLoading.tsx +0 -0
@@ -15,6 +15,7 @@ import * as PubSub from 'effect/PubSub';
15
15
  import * as Ref from 'effect/Ref';
16
16
 
17
17
  import { runAndForwardErrors } from '@dxos/effect';
18
+ import { Performance } from '@dxos/effect';
18
19
  import { log } from '@dxos/log';
19
20
 
20
21
  import * as ActivationEvent from './activation-event';
@@ -36,7 +37,13 @@ export type ManagerOptions = {
36
37
  registry?: Registry.Registry;
37
38
  };
38
39
 
39
- type ActivationMessage = { event: string; state: 'activating' | 'activated' | 'error'; error?: Error };
40
+ export type ActivationMessage = {
41
+ event: string;
42
+ state: 'activating' | 'activated' | 'error';
43
+ /** Module ID when the message pertains to a specific module activation. */
44
+ module?: string;
45
+ error?: Error;
46
+ };
40
47
 
41
48
  /**
42
49
  * Interface for the Plugin Manager.
@@ -74,6 +81,13 @@ export interface PluginManager {
74
81
  ): Effect.Effect<boolean, Error>;
75
82
  deactivate(id: string): Effect.Effect<boolean, Error>;
76
83
  reset(event: ActivationEvent.ActivationEvent | string): Effect.Effect<boolean, Error>;
84
+
85
+ /**
86
+ * Shuts down the manager by deactivating all active modules in reverse activation order,
87
+ * clearing all capabilities, and resetting lifecycle bookkeeping.
88
+ * Plugins, core, enabled, and modules remain intact so the manager can be reused.
89
+ */
90
+ shutdown(): Effect.Effect<boolean, Error>;
77
91
  }
78
92
 
79
93
  /**
@@ -105,6 +119,9 @@ class ManagerImpl implements PluginManager {
105
119
  private readonly _moduleSemaphores = new Map<Plugin.PluginModule['id'], Effect.Semaphore>();
106
120
  private readonly _activatingEvents = Effect.runSync(Ref.make<string[]>([]));
107
121
  private readonly _activatingModules = Effect.runSync(Ref.make<string[]>([]));
122
+ private readonly _inFlightFibers = Effect.runSync(Ref.make<Array<Fiber.Fiber<unknown, unknown>>>([]));
123
+ private readonly _shutdownSemaphore = Effect.runSync(Effect.makeSemaphore(1));
124
+ private readonly _shuttingDown = Effect.runSync(Ref.make(false));
108
125
 
109
126
  constructor({
110
127
  pluginLoader,
@@ -210,7 +227,7 @@ class ManagerImpl implements PluginManager {
210
227
  log('add plugin', { id });
211
228
  const plugin = yield* this._pluginLoader(id);
212
229
  this._addPlugin(plugin);
213
- return yield* this.enable(id);
230
+ return yield* this.enable(plugin.meta.id);
214
231
  });
215
232
  }
216
233
 
@@ -299,146 +316,30 @@ class ManagerImpl implements PluginManager {
299
316
  ): Effect.Effect<boolean, Error> {
300
317
  const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);
301
318
  return Effect.gen(this, function* () {
302
- log('activating', { key, ...params });
303
- yield* Ref.update(this._activatingEvents, (activating) => Array.append(activating, key));
304
- const pendingIndex = this._get(this._pendingResetAtom).findIndex((event) => event === key);
305
- if (pendingIndex !== -1) {
306
- this._update(this._pendingResetAtom, (pending) => pending.filter((event) => event !== key));
307
- }
308
-
309
- const activatingEvents = yield* this._activatingEvents;
310
- const activatingModules = yield* this._activatingModules;
311
- const modules = this._getInactiveModulesByEvent(key).filter((module) => {
312
- const allOf = ActivationEvent.isAllOf(module.activatesOn);
313
- if (!allOf) {
314
- return true;
315
- }
316
-
317
- // Check to see if all of the events in the `allOf` have been fired.
318
- // An event can be considered "fired" if it is in the `eventsFired` list or if it is currently being activated.
319
- const events = ActivationEvent.getEvents(module.activatesOn).filter(
320
- (event) => ActivationEvent.eventKey(event) !== key,
321
- );
322
- return (
323
- events.every(
324
- (event) =>
325
- this._get(this._eventsFiredAtom).includes(ActivationEvent.eventKey(event)) ||
326
- activatingEvents.includes(ActivationEvent.eventKey(event)),
327
- ) && !activatingModules.includes(module.id)
328
- );
329
- });
330
- yield* Ref.update(this._activatingModules, (activating) =>
331
- Array.appendAll(
332
- activating,
333
- modules.map((module) => module.id),
334
- ),
335
- );
336
- if (modules.length === 0) {
337
- log('no modules to activate', { key });
338
- if (!this._get(this._eventsFiredAtom).includes(key)) {
339
- this._update(this._eventsFiredAtom, (events) => [...events, key]);
340
- }
319
+ if (yield* this._isShuttingDown()) {
320
+ log('skipping activation during shutdown', { key, ...params });
341
321
  return false;
342
322
  }
343
323
 
344
- log('activating modules', { key, modules: modules.map((module) => module.id) });
345
- yield* PubSub.publish(this.activation, { event: key, state: 'activating' });
346
-
347
- // Fire activatesBefore events.
348
- const beforeEvents = Function.pipe(
349
- modules,
350
- Array.flatMap((module) => module.activatesBefore ?? []),
351
- HashSet.fromIterable,
352
- HashSet.toValues,
353
- Array.filter((event) => !activatingEvents.includes(ActivationEvent.eventKey(event))),
354
- );
355
- yield* Function.pipe(
356
- beforeEvents,
357
- Array.map((event) => this.activate(event, { before: key })),
358
- Effect.allWith({ concurrency: 'unbounded' }),
359
- together(
360
- Effect.sleep(Duration.seconds(10)).pipe(
361
- Effect.andThen(
362
- Effect.sync(() =>
363
- log.warn('activatesBefore is taking a long time', {
364
- event: key,
365
- beforeEvents: beforeEvents.map(ActivationEvent.eventKey),
366
- }),
367
- ),
368
- ),
369
- ),
370
- ),
371
- );
372
-
373
- // Concurrently triggers loading of lazy capabilities.
374
- const getCapabilities = yield* Function.pipe(
375
- modules,
376
- Array.map((mod) => this._loadModule(mod)),
377
- Effect.allWith({ concurrency: 'unbounded' }),
378
- Effect.catchAll((error) => {
379
- return Effect.gen(this, function* () {
380
- yield* PubSub.publish(this.activation, { event: key, state: 'error', error });
381
- return yield* Effect.fail(error);
382
- });
383
- }),
384
- );
385
-
386
- // Contribute the capabilities from the activated modules.
387
- yield* Function.pipe(
388
- modules,
389
- Array.zip(getCapabilities),
390
- Array.map(([module, capabilities]) => this._contributeCapabilities(module, capabilities)),
391
- // TODO(wittjosiah): This currently can't be run in parallel.
392
- // Running this with concurrency causes races with `allOf` activation events.
393
- Effect.all,
394
- );
395
-
396
- // Fire activatesAfter events.
397
- const afterEvents = Function.pipe(
398
- modules,
399
- Array.flatMap((module) => module.activatesAfter ?? []),
400
- HashSet.fromIterable,
401
- HashSet.toValues,
402
- Array.filter((event) => !activatingEvents.includes(ActivationEvent.eventKey(event))),
403
- );
404
- yield* Function.pipe(
405
- afterEvents,
406
- Array.map((event) => this.activate(event, { after: key })),
407
- Effect.allWith({ concurrency: 'unbounded' }),
408
- together(
409
- Effect.sleep(Duration.seconds(10)).pipe(
410
- Effect.andThen(
411
- Effect.sync(() =>
412
- log.warn('activatesAfter is taking a long time', {
413
- event: key,
414
- afterEvents: afterEvents.map(ActivationEvent.eventKey),
415
- }),
416
- ),
324
+ return yield* Effect.withFiberRuntime<boolean, Error>((fiber) =>
325
+ this._activateEvent(key, params, fiber).pipe(
326
+ together(
327
+ Effect.sleep(Duration.seconds(15)).pipe(
328
+ Effect.andThen(Effect.sync(() => log.warn('event activation is taking a long time', { event: key }))),
417
329
  ),
418
330
  ),
331
+ Performance.addTrackEntry({
332
+ name: typeof event === 'string' ? event : ActivationEvent.eventKey(event),
333
+ devtools: {
334
+ dataType: 'track-entry',
335
+ track: 'Event Activation',
336
+ trackGroup: 'Composer',
337
+ color: 'primary',
338
+ },
339
+ }),
419
340
  ),
420
341
  );
421
-
422
- yield* Ref.update(this._activatingEvents, (activating) => Array.filter(activating, (event) => event !== key));
423
- yield* Ref.update(this._activatingModules, (activating) =>
424
- Array.filter(activating, (module) => !modules.map((module) => module.id).includes(module)),
425
- );
426
-
427
- if (!this._get(this._eventsFiredAtom).includes(key)) {
428
- this._update(this._eventsFiredAtom, (events) => [...events, key]);
429
- }
430
-
431
- yield* PubSub.publish(this.activation, { event: key, state: 'activated' });
432
- log('activated', { key });
433
-
434
- return true;
435
- }).pipe(
436
- together(
437
- Effect.sleep(Duration.seconds(15)).pipe(
438
- Effect.andThen(Effect.sync(() => log.warn('event activation is taking a long time', { event: key }))),
439
- ),
440
- ),
441
- );
342
+ });
442
343
  }
443
344
 
444
345
  /**
@@ -485,6 +386,40 @@ class ManagerImpl implements PluginManager {
485
386
  });
486
387
  }
487
388
 
389
+ shutdown(): Effect.Effect<boolean, Error> {
390
+ return this._shutdownSemaphore.withPermits(1)(
391
+ Effect.gen(this, function* () {
392
+ yield* Ref.set(this._shuttingDown, true);
393
+ log('shutdown');
394
+
395
+ yield* this._interruptInFlightActivations();
396
+
397
+ const activeIds = [...this._get(this._activeAtom)].reverse();
398
+ const allModules = this._get(this._modulesAtom);
399
+ const modulesToDeactivate = activeIds
400
+ .map((id) => allModules.find((module) => module.id === id))
401
+ .filter((module): module is Plugin.PluginModule => module != null);
402
+
403
+ for (const module of modulesToDeactivate) {
404
+ yield* this._deactivateModule(module);
405
+ }
406
+
407
+ this._set(this._eventsFiredAtom, []);
408
+ this._set(this._pendingResetAtom, []);
409
+ this._moduleMemoMap.clear();
410
+ yield* Ref.set(this._activatingEvents, []);
411
+ yield* Ref.set(this._activatingModules, []);
412
+
413
+ log('shutdown complete');
414
+ return true;
415
+ }).pipe(Effect.ensuring(Ref.set(this._shuttingDown, false))),
416
+ );
417
+ }
418
+
419
+ //
420
+ // State helpers
421
+ //
422
+
488
423
  private _get<T>(atom: Atom.Atom<T>): T {
489
424
  return this.registry.get(atom);
490
425
  }
@@ -497,26 +432,8 @@ class ManagerImpl implements PluginManager {
497
432
  this._set(atom, updater(this._get(atom)));
498
433
  }
499
434
 
500
- private _addPlugin(plugin: Plugin.Plugin): void {
501
- log('add plugin', { id: plugin.meta.id });
502
- // TODO(wittjosiah): Find a way to add a warning for duplicate plugins that doesn't cause log spam.
503
- this._update(this._pluginsAtom, (plugins) => (plugins.includes(plugin) ? plugins : [...plugins, plugin]));
504
- }
505
-
506
- private _removePlugin(id: string): void {
507
- log('remove plugin', { id });
508
- this._update(this._pluginsAtom, (plugins) => plugins.filter((plugin) => plugin.meta.id !== id));
509
- }
510
-
511
- private _addModule(module: Plugin.PluginModule): void {
512
- log('add module', { id: module.id });
513
- // TODO(wittjosiah): Find a way to add a warning for duplicate modules that doesn't cause log spam.
514
- this._update(this._modulesAtom, (modules) => (modules.includes(module) ? modules : [...modules, module]));
515
- }
516
-
517
- private _removeModule(id: string): void {
518
- log('remove module', { id });
519
- this._update(this._modulesAtom, (modules) => modules.filter((module) => module.id !== id));
435
+ private _isShuttingDown(): Effect.Effect<boolean> {
436
+ return Ref.get(this._shuttingDown);
520
437
  }
521
438
 
522
439
  private _getPlugin(id: string): Plugin.Plugin | undefined {
@@ -560,6 +477,257 @@ class ManagerImpl implements PluginManager {
560
477
  }
561
478
  }
562
479
 
480
+ private _clearPendingReset(key: string): void {
481
+ const pendingIndex = this._get(this._pendingResetAtom).findIndex((event) => event === key);
482
+ if (pendingIndex !== -1) {
483
+ this._update(this._pendingResetAtom, (pending) => pending.filter((event) => event !== key));
484
+ }
485
+ }
486
+
487
+ //
488
+ // Fiber helpers
489
+ //
490
+
491
+ private _interruptInFlightActivations(): Effect.Effect<void> {
492
+ return Effect.gen(this, function* () {
493
+ const inFlightFibers = yield* Ref.get(this._inFlightFibers);
494
+ yield* Effect.forEach(inFlightFibers, (fiber) => Fiber.interrupt(fiber), {
495
+ concurrency: 'unbounded',
496
+ });
497
+ });
498
+ }
499
+
500
+ private _trackFiber(
501
+ ref: Ref.Ref<Array<Fiber.Fiber<unknown, unknown>>>,
502
+ fiber: Fiber.Fiber<unknown, unknown>,
503
+ ): Effect.Effect<void> {
504
+ return Ref.update(ref, (fibers) => [...fibers, fiber]);
505
+ }
506
+
507
+ private _untrackFiber(
508
+ ref: Ref.Ref<Array<Fiber.Fiber<unknown, unknown>>>,
509
+ fiber: Fiber.Fiber<unknown, unknown>,
510
+ ): Effect.Effect<void> {
511
+ return Ref.update(ref, (fibers) => fibers.filter((trackedFiber) => trackedFiber !== fiber));
512
+ }
513
+
514
+ //
515
+ // Registration helpers
516
+ //
517
+
518
+ private _addPlugin(plugin: Plugin.Plugin): void {
519
+ log('add plugin', { id: plugin.meta.id });
520
+ // TODO(wittjosiah): Find a way to add a warning for duplicate plugins that doesn't cause log spam.
521
+ this._update(this._pluginsAtom, (plugins) => (plugins.includes(plugin) ? plugins : [...plugins, plugin]));
522
+ }
523
+
524
+ private _removePlugin(id: string): void {
525
+ log('remove plugin', { id });
526
+ this._update(this._pluginsAtom, (plugins) => plugins.filter((plugin) => plugin.meta.id !== id));
527
+ }
528
+
529
+ private _addModule(module: Plugin.PluginModule): void {
530
+ log('add module', { id: module.id });
531
+ // TODO(wittjosiah): Find a way to add a warning for duplicate modules that doesn't cause log spam.
532
+ this._update(this._modulesAtom, (modules) => (modules.includes(module) ? modules : [...modules, module]));
533
+ }
534
+
535
+ private _removeModule(id: string): void {
536
+ log('remove module', { id });
537
+ this._update(this._modulesAtom, (modules) => modules.filter((module) => module.id !== id));
538
+ }
539
+
540
+ //
541
+ // Activation helpers
542
+ //
543
+
544
+ private _activateEvent(
545
+ key: string,
546
+ params: { before?: string; after?: string } | undefined,
547
+ fiber: Fiber.Fiber<unknown, unknown>,
548
+ ): Effect.Effect<boolean, Error> {
549
+ return Effect.gen(this, function* () {
550
+ yield* this._trackFiber(this._inFlightFibers, fiber);
551
+ log('activating', { key, ...params });
552
+ yield* Ref.update(this._activatingEvents, (activating) => Array.append(activating, key));
553
+ this._clearPendingReset(key);
554
+
555
+ const activatingEvents = yield* this._activatingEvents;
556
+ const activatingModules = yield* this._activatingModules;
557
+ const modules = this._getModulesForActivation(key, activatingEvents, activatingModules);
558
+ if (modules.length === 0) {
559
+ log('no modules to activate', { key });
560
+ if (!this._get(this._eventsFiredAtom).includes(key)) {
561
+ this._update(this._eventsFiredAtom, (events) => [...events, key]);
562
+ }
563
+ return false;
564
+ }
565
+
566
+ return yield* this._activateModulesForEvent(key, modules, activatingEvents);
567
+ }).pipe(
568
+ Effect.ensuring(
569
+ Effect.all([
570
+ this._untrackFiber(this._inFlightFibers, fiber),
571
+ Ref.update(this._activatingEvents, (activating) => Array.filter(activating, (event) => event !== key)),
572
+ ]),
573
+ ),
574
+ );
575
+ }
576
+
577
+ private _activateModulesForEvent(
578
+ key: string,
579
+ modules: Plugin.PluginModule[],
580
+ activatingEvents: string[],
581
+ ): Effect.Effect<boolean, Error> {
582
+ const activatingModuleIds = modules.map((module) => module.id);
583
+ return Effect.gen(this, function* () {
584
+ yield* Ref.update(this._activatingModules, (activating) => Array.appendAll(activating, activatingModuleIds));
585
+
586
+ log('activating modules', { key, modules: activatingModuleIds });
587
+ performance.mark(`event:${key}:start`);
588
+ yield* PubSub.publish(this.activation, { event: key, state: 'activating' });
589
+
590
+ yield* this._activateRelatedEvents(key, this._getBeforeEvents(modules, activatingEvents), 'before');
591
+
592
+ const capabilities = yield* this._loadCapabilitiesForModules(key, modules);
593
+ yield* this._contributeCapabilitiesForModules(modules, capabilities);
594
+
595
+ yield* this._activateRelatedEvents(key, this._getAfterEvents(modules, activatingEvents), 'after');
596
+
597
+ if (!this._get(this._eventsFiredAtom).includes(key)) {
598
+ this._update(this._eventsFiredAtom, (events) => [...events, key]);
599
+ }
600
+
601
+ performance.mark(`event:${key}:end`);
602
+ performance.measure(`event:${key}`, `event:${key}:start`, `event:${key}:end`);
603
+ yield* PubSub.publish(this.activation, { event: key, state: 'activated' });
604
+ log('activated', { key });
605
+
606
+ return true;
607
+ }).pipe(
608
+ Effect.ensuring(
609
+ Ref.update(this._activatingModules, (activating) =>
610
+ Array.filter(activating, (module) => !activatingModuleIds.includes(module)),
611
+ ),
612
+ ),
613
+ );
614
+ }
615
+
616
+ private _getModulesForActivation(
617
+ key: string,
618
+ activatingEvents: string[],
619
+ activatingModules: string[],
620
+ ): Plugin.PluginModule[] {
621
+ return this._getInactiveModulesByEvent(key).filter((module) => {
622
+ const allOf = ActivationEvent.isAllOf(module.activatesOn);
623
+ if (!allOf) {
624
+ return true;
625
+ }
626
+
627
+ // Check to see if all of the events in the `allOf` have been fired.
628
+ // An event can be considered "fired" if it is in the `eventsFired` list or if it is currently being activated.
629
+ const events = ActivationEvent.getEvents(module.activatesOn).filter(
630
+ (event) => ActivationEvent.eventKey(event) !== key,
631
+ );
632
+ return (
633
+ events.every(
634
+ (event) =>
635
+ this._get(this._eventsFiredAtom).includes(ActivationEvent.eventKey(event)) ||
636
+ activatingEvents.includes(ActivationEvent.eventKey(event)),
637
+ ) && !activatingModules.includes(module.id)
638
+ );
639
+ });
640
+ }
641
+
642
+ private _getBeforeEvents(
643
+ modules: Plugin.PluginModule[],
644
+ activatingEvents: string[],
645
+ ): ActivationEvent.ActivationEvent[] {
646
+ return Function.pipe(
647
+ modules,
648
+ Array.flatMap((module) => module.activatesBefore ?? []),
649
+ HashSet.fromIterable,
650
+ HashSet.toValues,
651
+ Array.filter((event) => !activatingEvents.includes(ActivationEvent.eventKey(event))),
652
+ );
653
+ }
654
+
655
+ private _getAfterEvents(
656
+ modules: Plugin.PluginModule[],
657
+ activatingEvents: string[],
658
+ ): ActivationEvent.ActivationEvent[] {
659
+ return Function.pipe(
660
+ modules,
661
+ Array.flatMap((module) => module.activatesAfter ?? []),
662
+ HashSet.fromIterable,
663
+ HashSet.toValues,
664
+ Array.filter((event) => !activatingEvents.includes(ActivationEvent.eventKey(event))),
665
+ );
666
+ }
667
+
668
+ private _activateRelatedEvents(
669
+ key: string,
670
+ events: ActivationEvent.ActivationEvent[],
671
+ phase: 'before' | 'after',
672
+ ): Effect.Effect<void, Error> {
673
+ const logLabel = phase === 'before' ? 'activatesBefore' : 'activatesAfter';
674
+ const eventKey = phase === 'before' ? 'beforeEvents' : 'afterEvents';
675
+ return Function.pipe(
676
+ events,
677
+ Array.map((event) => this.activate(event, phase === 'before' ? { before: key } : { after: key })),
678
+ Effect.allWith({ concurrency: 'unbounded' }),
679
+ together(
680
+ Effect.sleep(Duration.seconds(10)).pipe(
681
+ Effect.andThen(
682
+ Effect.sync(() =>
683
+ log.warn(`${logLabel} is taking a long time`, {
684
+ event: key,
685
+ [eventKey]: events.map(ActivationEvent.eventKey),
686
+ }),
687
+ ),
688
+ ),
689
+ ),
690
+ ),
691
+ Effect.asVoid,
692
+ );
693
+ }
694
+
695
+ //
696
+ // Module lifecycle helpers
697
+ //
698
+
699
+ private _loadCapabilitiesForModules(
700
+ key: string,
701
+ modules: Plugin.PluginModule[],
702
+ ): Effect.Effect<Capability.Any[][], Error> {
703
+ return Function.pipe(
704
+ modules,
705
+ Array.map((mod) => this._loadModule(mod)),
706
+ Effect.allWith({ concurrency: 'unbounded' }),
707
+ Effect.catchAll((error) => {
708
+ return Effect.gen(this, function* () {
709
+ yield* PubSub.publish(this.activation, { event: key, state: 'error', error });
710
+ return yield* Effect.fail(error);
711
+ });
712
+ }),
713
+ );
714
+ }
715
+
716
+ private _contributeCapabilitiesForModules(
717
+ modules: Plugin.PluginModule[],
718
+ capabilities: Capability.Any[][],
719
+ ): Effect.Effect<void, Error> {
720
+ return Function.pipe(
721
+ modules,
722
+ Array.zip(capabilities),
723
+ Array.map(([module, capabilitySet]) => this._contributeCapabilities(module, capabilitySet)),
724
+ // TODO(wittjosiah): This currently can't be run in parallel.
725
+ // Running this with concurrency causes races with `allOf` activation events.
726
+ Effect.all,
727
+ Effect.asVoid,
728
+ );
729
+ }
730
+
563
731
  private _getModuleSemaphore(moduleId: Plugin.PluginModule['id']): Effect.Semaphore {
564
732
  let semaphore = this._moduleSemaphores.get(moduleId);
565
733
  if (!semaphore) {
@@ -586,6 +754,8 @@ class ManagerImpl implements PluginManager {
586
754
 
587
755
  const loadEffect = Effect.gen(this, function* () {
588
756
  log('loading module', { module: module.id });
757
+ performance.mark(`module:${module.id}:start`);
758
+ yield* PubSub.publish(this.activation, { event: '', state: 'activating', module: module.id });
589
759
  const [duration, capabilities] = yield* module
590
760
  .activate()
591
761
  .pipe(
@@ -594,9 +764,13 @@ class ManagerImpl implements PluginManager {
594
764
  Effect.timed,
595
765
  );
596
766
  const normalized = capabilities == null ? [] : Array.isArray(capabilities) ? capabilities : [capabilities];
767
+ const elapsed = Duration.toMillis(duration);
768
+ performance.mark(`module:${module.id}:end`);
769
+ performance.measure(`module:${module.id}`, `module:${module.id}:start`, `module:${module.id}:end`);
770
+ yield* PubSub.publish(this.activation, { event: '', state: 'activated', module: module.id });
597
771
  log('loaded module', {
598
772
  module: module.id,
599
- elapsed: Duration.toMillis(duration),
773
+ elapsed,
600
774
  failed: false,
601
775
  });
602
776
  return normalized as Capability.Any[];
@@ -609,10 +783,19 @@ class ManagerImpl implements PluginManager {
609
783
  ),
610
784
  ),
611
785
  ),
786
+ Performance.addTrackEntry({
787
+ name: module.id,
788
+ devtools: {
789
+ dataType: 'track-entry',
790
+ track: 'Module Activation',
791
+ trackGroup: 'Composer',
792
+ color: 'primary',
793
+ },
794
+ }),
612
795
  );
613
796
 
614
797
  // Fork the load to run in background, completing the deferred when done.
615
- yield* Effect.forkDaemon(
798
+ const fiber = yield* Effect.forkDaemon(
616
799
  loadEffect.pipe(
617
800
  Effect.tap((result) => Deferred.succeed(deferred, result)),
618
801
  Effect.catchAllCause((cause) => {
@@ -627,6 +810,10 @@ class ManagerImpl implements PluginManager {
627
810
  }),
628
811
  ),
629
812
  );
813
+ yield* this._trackFiber(this._inFlightFibers, fiber);
814
+ yield* Effect.forkDaemon(
815
+ Fiber.await(fiber).pipe(Effect.andThen(() => this._untrackFiber(this._inFlightFibers, fiber))),
816
+ );
630
817
 
631
818
  return deferred;
632
819
  }).pipe(semaphore.withPermits(1));
@@ -45,11 +45,18 @@ export const activate = (event: ActivationEvent.ActivationEvent): Effect.Effect<
45
45
  export const reset = (event: ActivationEvent.ActivationEvent): Effect.Effect<boolean, Error, Service> =>
46
46
  Effect.flatMap(Service, (manager) => manager.reset(event));
47
47
 
48
+ /**
49
+ * Shuts down the plugin manager, deactivating all active modules and clearing lifecycle state.
50
+ * Accesses the PluginManager via the Effect layer system.
51
+ */
52
+ export const shutdown = (): Effect.Effect<boolean, Error, Service> =>
53
+ Effect.flatMap(Service, (manager) => manager.shutdown());
54
+
48
55
  /**
49
56
  * Computes a module ID from plugin ID and export name.
50
57
  */
51
58
  const computeModuleId = (pluginId: string, moduleName: string): string => {
52
- return `${pluginId}/module/${moduleName}`;
59
+ return `${pluginId}.module.${moduleName}`;
53
60
  };
54
61
 
55
62
  /**
@@ -128,7 +135,7 @@ export type Meta = {
128
135
  *
129
136
  * Expected to be in the form of a valid URL.
130
137
  *
131
- * @example dxos.org/plugin/example
138
+ * @example org.dxos.plugin.example
132
139
  */
133
140
  id: string;
134
141
 
@@ -190,6 +197,7 @@ export const isPlugin = (value: unknown): value is Plugin => {
190
197
  * A collection of modules that are be enabled/disabled as a unit.
191
198
  * Plugins provide things such as components, state, actions, etc. to the application.
192
199
  */
200
+ // TODO(burdon): Convert to ECHO schema.
193
201
  export interface Plugin {
194
202
  readonly [PluginTypeId]: PluginTypeId;
195
203
  readonly meta: Readonly<Meta>;