@dxos/app-framework 0.8.4-main.9be5663bfe → 0.8.4-main.abd8ff62ef

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 (278) hide show
  1. package/dist/lib/browser/{capability-BBBBAPDI.mjs → capability-Q5XRXRD2.mjs} +10 -10
  2. package/dist/lib/browser/{capability-OP63CD5N.mjs → capability-V7LR4LQN.mjs} +11 -11
  3. package/dist/lib/browser/capability-V7LR4LQN.mjs.map +7 -0
  4. package/dist/lib/browser/{chunk-T3Y4AEKX.mjs → chunk-23D4SJUE.mjs} +3 -3
  5. package/dist/lib/browser/{chunk-T3Y4AEKX.mjs.map → chunk-23D4SJUE.mjs.map} +1 -1
  6. package/dist/lib/browser/{chunk-2CKCJ6PN.mjs → chunk-3JWJXGLK.mjs} +1 -1
  7. package/dist/lib/browser/{chunk-2CKCJ6PN.mjs.map → chunk-3JWJXGLK.mjs.map} +1 -1
  8. package/dist/lib/browser/{chunk-GX4TUNM6.mjs → chunk-3ZS2A3DN.mjs} +170 -226
  9. package/dist/lib/browser/chunk-3ZS2A3DN.mjs.map +7 -0
  10. package/dist/lib/browser/{chunk-I34GF4NG.mjs → chunk-45CHLTBV.mjs} +2 -2
  11. package/dist/lib/browser/chunk-5LAIGWLU.mjs +467 -0
  12. package/dist/lib/browser/chunk-5LAIGWLU.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-QSXYHXCE.mjs → chunk-66IXTIVK.mjs} +1 -1
  14. package/dist/lib/browser/{chunk-QSXYHXCE.mjs.map → chunk-66IXTIVK.mjs.map} +2 -2
  15. package/dist/lib/browser/{chunk-TGX63LTL.mjs → chunk-FJ4765WW.mjs} +1 -1
  16. package/dist/lib/browser/{chunk-TGX63LTL.mjs.map → chunk-FJ4765WW.mjs.map} +2 -2
  17. package/dist/lib/browser/chunk-G7SDBRKH.mjs +1 -0
  18. package/dist/lib/browser/chunk-JXCBZSBJ.mjs +372 -0
  19. package/dist/lib/browser/chunk-JXCBZSBJ.mjs.map +7 -0
  20. package/dist/lib/browser/chunk-MX5DKEJH.mjs +584 -0
  21. package/dist/lib/browser/chunk-MX5DKEJH.mjs.map +7 -0
  22. package/dist/lib/browser/{chunk-JKWMHZP6.mjs → chunk-WBHCSOBW.mjs} +2 -2
  23. package/dist/lib/browser/chunk-WBHCSOBW.mjs.map +7 -0
  24. package/dist/lib/browser/{chunk-FU4GAFUQ.mjs → chunk-Z55LVAGN.mjs} +80 -15
  25. package/dist/lib/browser/chunk-Z55LVAGN.mjs.map +7 -0
  26. package/dist/lib/browser/{chunk-F7FW2RK2.mjs → chunk-ZGJAZSNE.mjs} +7 -32
  27. package/dist/lib/browser/chunk-ZGJAZSNE.mjs.map +7 -0
  28. package/dist/lib/browser/cli/index.mjs +11 -27
  29. package/dist/lib/browser/cli/index.mjs.map +2 -2
  30. package/dist/lib/browser/common/activation-events.mjs +7 -7
  31. package/dist/lib/browser/common/capabilities.mjs +7 -7
  32. package/dist/lib/browser/core/activation-event.mjs +1 -1
  33. package/dist/lib/browser/core/capability.mjs +1 -1
  34. package/dist/lib/browser/core/plugin-manager.mjs +6 -4
  35. package/dist/lib/browser/core/plugin.mjs +10 -2
  36. package/dist/lib/browser/core/url-loader.mjs +13 -5
  37. package/dist/lib/browser/index.mjs +22 -18
  38. package/dist/lib/browser/index.mjs.map +3 -3
  39. package/dist/lib/browser/{invoker-capability-H5PPENOC.mjs → invoker-capability-LNX4CGIV.mjs} +12 -11
  40. package/dist/lib/browser/invoker-capability-LNX4CGIV.mjs.map +7 -0
  41. package/dist/lib/browser/meta.json +1 -1
  42. package/dist/lib/browser/testing/index.mjs +144 -27
  43. package/dist/lib/browser/testing/index.mjs.map +4 -4
  44. package/dist/lib/browser/testing/react.mjs +78 -0
  45. package/dist/lib/browser/testing/react.mjs.map +7 -0
  46. package/dist/lib/browser/ui/index.mjs +18 -14
  47. package/dist/lib/node-esm/{capability-AWBEMRYR.mjs → capability-EW5GJCI6.mjs} +10 -10
  48. package/dist/lib/node-esm/{capability-WFEG6CIZ.mjs → capability-YKBMMD53.mjs} +11 -11
  49. package/dist/lib/node-esm/capability-YKBMMD53.mjs.map +7 -0
  50. package/dist/lib/node-esm/{chunk-FKE4Z3D6.mjs → chunk-37Z53PXZ.mjs} +1 -1
  51. package/dist/lib/node-esm/{chunk-FKE4Z3D6.mjs.map → chunk-37Z53PXZ.mjs.map} +2 -2
  52. package/dist/lib/node-esm/{chunk-WZCSOX5Q.mjs → chunk-6XW6LET6.mjs} +2 -2
  53. package/dist/lib/node-esm/{chunk-URWHJQT2.mjs → chunk-D347W3KO.mjs} +7 -32
  54. package/dist/lib/node-esm/chunk-D347W3KO.mjs.map +7 -0
  55. package/dist/lib/node-esm/chunk-D5PO2WXX.mjs +373 -0
  56. package/dist/lib/node-esm/chunk-D5PO2WXX.mjs.map +7 -0
  57. package/dist/lib/node-esm/{chunk-ULUEXB7Q.mjs → chunk-HTBJU5FX.mjs} +80 -15
  58. package/dist/lib/node-esm/chunk-HTBJU5FX.mjs.map +7 -0
  59. package/dist/lib/node-esm/chunk-KM2F6GH6.mjs +468 -0
  60. package/dist/lib/node-esm/chunk-KM2F6GH6.mjs.map +7 -0
  61. package/dist/lib/node-esm/{chunk-EL3R25OQ.mjs → chunk-OZ7DZA5Z.mjs} +1 -1
  62. package/dist/lib/node-esm/{chunk-BCEOLX47.mjs → chunk-Q7XBFII4.mjs} +170 -226
  63. package/dist/lib/node-esm/chunk-Q7XBFII4.mjs.map +7 -0
  64. package/dist/lib/node-esm/{chunk-VKHGNEDB.mjs → chunk-SBS2YMPT.mjs} +3 -3
  65. package/dist/lib/node-esm/{chunk-VKHGNEDB.mjs.map → chunk-SBS2YMPT.mjs.map} +1 -1
  66. package/dist/lib/node-esm/{chunk-42KBWDE4.mjs → chunk-SDJ4B2LU.mjs} +1 -1
  67. package/dist/lib/node-esm/{chunk-42KBWDE4.mjs.map → chunk-SDJ4B2LU.mjs.map} +1 -1
  68. package/dist/lib/node-esm/{chunk-G3RTFSNG.mjs → chunk-WFSRZKBP.mjs} +2 -2
  69. package/dist/lib/node-esm/chunk-WFSRZKBP.mjs.map +7 -0
  70. package/dist/lib/node-esm/chunk-WKTLE7MG.mjs +585 -0
  71. package/dist/lib/node-esm/chunk-WKTLE7MG.mjs.map +7 -0
  72. package/dist/lib/node-esm/{chunk-ZZ7CKK6W.mjs → chunk-XOCUANHO.mjs} +1 -1
  73. package/dist/lib/node-esm/{chunk-ZZ7CKK6W.mjs.map → chunk-XOCUANHO.mjs.map} +2 -2
  74. package/dist/lib/node-esm/cli/index.mjs +11 -27
  75. package/dist/lib/node-esm/cli/index.mjs.map +2 -2
  76. package/dist/lib/node-esm/common/activation-events.mjs +7 -7
  77. package/dist/lib/node-esm/common/capabilities.mjs +7 -7
  78. package/dist/lib/node-esm/core/activation-event.mjs +1 -1
  79. package/dist/lib/node-esm/core/capability.mjs +1 -1
  80. package/dist/lib/node-esm/core/plugin-manager.mjs +6 -4
  81. package/dist/lib/node-esm/core/plugin.mjs +10 -2
  82. package/dist/lib/node-esm/core/url-loader.mjs +13 -5
  83. package/dist/lib/node-esm/index.mjs +22 -18
  84. package/dist/lib/node-esm/index.mjs.map +3 -3
  85. package/dist/lib/node-esm/{invoker-capability-S3ZA527J.mjs → invoker-capability-O4T5PHLA.mjs} +12 -11
  86. package/dist/lib/node-esm/invoker-capability-O4T5PHLA.mjs.map +7 -0
  87. package/dist/lib/node-esm/meta.json +1 -1
  88. package/dist/lib/node-esm/testing/index.mjs +144 -27
  89. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  90. package/dist/lib/node-esm/testing/react.mjs +79 -0
  91. package/dist/lib/node-esm/testing/react.mjs.map +7 -0
  92. package/dist/lib/node-esm/ui/index.mjs +18 -14
  93. package/dist/plugin/node-esm/index.mjs +480 -32
  94. package/dist/plugin/node-esm/index.mjs.map +4 -4
  95. package/dist/plugin/node-esm/meta.json +1 -1
  96. package/dist/types/src/common/capabilities.d.ts +2 -1
  97. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  98. package/dist/types/src/common/operations.d.ts +1 -1
  99. package/dist/types/src/common/operations.d.ts.map +1 -1
  100. package/dist/types/src/core/activation-event.d.ts +4 -4
  101. package/dist/types/src/core/activation-event.d.ts.map +1 -1
  102. package/dist/types/src/core/capability-manager.d.ts.map +1 -1
  103. package/dist/types/src/core/capability.d.ts +2 -2
  104. package/dist/types/src/core/capability.d.ts.map +1 -1
  105. package/dist/types/src/core/index.d.ts +2 -0
  106. package/dist/types/src/core/index.d.ts.map +1 -1
  107. package/dist/types/src/core/plugin-asset-cache.d.ts +71 -0
  108. package/dist/types/src/core/plugin-asset-cache.d.ts.map +1 -0
  109. package/dist/types/src/core/plugin-manager.d.ts +51 -2
  110. package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
  111. package/dist/types/src/core/plugin-manifest.d.ts +76 -0
  112. package/dist/types/src/core/plugin-manifest.d.ts.map +1 -0
  113. package/dist/types/src/core/plugin-manifest.test.d.ts +2 -0
  114. package/dist/types/src/core/plugin-manifest.test.d.ts.map +1 -0
  115. package/dist/types/src/core/plugin.d.ts +107 -6
  116. package/dist/types/src/core/plugin.d.ts.map +1 -1
  117. package/dist/types/src/core/url-loader.d.ts +90 -3
  118. package/dist/types/src/core/url-loader.d.ts.map +1 -1
  119. package/dist/types/src/helpers.d.ts.map +1 -1
  120. package/dist/types/src/plugin-operation/history/capability.d.ts.map +1 -1
  121. package/dist/types/src/plugin-operation/history/errors.d.ts +6 -6
  122. package/dist/types/src/plugin-operation/history/errors.d.ts.map +1 -1
  123. package/dist/types/src/plugin-operation/history/history-tracker.d.ts +1 -1
  124. package/dist/types/src/plugin-operation/history/history-tracker.d.ts.map +1 -1
  125. package/dist/types/src/plugin-operation/history/types.d.ts +1 -1
  126. package/dist/types/src/plugin-operation/history/types.d.ts.map +1 -1
  127. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts +1 -1
  128. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts.map +1 -1
  129. package/dist/types/src/plugin-operation/history/undo-registry.d.ts +1 -1
  130. package/dist/types/src/plugin-operation/history/undo-registry.d.ts.map +1 -1
  131. package/dist/types/src/plugin-operation/invoker-capability.d.ts +1 -1
  132. package/dist/types/src/plugin-operation/invoker-capability.d.ts.map +1 -1
  133. package/dist/types/src/plugin-operation/testing.d.ts +2 -1
  134. package/dist/types/src/plugin-operation/testing.d.ts.map +1 -1
  135. package/dist/types/src/plugin-runtime/capability.d.ts +1 -1
  136. package/dist/types/src/plugin-runtime/capability.d.ts.map +1 -1
  137. package/dist/types/src/testing/harness.d.ts +67 -0
  138. package/dist/types/src/testing/harness.d.ts.map +1 -0
  139. package/dist/types/src/testing/index.d.ts +1 -0
  140. package/dist/types/src/testing/index.d.ts.map +1 -1
  141. package/dist/types/src/testing/react.d.ts +27 -0
  142. package/dist/types/src/testing/react.d.ts.map +1 -0
  143. package/dist/types/src/testing/react.test.d.ts +2 -0
  144. package/dist/types/src/testing/react.test.d.ts.map +1 -0
  145. package/dist/types/src/testing/service.d.ts.map +1 -1
  146. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  147. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  148. package/dist/types/src/ui/components/App/App.d.ts.map +1 -1
  149. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -1
  150. package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts +64 -0
  151. package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts.map +1 -0
  152. package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts +19 -0
  153. package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts.map +1 -0
  154. package/dist/types/src/ui/components/Placeholder/index.d.ts +2 -0
  155. package/dist/types/src/ui/components/Placeholder/index.d.ts.map +1 -0
  156. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -1
  157. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +16 -4
  158. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
  159. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
  160. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -1
  161. package/dist/types/src/ui/components/Surface/index.d.ts +16 -6
  162. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
  163. package/dist/types/src/ui/components/Surface/types.d.ts +110 -9
  164. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
  165. package/dist/types/src/ui/components/Surface/types.test.d.ts +2 -0
  166. package/dist/types/src/ui/components/Surface/types.test.d.ts.map +1 -0
  167. package/dist/types/src/ui/components/index.d.ts +1 -0
  168. package/dist/types/src/ui/components/index.d.ts.map +1 -1
  169. package/dist/types/src/ui/hooks/useApp.d.ts +29 -3
  170. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -1
  171. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
  172. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -1
  173. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -1
  174. package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts +34 -0
  175. package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts.map +1 -0
  176. package/dist/types/src/vite-plugin/boot-loader/index.d.ts +52 -0
  177. package/dist/types/src/vite-plugin/boot-loader/index.d.ts.map +1 -0
  178. package/dist/types/src/vite-plugin/composer/index.d.ts +34 -0
  179. package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -0
  180. package/dist/types/src/vite-plugin/import-map/index.d.ts +28 -0
  181. package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -0
  182. package/dist/types/src/vite-plugin/index.d.ts +4 -2
  183. package/dist/types/src/vite-plugin/index.d.ts.map +1 -1
  184. package/dist/types/src/vite-plugin/manifest.d.ts +37 -0
  185. package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -0
  186. package/dist/types/src/vite-plugin/manifest.test.d.ts +2 -0
  187. package/dist/types/src/vite-plugin/manifest.test.d.ts.map +1 -0
  188. package/dist/types/src/vite-plugin/packages.d.ts +10 -4
  189. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -1
  190. package/dist/types/tsconfig.tsbuildinfo +1 -1
  191. package/moon.yml +1 -0
  192. package/package.json +33 -59
  193. package/src/common/capabilities.ts +2 -1
  194. package/src/common/operations.ts +1 -1
  195. package/src/core/capability.ts +1 -1
  196. package/src/core/index.ts +2 -0
  197. package/src/core/plugin-asset-cache.ts +60 -0
  198. package/src/core/plugin-manager.test.ts +246 -5
  199. package/src/core/plugin-manager.ts +167 -25
  200. package/src/core/plugin-manifest.test.ts +48 -0
  201. package/src/core/plugin-manifest.ts +102 -0
  202. package/src/core/plugin.ts +135 -10
  203. package/src/core/url-loader.test.ts +104 -5
  204. package/src/core/url-loader.ts +226 -37
  205. package/src/plugin-operation/OperationPlugin.ts +2 -2
  206. package/src/plugin-operation/history/capability.ts +1 -1
  207. package/src/plugin-operation/history/history-tracker.test.ts +2 -1
  208. package/src/plugin-operation/history/history-tracker.ts +1 -1
  209. package/src/plugin-operation/history/types.ts +1 -1
  210. package/src/plugin-operation/history/undo-mapping.ts +1 -1
  211. package/src/plugin-operation/history/undo-registry.ts +1 -1
  212. package/src/plugin-operation/invoker-capability.ts +2 -1
  213. package/src/plugin-operation/testing.ts +2 -1
  214. package/src/plugin-runtime/RuntimePlugin.ts +2 -2
  215. package/src/testing/harness.ts +229 -0
  216. package/src/testing/index.ts +1 -0
  217. package/src/testing/react.test.tsx +48 -0
  218. package/src/testing/react.tsx +113 -0
  219. package/src/testing/withPluginManager.stories.tsx +1 -1
  220. package/src/ui/components/App/App.stories.tsx +1 -1
  221. package/src/ui/components/App/App.tsx +25 -2
  222. package/src/ui/components/Placeholder/Placeholder.stories.tsx +77 -0
  223. package/src/ui/components/Placeholder/Placeholder.tsx +155 -0
  224. package/src/ui/components/Placeholder/index.ts +5 -0
  225. package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +4 -2
  226. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +1 -1
  227. package/src/ui/components/Surface/SurfaceComponent.tsx +83 -46
  228. package/src/ui/components/Surface/index.ts +20 -1
  229. package/src/ui/components/Surface/types.test.ts +126 -0
  230. package/src/ui/components/Surface/types.ts +164 -12
  231. package/src/ui/components/index.ts +1 -0
  232. package/src/ui/hooks/useApp.tsx +165 -41
  233. package/src/ui/hooks/useLoading.tsx +14 -6
  234. package/src/vite-plugin/boot-loader/BootLoader.stories.tsx +263 -0
  235. package/src/vite-plugin/boot-loader/boot-loader.css +294 -0
  236. package/src/vite-plugin/boot-loader/boot-loader.js +274 -0
  237. package/src/vite-plugin/boot-loader/index.ts +112 -0
  238. package/src/vite-plugin/composer/index.ts +277 -0
  239. package/src/vite-plugin/import-map/index.ts +524 -0
  240. package/src/vite-plugin/index.ts +6 -2
  241. package/src/vite-plugin/manifest.test.ts +24 -0
  242. package/src/vite-plugin/manifest.ts +50 -0
  243. package/src/vite-plugin/packages.ts +169 -10
  244. package/tsconfig.json +9 -0
  245. package/.swc/plugins/linux_x86_64_19.0.0/727453fb3a62f7f1d952a41e051ca8a6f88cadc45cee43c6a4d1aa45f9b75665.wasmer-v7 +0 -0
  246. package/dist/lib/browser/capability-OP63CD5N.mjs.map +0 -7
  247. package/dist/lib/browser/chunk-F7FW2RK2.mjs.map +0 -7
  248. package/dist/lib/browser/chunk-FU4GAFUQ.mjs.map +0 -7
  249. package/dist/lib/browser/chunk-GX4TUNM6.mjs.map +0 -7
  250. package/dist/lib/browser/chunk-JKWMHZP6.mjs.map +0 -7
  251. package/dist/lib/browser/chunk-LVJW5EFU.mjs +0 -157
  252. package/dist/lib/browser/chunk-LVJW5EFU.mjs.map +0 -7
  253. package/dist/lib/browser/chunk-RFSO3JRG.mjs +0 -1
  254. package/dist/lib/browser/chunk-WPE6AL7I.mjs +0 -905
  255. package/dist/lib/browser/chunk-WPE6AL7I.mjs.map +0 -7
  256. package/dist/lib/browser/invoker-capability-H5PPENOC.mjs.map +0 -7
  257. package/dist/lib/node-esm/capability-WFEG6CIZ.mjs.map +0 -7
  258. package/dist/lib/node-esm/chunk-4A3ZCMI3.mjs +0 -158
  259. package/dist/lib/node-esm/chunk-4A3ZCMI3.mjs.map +0 -7
  260. package/dist/lib/node-esm/chunk-BCEOLX47.mjs.map +0 -7
  261. package/dist/lib/node-esm/chunk-G3RTFSNG.mjs.map +0 -7
  262. package/dist/lib/node-esm/chunk-LQKOTNJW.mjs +0 -906
  263. package/dist/lib/node-esm/chunk-LQKOTNJW.mjs.map +0 -7
  264. package/dist/lib/node-esm/chunk-ULUEXB7Q.mjs.map +0 -7
  265. package/dist/lib/node-esm/chunk-URWHJQT2.mjs.map +0 -7
  266. package/dist/lib/node-esm/invoker-capability-S3ZA527J.mjs.map +0 -7
  267. package/dist/types/src/vite-plugin/composer-plugin.d.ts +0 -18
  268. package/dist/types/src/vite-plugin/composer-plugin.d.ts.map +0 -1
  269. package/dist/types/src/vite-plugin/import-map-plugin.d.ts +0 -16
  270. package/dist/types/src/vite-plugin/import-map-plugin.d.ts.map +0 -1
  271. package/src/vite-plugin/composer-plugin.ts +0 -128
  272. package/src/vite-plugin/import-map-plugin.ts +0 -314
  273. /package/dist/lib/browser/{capability-BBBBAPDI.mjs.map → capability-Q5XRXRD2.mjs.map} +0 -0
  274. /package/dist/lib/browser/{chunk-I34GF4NG.mjs.map → chunk-45CHLTBV.mjs.map} +0 -0
  275. /package/dist/lib/browser/{chunk-RFSO3JRG.mjs.map → chunk-G7SDBRKH.mjs.map} +0 -0
  276. /package/dist/lib/node-esm/{capability-AWBEMRYR.mjs.map → capability-EW5GJCI6.mjs.map} +0 -0
  277. /package/dist/lib/node-esm/{chunk-WZCSOX5Q.mjs.map → chunk-6XW6LET6.mjs.map} +0 -0
  278. /package/dist/lib/node-esm/{chunk-EL3R25OQ.mjs.map → chunk-OZ7DZA5Z.mjs.map} +0 -0
package/moon.yml CHANGED
@@ -20,6 +20,7 @@ tasks:
20
20
  - '--entryPoint=src/common/activation-events.ts'
21
21
  - '--entryPoint=src/ui/index.ts'
22
22
  - '--entryPoint=src/testing/index.ts'
23
+ - '--entryPoint=src/testing/react.tsx'
23
24
  - '--entryPoint=src/core/url-loader.ts'
24
25
  deps:
25
26
  - compile-plugin
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/app-framework",
3
- "version": "0.8.4-main.9be5663bfe",
3
+ "version": "0.8.4-main.abd8ff62ef",
4
4
  "description": "A framework for building applications from composible plugins.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -77,6 +77,12 @@
77
77
  "node": "./dist/lib/node-esm/testing/index.mjs",
78
78
  "types": "./dist/types/src/testing/index.d.ts"
79
79
  },
80
+ "./testing-react": {
81
+ "source": "./src/testing/react.tsx",
82
+ "browser": "./dist/lib/browser/testing/react.mjs",
83
+ "node": "./dist/lib/node-esm/testing/react.mjs",
84
+ "types": "./dist/types/src/testing/react.d.ts"
85
+ },
80
86
  "./ui": {
81
87
  "source": "./src/ui/index.ts",
82
88
  "browser": "./dist/lib/browser/ui/index.mjs",
@@ -85,80 +91,48 @@
85
91
  }
86
92
  },
87
93
  "types": "dist/types/src/index.d.ts",
88
- "typesVersions": {
89
- "*": {
90
- "ActivationEvent": [
91
- "dist/types/src/activation-event/index.d.ts"
92
- ],
93
- "ActivationEvents": [
94
- "dist/types/src/common/activation-events.d.ts"
95
- ],
96
- "Capabilities": [
97
- "dist/types/src/common/capabilities.d.ts"
98
- ],
99
- "Capability": [
100
- "dist/types/src/capability/index.d.ts"
101
- ],
102
- "Plugin": [
103
- "dist/types/src/plugin/index.d.ts"
104
- ],
105
- "PluginManager": [
106
- "dist/types/src/plugin-manager/index.d.ts"
107
- ],
108
- "UrlLoader": [
109
- "dist/types/src/url-loader/index.d.ts"
110
- ],
111
- "vite-plugin": [
112
- "dist/types/src/vite-plugin/index.d.ts"
113
- ],
114
- "cli": [
115
- "dist/types/src/cli/index.d.ts"
116
- ],
117
- "testing": [
118
- "dist/types/src/testing/index.d.ts"
119
- ],
120
- "ui": [
121
- "dist/types/src/ui/index.d.ts"
122
- ]
123
- }
124
- },
125
94
  "dependencies": {
126
95
  "@effect/cli": "0.73.2",
127
96
  "cjs-module-lexer": "^2.2.0",
128
- "@dxos/async": "0.8.4-main.9be5663bfe",
129
- "@dxos/debug": "0.8.4-main.9be5663bfe",
130
- "@dxos/echo": "0.8.4-main.9be5663bfe",
131
- "@dxos/invariant": "0.8.4-main.9be5663bfe",
132
- "@dxos/errors": "0.8.4-main.9be5663bfe",
133
- "@dxos/operation": "0.8.4-main.9be5663bfe",
134
- "@dxos/react-error-boundary": "0.8.4-main.9be5663bfe",
135
- "@dxos/util": "0.8.4-main.9be5663bfe",
136
- "@dxos/log": "0.8.4-main.9be5663bfe",
137
- "@dxos/web-context": "0.8.4-main.9be5663bfe",
138
- "@dxos/react-hooks": "0.8.4-main.9be5663bfe",
139
- "@dxos/web-context-react": "0.8.4-main.9be5663bfe",
140
- "@dxos/effect": "0.8.4-main.9be5663bfe"
97
+ "@dxos/async": "0.8.4-main.abd8ff62ef",
98
+ "@dxos/debug": "0.8.4-main.abd8ff62ef",
99
+ "@dxos/compute": "0.8.4-main.abd8ff62ef",
100
+ "@dxos/effect": "0.8.4-main.abd8ff62ef",
101
+ "@dxos/errors": "0.8.4-main.abd8ff62ef",
102
+ "@dxos/invariant": "0.8.4-main.abd8ff62ef",
103
+ "@dxos/echo": "0.8.4-main.abd8ff62ef",
104
+ "@dxos/log": "0.8.4-main.abd8ff62ef",
105
+ "@dxos/operation": "0.8.4-main.abd8ff62ef",
106
+ "@dxos/protocols": "0.8.4-main.abd8ff62ef",
107
+ "@dxos/react-hooks": "0.8.4-main.abd8ff62ef",
108
+ "@dxos/react-ui": "0.8.4-main.abd8ff62ef",
109
+ "@dxos/web-context": "0.8.4-main.abd8ff62ef",
110
+ "@dxos/ui-theme": "0.8.4-main.abd8ff62ef",
111
+ "@dxos/react-error-boundary": "0.8.4-main.abd8ff62ef",
112
+ "@dxos/web-context-react": "0.8.4-main.abd8ff62ef",
113
+ "@dxos/util": "0.8.4-main.abd8ff62ef"
141
114
  },
142
115
  "devDependencies": {
143
116
  "@effect-atom/atom-react": "^0.5.0",
144
117
  "@effect/platform": "0.94.4",
145
- "@effect/vitest": "0.27.0",
118
+ "@effect/vitest": "0.29.0",
119
+ "@testing-library/react": "^16.3.0",
146
120
  "@types/react": "~19.2.7",
147
121
  "effect": "3.20.0",
148
122
  "react": "~19.2.3",
149
123
  "react-dom": "~19.2.3",
150
124
  "typedoc": "0.28.1",
151
- "vite": "^7.1.11",
152
- "@dxos/echo-db": "0.8.4-main.9be5663bfe",
153
- "@dxos/random": "0.8.4-main.9be5663bfe",
154
- "@dxos/storybook-utils": "0.8.4-main.9be5663bfe",
155
- "@dxos/test-utils": "0.8.4-main.9be5663bfe",
156
- "@dxos/react-ui": "0.8.4-main.9be5663bfe",
157
- "@dxos/ui-theme": "0.8.4-main.9be5663bfe"
125
+ "vite": "^8.0.10",
126
+ "@dxos/brand": "0.8.4-main.abd8ff62ef",
127
+ "@dxos/echo-db": "0.8.4-main.abd8ff62ef",
128
+ "@dxos/storybook-utils": "0.8.4-main.abd8ff62ef",
129
+ "@dxos/random": "0.8.4-main.abd8ff62ef",
130
+ "@dxos/test-utils": "0.8.4-main.abd8ff62ef"
158
131
  },
159
132
  "peerDependencies": {
160
133
  "@effect-atom/atom-react": "^0.5.0",
161
134
  "@effect/platform": "0.94.4",
135
+ "@testing-library/react": "^16.3.0",
162
136
  "effect": "3.20.0",
163
137
  "react": "~19.2.3",
164
138
  "react-dom": "~19.2.3"
@@ -9,7 +9,8 @@ import type * as Layer$ from 'effect/Layer';
9
9
  import type * as ManagedRuntime$ from 'effect/ManagedRuntime';
10
10
  import type { FC, PropsWithChildren } from 'react';
11
11
 
12
- import type { OperationInvoker as OperationInvoker$, OperationHandlerSet } from '@dxos/operation';
12
+ import type { OperationHandlerSet } from '@dxos/compute';
13
+ import { OperationInvoker as OperationInvoker$ } from '@dxos/operation';
13
14
 
14
15
  import { Capability as Capability$, type PluginManager as PluginManager$ } from '../core';
15
16
  import type {
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
- import { Operation } from '@dxos/operation';
7
+ import { Operation } from '@dxos/compute';
8
8
 
9
9
  import { Capability } from '../core';
10
10
  import { Label } from './translations';
@@ -232,7 +232,7 @@ export const getModuleTag = (capability: unknown): string | undefined => {
232
232
  * export default Capability.makeModule(
233
233
  * Effect.fnUntraced(function* (props: { observability: boolean }) {
234
234
  * const invoker = yield* Capability.get(Capabilities.OperationInvoker);
235
- * return contributes(Capabilities.IntentResolver, ...);
235
+ * return contributes(Capabilities.OperationHandler, ...);
236
236
  * })
237
237
  * );
238
238
  * ```
package/src/core/index.ts CHANGED
@@ -6,5 +6,7 @@ export * as ActivationEvent from './activation-event';
6
6
  export * as Capability from './capability';
7
7
  export * as CapabilityManager from './capability-manager';
8
8
  export * as Plugin from './plugin';
9
+ export * as PluginAssetCache from './plugin-asset-cache';
9
10
  export * as PluginManager from './plugin-manager';
11
+ export * as PluginManifest from './plugin-manifest';
10
12
  export * as UrlLoader from './url-loader';
@@ -0,0 +1,60 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { BaseError } from '@dxos/errors';
8
+
9
+ /**
10
+ * Tagged error for cache operations. Construction sites supply `context.operation`
11
+ * (one of `'cache' | 'evict' | 'resolve' | 'list'`) and `context.pluginId` so
12
+ * downstream handlers can route on the failed call without scanning the message.
13
+ */
14
+ export class PluginAssetCacheError extends BaseError.extend(
15
+ 'PluginAssetCacheError',
16
+ 'Plugin asset cache operation failed',
17
+ ) {}
18
+
19
+ /**
20
+ * Per-platform offline cache for third-party plugin assets.
21
+ *
22
+ * Implementations live alongside their platform glue (composer-app's
23
+ * `asset-cache/{tauri,service-worker}.ts`); the no-op default is for tests
24
+ * and unsupported environments.
25
+ */
26
+ export interface Cache {
27
+ /**
28
+ * Persist all listed URLs under the namespace of `pluginId`. Idempotent.
29
+ * The order of `urls` is significant — the first entry is treated as the entry module.
30
+ */
31
+ cache(pluginId: string, urls: readonly string[]): Effect.Effect<void, PluginAssetCacheError>;
32
+
33
+ /**
34
+ * Drop all assets for a plugin (uninstall).
35
+ */
36
+ evict(pluginId: string): Effect.Effect<void, PluginAssetCacheError>;
37
+
38
+ /**
39
+ * Resolves a plugin asset URL to a platform-specific cached URL when one is available.
40
+ * Returns the original URL when no cached copy exists or the platform serves cached
41
+ * responses transparently (e.g. service worker fetch interception on web).
42
+ */
43
+ resolve(pluginId: string, url: string): Effect.Effect<string, PluginAssetCacheError>;
44
+
45
+ /**
46
+ * List currently cached plugin ids (diagnostic).
47
+ */
48
+ list(): Effect.Effect<readonly string[], PluginAssetCacheError>;
49
+ }
50
+
51
+ /**
52
+ * No-op implementation. Used when no platform cache is registered (tests, unsupported environments).
53
+ * Plugins still load — they just have no offline guarantee.
54
+ */
55
+ export const noop = (): Cache => ({
56
+ cache: () => Effect.void,
57
+ evict: () => Effect.void,
58
+ resolve: (_pluginId, url) => Effect.succeed(url),
59
+ list: () => Effect.succeed([] as readonly string[]),
60
+ });
@@ -76,9 +76,10 @@ describe('PluginManager', () => {
76
76
 
77
77
  const manager = PluginManager.make({ pluginLoader });
78
78
  const added = yield* manager.add(testMeta.id);
79
- assert.isTrue(added);
79
+ assert.strictEqual(added, testPlugin);
80
80
  assert.deepStrictEqual(manager.getPlugins(), [testPlugin]);
81
- const removed = manager.remove(testMeta.id);
81
+ assert.deepStrictEqual(manager.getEnabled(), []);
82
+ const removed = yield* manager.remove(testMeta.id);
82
83
  assert.isTrue(removed);
83
84
  assert.deepStrictEqual(manager.getPlugins(), []);
84
85
  }),
@@ -99,8 +100,10 @@ describe('PluginManager', () => {
99
100
 
100
101
  const manager = PluginManager.make({ pluginLoader: urlLoader });
101
102
  const added = yield* manager.add(urlLocator);
102
- assert.isTrue(added);
103
+ assert.strictEqual(added, testPlugin);
103
104
  assert.deepStrictEqual(manager.getPlugins(), [testPlugin]);
105
+ assert.deepStrictEqual(manager.getEnabled(), []);
106
+ yield* manager.enable(added.meta.id);
104
107
  assert.deepStrictEqual(manager.getEnabled(), [testMeta.id]);
105
108
  }),
106
109
  );
@@ -219,6 +222,7 @@ describe('PluginManager', () => {
219
222
 
220
223
  const manager = PluginManager.make({ pluginLoader });
221
224
  yield* manager.add(testMeta.id);
225
+ yield* manager.enable(testMeta.id);
222
226
  const error = yield* Effect.flip(manager.activate(FailEvent));
223
227
  assert.strictEqual(error.message, 'test');
224
228
  }),
@@ -251,6 +255,7 @@ describe('PluginManager', () => {
251
255
 
252
256
  const manager = PluginManager.make({ pluginLoader });
253
257
  yield* manager.add(testMeta.id);
258
+ yield* manager.enable(testMeta.id);
254
259
  const error = yield* Effect.flip(manager.activate(DefectEvent));
255
260
 
256
261
  // Verify the error was caught and propagated.
@@ -297,6 +302,7 @@ describe('PluginManager', () => {
297
302
 
298
303
  const manager = PluginManager.make({ pluginLoader });
299
304
  yield* manager.add(testMeta.id);
305
+ yield* manager.enable(testMeta.id);
300
306
  const error = yield* Effect.flip(manager.activate(DefectEvent));
301
307
 
302
308
  // Verify the error was caught and propagated.
@@ -361,6 +367,7 @@ describe('PluginManager', () => {
361
367
  );
362
368
 
363
369
  yield* manager.add(testMeta.id);
370
+ yield* manager.enable(testMeta.id);
364
371
  yield* manager.activate(ActivationEvents.Startup);
365
372
  yield* activating.await;
366
373
  yield* activated.await;
@@ -411,6 +418,7 @@ describe('PluginManager', () => {
411
418
 
412
419
  {
413
420
  yield* manager.add(testMeta.id);
421
+ yield* manager.enable(testMeta.id);
414
422
  const result = yield* manager.activate(ActivationEvents.Startup);
415
423
  assert.isTrue(result);
416
424
  assert.deepStrictEqual(manager.getActive(), [testPlugin.modules[0].id]);
@@ -475,16 +483,19 @@ describe('PluginManager', () => {
475
483
  assert.strictEqual(manager.capabilities.getAll(Number).length, 0);
476
484
 
477
485
  yield* manager.add(Plugin1.meta.id);
486
+ yield* manager.enable(Plugin1.meta.id);
478
487
  yield* manager.activate(CountEvent);
479
488
  assert.deepStrictEqual(manager.getActive(), [plugin1.modules[0].id]);
480
489
  assert.strictEqual(manager.capabilities.getAll(Number).length, 1);
481
490
 
482
491
  yield* manager.add(Plugin2.meta.id);
492
+ yield* manager.enable(Plugin2.meta.id);
483
493
  yield* manager.activate(CountEvent);
484
494
  assert.deepStrictEqual(manager.getActive(), [plugin1.modules[0].id, plugin2.modules[0].id]);
485
495
  assert.strictEqual(manager.capabilities.getAll(Number).length, 2);
486
496
 
487
497
  yield* manager.add(Plugin3.meta.id);
498
+ yield* manager.enable(Plugin3.meta.id);
488
499
  yield* manager.activate(CountEvent);
489
500
  assert.deepStrictEqual(manager.getActive(), [
490
501
  plugin1.modules[0].id,
@@ -515,6 +526,7 @@ describe('PluginManager', () => {
515
526
  assert.strictEqual(manager.capabilities.getAll(String).length, 0);
516
527
 
517
528
  yield* manager.add(testMeta.id);
529
+ yield* manager.enable(testMeta.id);
518
530
  yield* manager.activate(ActivationEvents.Startup);
519
531
  assert.deepStrictEqual(manager.getActive(), []);
520
532
  assert.strictEqual(manager.capabilities.getAll(String).length, 0);
@@ -548,6 +560,7 @@ describe('PluginManager', () => {
548
560
  assert.strictEqual(count, 0);
549
561
 
550
562
  yield* manager.add(testMeta.id);
563
+ yield* manager.enable(testMeta.id);
551
564
  yield* manager.activate(CountEvent);
552
565
  assert.deepStrictEqual(manager.getActive(), [testPlugin.modules[0].id]);
553
566
  assert.strictEqual(manager.capabilities.getAll(String).length, 1);
@@ -572,7 +585,7 @@ describe('PluginManager', () => {
572
585
  Plugin.addModule({
573
586
  id: 'Count',
574
587
  activatesOn: ActivationEvents.Startup,
575
- activatesBefore: [CountEvent],
588
+ firesBeforeActivation: [CountEvent],
576
589
  activate: Effect.fnUntraced(function* () {
577
590
  const capabilityManager = yield* Capability.Service;
578
591
  computeTotal(capabilityManager);
@@ -607,7 +620,9 @@ describe('PluginManager', () => {
607
620
  const manager = PluginManager.make({ pluginLoader });
608
621
  {
609
622
  yield* manager.add(Test.meta.id);
623
+ yield* manager.enable(Test.meta.id);
610
624
  yield* manager.add(Count.meta.id);
625
+ yield* manager.enable(Count.meta.id);
611
626
  yield* manager.activate(ActivationEvents.Startup);
612
627
  assert.deepStrictEqual(manager.getActive(), [
613
628
  ...testPlugin.modules.map((m) => m.id),
@@ -690,6 +705,7 @@ describe('PluginManager', () => {
690
705
  assert.strictEqual(pendingResetUpdates.count, 0);
691
706
 
692
707
  yield* manager.add(Plugin1.meta.id);
708
+ yield* manager.enable(Plugin1.meta.id);
693
709
  assert.strictEqual(pluginUpdates.count, 1);
694
710
  assert.strictEqual(enabledUpdates.count, 1);
695
711
  assert.strictEqual(modulesUpdates.count, 1);
@@ -706,6 +722,7 @@ describe('PluginManager', () => {
706
722
  assert.strictEqual(pendingResetUpdates.count, 0);
707
723
 
708
724
  yield* manager.add(Plugin2.meta.id);
725
+ yield* manager.enable(Plugin2.meta.id);
709
726
  assert.strictEqual(pluginUpdates.count, 2);
710
727
  assert.strictEqual(enabledUpdates.count, 2);
711
728
  assert.strictEqual(modulesUpdates.count, 2);
@@ -722,6 +739,7 @@ describe('PluginManager', () => {
722
739
  assert.strictEqual(pendingResetUpdates.count, 2);
723
740
 
724
741
  yield* manager.add(Plugin3.meta.id);
742
+ yield* manager.enable(Plugin3.meta.id);
725
743
  assert.strictEqual(pluginUpdates.count, 3);
726
744
  assert.strictEqual(enabledUpdates.count, 3);
727
745
  assert.strictEqual(modulesUpdates.count, 3);
@@ -746,7 +764,7 @@ describe('PluginManager', () => {
746
764
  assert.strictEqual(eventsFiredUpdates.count, 1);
747
765
  assert.strictEqual(pendingResetUpdates.count, 4);
748
766
 
749
- manager.remove(Plugin1.meta.id);
767
+ yield* manager.remove(Plugin1.meta.id);
750
768
  assert.strictEqual(pluginUpdates.count, 4);
751
769
  assert.strictEqual(enabledUpdates.count, 4);
752
770
  assert.strictEqual(modulesUpdates.count, 4);
@@ -793,6 +811,7 @@ describe('PluginManager', () => {
793
811
 
794
812
  const manager = PluginManager.make({ pluginLoader });
795
813
  yield* manager.add(SlowPlugin.meta.id);
814
+ yield* manager.enable(SlowPlugin.meta.id);
796
815
 
797
816
  // Fork the activation so we can control time with TestClock.
798
817
  const activationFiber = yield* Effect.fork(manager.activate(SlowEvent));
@@ -841,6 +860,7 @@ describe('PluginManager', () => {
841
860
 
842
861
  const manager = PluginManager.make({ pluginLoader });
843
862
  yield* manager.add(ConcurrentPlugin.meta.id);
863
+ yield* manager.enable(ConcurrentPlugin.meta.id);
844
864
 
845
865
  // Fork two concurrent activations with DIFFERENT events.
846
866
  // Both events trigger the same module, so both will try to call _loadModule.
@@ -889,7 +909,9 @@ describe('PluginManager', () => {
889
909
 
890
910
  const manager = PluginManager.make({ pluginLoader });
891
911
  yield* manager.add(Plugin1.meta.id);
912
+ yield* manager.enable(Plugin1.meta.id);
892
913
  yield* manager.add(Plugin2.meta.id);
914
+ yield* manager.enable(Plugin2.meta.id);
893
915
  yield* manager.activate(ActivationEvents.Startup);
894
916
  assert.strictEqual(manager.getActive().length, 2);
895
917
  assert.strictEqual(manager.capabilities.getAll(String).length, 1);
@@ -926,6 +948,7 @@ describe('PluginManager', () => {
926
948
 
927
949
  const manager = PluginManager.make({ pluginLoader });
928
950
  yield* manager.add(testMeta.id);
951
+ yield* manager.enable(testMeta.id);
929
952
  yield* manager.activate(ActivationEvents.Startup);
930
953
  assert.isFalse(deactivated);
931
954
 
@@ -971,7 +994,9 @@ describe('PluginManager', () => {
971
994
 
972
995
  const manager = PluginManager.make({ pluginLoader });
973
996
  yield* manager.add(Plugin1.meta.id);
997
+ yield* manager.enable(Plugin1.meta.id);
974
998
  yield* manager.add(Plugin2.meta.id);
999
+ yield* manager.enable(Plugin2.meta.id);
975
1000
  yield* manager.activate(ActivationEvents.Startup);
976
1001
 
977
1002
  yield* manager.shutdown();
@@ -994,6 +1019,7 @@ describe('PluginManager', () => {
994
1019
 
995
1020
  const manager = PluginManager.make({ pluginLoader });
996
1021
  yield* manager.add(testMeta.id);
1022
+ yield* manager.enable(testMeta.id);
997
1023
  yield* manager.activate(ActivationEvents.Startup);
998
1024
  assert.isTrue(manager.getEventsFired().length > 0);
999
1025
 
@@ -1026,6 +1052,7 @@ describe('PluginManager', () => {
1026
1052
 
1027
1053
  const manager = PluginManager.make({ pluginLoader });
1028
1054
  yield* manager.add(testMeta.id);
1055
+ yield* manager.enable(testMeta.id);
1029
1056
 
1030
1057
  const activationFiber = yield* Effect.fork(manager.activate(ActivationEvents.Startup));
1031
1058
  yield* activationStarted.await;
@@ -1062,6 +1089,7 @@ describe('PluginManager', () => {
1062
1089
 
1063
1090
  const manager = PluginManager.make({ pluginLoader });
1064
1091
  yield* manager.add(testMeta.id);
1092
+ yield* manager.enable(testMeta.id);
1065
1093
  yield* manager.activate(ActivationEvents.Startup);
1066
1094
 
1067
1095
  const pluginsBefore = manager.getPlugins();
@@ -1097,6 +1125,7 @@ describe('PluginManager', () => {
1097
1125
 
1098
1126
  const manager = PluginManager.make({ pluginLoader });
1099
1127
  yield* manager.add(testMeta.id);
1128
+ yield* manager.enable(testMeta.id);
1100
1129
  yield* manager.activate(ActivationEvents.Startup);
1101
1130
  assert.strictEqual(activateCount, 1);
1102
1131
  assert.deepStrictEqual(manager.getActive(), [testPlugin.modules[0].id]);
@@ -1110,4 +1139,216 @@ describe('PluginManager', () => {
1110
1139
  assert.strictEqual(manager.capabilities.getAll(String).length, 1);
1111
1140
  }),
1112
1141
  );
1142
+
1143
+ describe('Plugin.lazy', () => {
1144
+ const lazyMeta = { id: 'org.dxos.plugin.lazy', name: 'Lazy' };
1145
+
1146
+ it('exposes meta synchronously without invoking the loader', () => {
1147
+ let loaderCalls = 0;
1148
+ const Real = Plugin.make(Plugin.define<void>(lazyMeta));
1149
+ const LazyTest = Plugin.lazy(lazyMeta, () => {
1150
+ loaderCalls++;
1151
+ return Promise.resolve({ default: Real });
1152
+ });
1153
+
1154
+ assert.strictEqual(LazyTest.meta.id, lazyMeta.id);
1155
+ assert.strictEqual(LazyTest.meta.name, 'Lazy');
1156
+ assert.strictEqual(loaderCalls, 0);
1157
+
1158
+ const stub = LazyTest();
1159
+ assert.strictEqual(stub.meta.id, lazyMeta.id);
1160
+ assert.deepStrictEqual([...stub.modules], []);
1161
+ assert.isTrue(Plugin.isLazy(stub));
1162
+ assert.strictEqual(loaderCalls, 0);
1163
+ });
1164
+
1165
+ it.effect('resolves the loader on enable and registers the real plugin modules', () =>
1166
+ Effect.gen(function* () {
1167
+ let loaderCalls = 0;
1168
+ const Real = Plugin.define(lazyMeta).pipe(
1169
+ Plugin.addModule({
1170
+ id: 'Hello',
1171
+ activatesOn: ActivationEvents.Startup,
1172
+ activate: () => Effect.succeed(Capability.contributes(String, { string: 'hello' })),
1173
+ }),
1174
+ Plugin.make,
1175
+ );
1176
+ const LazyTest = Plugin.lazy(lazyMeta, () => {
1177
+ loaderCalls++;
1178
+ return Promise.resolve({ default: Real });
1179
+ });
1180
+
1181
+ const lazyStub = LazyTest();
1182
+ plugins = [lazyStub];
1183
+
1184
+ const manager = PluginManager.make({ pluginLoader });
1185
+ yield* manager.add(lazyMeta.id);
1186
+ // Loader has not been invoked yet — only meta is exposed.
1187
+ assert.strictEqual(loaderCalls, 0);
1188
+ assert.deepStrictEqual(manager.getModules(), []);
1189
+
1190
+ yield* manager.enable(lazyMeta.id);
1191
+ assert.strictEqual(loaderCalls, 1);
1192
+ // After enable the registered plugin should be the real one (not the stub),
1193
+ // and its modules should be registered with the manager.
1194
+ const registered = manager.getPlugins().find((p) => p.meta.id === lazyMeta.id);
1195
+ assert.isDefined(registered);
1196
+ assert.isFalse(Plugin.isLazy(registered!));
1197
+ assert.strictEqual(registered!.modules.length, 1);
1198
+
1199
+ yield* manager.activate(ActivationEvents.Startup);
1200
+ assert.strictEqual(manager.capabilities.getAll(String).length, 1);
1201
+ }),
1202
+ );
1203
+
1204
+ it.effect('does not invoke the loader if the plugin is never enabled', () =>
1205
+ Effect.gen(function* () {
1206
+ let loaderCalls = 0;
1207
+ const Real = Plugin.make(Plugin.define<void>(lazyMeta));
1208
+ const LazyTest = Plugin.lazy(lazyMeta, () => {
1209
+ loaderCalls++;
1210
+ return Promise.resolve({ default: Real });
1211
+ });
1212
+ const lazyStub = LazyTest();
1213
+ plugins = [lazyStub];
1214
+
1215
+ const manager = PluginManager.make({ pluginLoader });
1216
+ yield* manager.add(lazyMeta.id);
1217
+
1218
+ // Activate an event that has no listeners — the lazy plugin must not load.
1219
+ yield* manager.activate(ActivationEvents.Startup);
1220
+ assert.strictEqual(loaderCalls, 0);
1221
+ }),
1222
+ );
1223
+
1224
+ it.effect('forwards factory options to the real plugin factory', () =>
1225
+ Effect.gen(function* () {
1226
+ type Opts = { greeting: string };
1227
+ const RealFactory = (opts: Opts) =>
1228
+ Plugin.define(lazyMeta).pipe(
1229
+ Plugin.addModule({
1230
+ id: 'Hello',
1231
+ activatesOn: ActivationEvents.Startup,
1232
+ activate: () => Effect.succeed(Capability.contributes(String, { string: opts.greeting })),
1233
+ }),
1234
+ Plugin.make,
1235
+ )(undefined as void);
1236
+
1237
+ const RealFactoryWithMeta = Object.assign(RealFactory, { meta: lazyMeta });
1238
+
1239
+ const LazyTest = Plugin.lazy<Opts>(lazyMeta, () => Promise.resolve({ default: RealFactoryWithMeta }));
1240
+ const lazyStub = LazyTest({ greeting: 'hola' });
1241
+ plugins = [lazyStub];
1242
+
1243
+ const manager = PluginManager.make({ pluginLoader });
1244
+ yield* manager.add(lazyMeta.id);
1245
+ yield* manager.enable(lazyMeta.id);
1246
+ yield* manager.activate(ActivationEvents.Startup);
1247
+
1248
+ const all = manager.capabilities.getAll(String);
1249
+ assert.strictEqual(all.length, 1);
1250
+ assert.strictEqual(all[0].string, 'hola');
1251
+ }),
1252
+ );
1253
+
1254
+ it.effect('wraps loader rejections in a descriptive error', () =>
1255
+ Effect.gen(function* () {
1256
+ const LazyTest = Plugin.lazy(lazyMeta, () =>
1257
+ Promise.reject<{ default: Plugin.PluginFactory }>(new Error('boom')),
1258
+ );
1259
+ const lazyStub = LazyTest();
1260
+ plugins = [lazyStub];
1261
+
1262
+ const manager = PluginManager.make({ pluginLoader });
1263
+ yield* manager.add(lazyMeta.id);
1264
+
1265
+ const exit = yield* Effect.exit(manager.enable(lazyMeta.id));
1266
+ assert.isTrue(Exit.isFailure(exit));
1267
+ if (Exit.isFailure(exit)) {
1268
+ const failure = Cause.failureOption(exit.cause);
1269
+ assert.isTrue(failure._tag === 'Some');
1270
+ if (failure._tag === 'Some') {
1271
+ assert.isTrue(Plugin.LazyPluginError.is(failure.value));
1272
+ assert.strictEqual((failure.value as Plugin.LazyPluginError).context.id, lazyMeta.id);
1273
+ assert.strictEqual((failure.value as Plugin.LazyPluginError).context.reason, 'load-failed');
1274
+ }
1275
+ }
1276
+ }),
1277
+ );
1278
+
1279
+ it.effect('publishes a lazy:<id> error message when resolution fails', () =>
1280
+ Effect.gen(function* () {
1281
+ const LazyTest = Plugin.lazy(lazyMeta, () =>
1282
+ Promise.reject<{ default: Plugin.PluginFactory }>(new Error('boom')),
1283
+ );
1284
+ const lazyStub = LazyTest();
1285
+ plugins = [lazyStub];
1286
+
1287
+ const manager = PluginManager.make({ pluginLoader });
1288
+ // Subscribe first so we don't miss the activating/error pair.
1289
+ const queue = yield* PubSub.subscribe(manager.activation);
1290
+ yield* manager.add(lazyMeta.id);
1291
+ yield* Effect.exit(manager.enable(lazyMeta.id));
1292
+ const messages = yield* Queue.takeAll(queue);
1293
+
1294
+ const errorMessage = [...messages].find((m) => m.module === `lazy:${lazyMeta.id}` && m.state === 'error');
1295
+ assert.isDefined(errorMessage);
1296
+ assert.isDefined(errorMessage!.error);
1297
+ }).pipe(Effect.scoped),
1298
+ );
1299
+
1300
+ it.effect('coalesces concurrent lazy resolutions of the same plugin id', () =>
1301
+ Effect.gen(function* () {
1302
+ let factoryCalls = 0;
1303
+ const Real = (() => {
1304
+ const inner = Plugin.make(
1305
+ Plugin.define<void>(lazyMeta).pipe(
1306
+ Plugin.addModule({
1307
+ id: 'Hello',
1308
+ activatesOn: ActivationEvents.Startup,
1309
+ activate: () => Effect.succeed(Capability.contributes(String, { string: 'hello' })),
1310
+ }),
1311
+ ),
1312
+ );
1313
+ const factory = (() => {
1314
+ factoryCalls++;
1315
+ return inner();
1316
+ }) as Plugin.PluginFactory;
1317
+ return Object.assign(factory, { meta: lazyMeta });
1318
+ })();
1319
+ const LazyTest = Plugin.lazy(lazyMeta, () => Promise.resolve({ default: Real }));
1320
+ const lazyStub = LazyTest();
1321
+ // `manager.enable(id)` is implicitly called twice — once from the
1322
+ // constructor's core/enabled chain, once from our explicit call. With
1323
+ // coalescing, the underlying factory should still run exactly once.
1324
+ plugins = [lazyStub];
1325
+ const manager = PluginManager.make({ pluginLoader, plugins, core: [lazyMeta.id] });
1326
+ yield* manager.enable(lazyMeta.id);
1327
+ assert.strictEqual(factoryCalls, 1);
1328
+ }),
1329
+ );
1330
+
1331
+ it.effect('fails with a tagged error when the factory output is not a Plugin', () =>
1332
+ Effect.gen(function* () {
1333
+ const BadFactory = Object.assign(() => ({ not: 'a plugin' }) as any, { meta: lazyMeta });
1334
+ const LazyTest = Plugin.lazy(lazyMeta, () => Promise.resolve({ default: BadFactory }));
1335
+ const lazyStub = LazyTest();
1336
+ plugins = [lazyStub];
1337
+
1338
+ const manager = PluginManager.make({ pluginLoader });
1339
+ yield* manager.add(lazyMeta.id);
1340
+
1341
+ const exit = yield* Effect.exit(manager.enable(lazyMeta.id));
1342
+ assert.isTrue(Exit.isFailure(exit));
1343
+ if (Exit.isFailure(exit)) {
1344
+ const failure = Cause.failureOption(exit.cause);
1345
+ assert.isTrue(failure._tag === 'Some');
1346
+ if (failure._tag === 'Some') {
1347
+ assert.isTrue(Plugin.LazyPluginError.is(failure.value));
1348
+ assert.strictEqual((failure.value as Plugin.LazyPluginError).context.reason, 'invalid-plugin');
1349
+ }
1350
+ }
1351
+ }),
1352
+ );
1353
+ });
1113
1354
  });