@dxos/app-framework 0.8.4-main.c85a9c8dae → 0.8.4-main.cb12b3f963
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.
- package/dist/lib/browser/{capability-7RLVE42K.mjs → capability-5RRH3WIB.mjs} +11 -10
- package/dist/lib/browser/capability-5RRH3WIB.mjs.map +7 -0
- package/dist/lib/browser/{capability-2GL5JAGJ.mjs → capability-LUKGKUQH.mjs} +10 -9
- package/dist/lib/browser/{chunk-5RJNZV7K.mjs → chunk-23D4SJUE.mjs} +11 -13
- package/dist/lib/browser/{chunk-5RJNZV7K.mjs.map → chunk-23D4SJUE.mjs.map} +3 -3
- package/dist/lib/browser/{chunk-YNFPIQGB.mjs → chunk-3JWJXGLK.mjs} +5 -2
- package/dist/lib/browser/chunk-3JWJXGLK.mjs.map +7 -0
- package/dist/lib/browser/chunk-45CHLTBV.mjs +34 -0
- package/dist/lib/browser/chunk-45CHLTBV.mjs.map +7 -0
- package/dist/lib/browser/{chunk-PKQT6C53.mjs → chunk-66IXTIVK.mjs} +3 -2
- package/dist/lib/browser/chunk-66IXTIVK.mjs.map +7 -0
- package/dist/lib/browser/chunk-CZ4BIAHH.mjs +422 -0
- package/dist/lib/browser/chunk-CZ4BIAHH.mjs.map +7 -0
- package/dist/lib/browser/chunk-FJ4765WW.mjs +8 -0
- package/dist/lib/browser/{chunk-FHQTHCX7.mjs.map → chunk-FJ4765WW.mjs.map} +3 -3
- package/dist/lib/browser/chunk-FO3IYSLV.mjs +68 -0
- package/dist/lib/browser/chunk-FO3IYSLV.mjs.map +7 -0
- package/dist/lib/browser/chunk-MX5DKEJH.mjs +584 -0
- package/dist/lib/browser/chunk-MX5DKEJH.mjs.map +7 -0
- package/dist/lib/browser/chunk-NBXPP7JR.mjs +1174 -0
- package/dist/lib/browser/chunk-NBXPP7JR.mjs.map +7 -0
- package/dist/lib/browser/chunk-PC4NOADA.mjs +471 -0
- package/dist/lib/browser/chunk-PC4NOADA.mjs.map +7 -0
- package/dist/lib/browser/{chunk-REORGDJT.mjs → chunk-WBHCSOBW.mjs} +18 -18
- package/dist/lib/browser/chunk-WBHCSOBW.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FNKT2QQ2.mjs → chunk-Z55LVAGN.mjs} +85 -17
- package/dist/lib/browser/chunk-Z55LVAGN.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ZRWBPIZG.mjs → chunk-ZGJAZSNE.mjs} +9 -37
- package/dist/lib/browser/chunk-ZGJAZSNE.mjs.map +7 -0
- package/dist/lib/browser/cli/index.mjs +16 -29
- package/dist/lib/browser/cli/index.mjs.map +3 -3
- package/dist/lib/browser/common/activation-events.mjs +9 -8
- package/dist/lib/browser/common/capabilities.mjs +9 -8
- package/dist/lib/browser/core/activation-event.mjs +1 -1
- package/dist/lib/browser/core/capability.mjs +3 -1
- package/dist/lib/browser/core/plugin-manager.mjs +8 -4
- package/dist/lib/browser/core/plugin.mjs +14 -4
- package/dist/lib/browser/core/url-loader.mjs +24 -0
- package/dist/lib/browser/index.mjs +37 -22
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{invoker-capability-BNLVNYHU.mjs → invoker-capability-K4GHUFXF.mjs} +22 -14
- package/dist/lib/browser/invoker-capability-K4GHUFXF.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +184 -49
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/browser/testing/react.mjs +78 -0
- package/dist/lib/browser/testing/react.mjs.map +7 -0
- package/dist/lib/browser/ui/index.mjs +18 -15
- package/dist/lib/node-esm/{capability-CHIMU6LX.mjs → capability-FCGZVIEG.mjs} +10 -9
- package/dist/lib/{browser/capability-2GL5JAGJ.mjs.map → node-esm/capability-FCGZVIEG.mjs.map} +1 -1
- package/dist/lib/node-esm/{capability-EVZK4REM.mjs → capability-JOIQ2MQE.mjs} +11 -10
- package/dist/lib/node-esm/capability-JOIQ2MQE.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-UEWJDI2L.mjs → chunk-37Z53PXZ.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-UEWJDI2L.mjs.map → chunk-37Z53PXZ.mjs.map} +3 -3
- package/dist/lib/node-esm/chunk-42J2ZUQQ.mjs +472 -0
- package/dist/lib/node-esm/chunk-42J2ZUQQ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-6XW6LET6.mjs +35 -0
- package/dist/lib/node-esm/chunk-6XW6LET6.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-2A4PRBIX.mjs → chunk-D347W3KO.mjs} +9 -37
- package/dist/lib/node-esm/chunk-D347W3KO.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-CJCQS2YL.mjs → chunk-HTBJU5FX.mjs} +85 -17
- package/dist/lib/node-esm/chunk-HTBJU5FX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-M3HKPRPO.mjs +423 -0
- package/dist/lib/node-esm/chunk-M3HKPRPO.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-MUVUQC3G.mjs +1175 -0
- package/dist/lib/node-esm/chunk-MUVUQC3G.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-VUIUFIGT.mjs → chunk-SBS2YMPT.mjs} +11 -13
- package/dist/lib/node-esm/{chunk-VUIUFIGT.mjs.map → chunk-SBS2YMPT.mjs.map} +3 -3
- package/dist/lib/node-esm/{chunk-SB5ODNPX.mjs → chunk-SDJ4B2LU.mjs} +5 -2
- package/dist/lib/node-esm/chunk-SDJ4B2LU.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-UFW652GS.mjs → chunk-WFSRZKBP.mjs} +18 -18
- package/dist/lib/node-esm/chunk-WFSRZKBP.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-WK7OIQKI.mjs +70 -0
- package/dist/lib/node-esm/chunk-WK7OIQKI.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-WKTLE7MG.mjs +585 -0
- package/dist/lib/node-esm/chunk-WKTLE7MG.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-7OWSHPYK.mjs → chunk-XOCUANHO.mjs} +3 -2
- package/dist/lib/node-esm/chunk-XOCUANHO.mjs.map +7 -0
- package/dist/lib/node-esm/cli/index.mjs +16 -29
- package/dist/lib/node-esm/cli/index.mjs.map +3 -3
- package/dist/lib/node-esm/common/activation-events.mjs +9 -8
- package/dist/lib/node-esm/common/capabilities.mjs +9 -8
- package/dist/lib/node-esm/core/activation-event.mjs +1 -1
- package/dist/lib/node-esm/core/capability.mjs +3 -1
- package/dist/lib/node-esm/core/plugin-manager.mjs +8 -4
- package/dist/lib/node-esm/core/plugin.mjs +14 -4
- package/dist/lib/node-esm/core/url-loader.mjs +25 -0
- package/dist/lib/node-esm/index.mjs +37 -22
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{invoker-capability-VF6SP44V.mjs → invoker-capability-XEPW5LMJ.mjs} +22 -14
- package/dist/lib/node-esm/invoker-capability-XEPW5LMJ.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +184 -49
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/lib/node-esm/testing/react.mjs +79 -0
- package/dist/lib/node-esm/testing/react.mjs.map +7 -0
- package/dist/lib/node-esm/ui/index.mjs +18 -15
- package/dist/plugin/node-esm/index.mjs +875 -0
- package/dist/plugin/node-esm/index.mjs.map +7 -0
- package/dist/plugin/node-esm/meta.json +1 -0
- package/dist/types/src/common/activation-events.d.ts +1 -1
- package/dist/types/src/common/activation-events.d.ts.map +1 -1
- package/dist/types/src/common/annotations.d.ts +1 -0
- package/dist/types/src/common/annotations.d.ts.map +1 -0
- package/dist/types/src/common/capabilities.d.ts +4 -8
- package/dist/types/src/common/capabilities.d.ts.map +1 -1
- package/dist/types/src/common/operations.d.ts +8 -22
- package/dist/types/src/common/operations.d.ts.map +1 -1
- package/dist/types/src/core/activation-event.d.ts +5 -5
- package/dist/types/src/core/activation-event.d.ts.map +1 -1
- package/dist/types/src/core/capability-manager.d.ts +5 -0
- package/dist/types/src/core/capability-manager.d.ts.map +1 -1
- package/dist/types/src/core/capability.d.ts +8 -2
- package/dist/types/src/core/capability.d.ts.map +1 -1
- package/dist/types/src/core/edge-registry-plugin-provider.d.ts +30 -0
- package/dist/types/src/core/edge-registry-plugin-provider.d.ts.map +1 -0
- package/dist/types/src/core/index.d.ts +6 -0
- package/dist/types/src/core/index.d.ts.map +1 -1
- package/dist/types/src/core/plugin-asset-cache.d.ts +71 -0
- package/dist/types/src/core/plugin-asset-cache.d.ts.map +1 -0
- package/dist/types/src/core/plugin-manager.d.ts +177 -4
- package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manifest.d.ts +101 -0
- package/dist/types/src/core/plugin-manifest.d.ts.map +1 -0
- package/dist/types/src/core/plugin-manifest.test.d.ts +2 -0
- package/dist/types/src/core/plugin-manifest.test.d.ts.map +1 -0
- package/dist/types/src/core/plugin.d.ts +113 -7
- package/dist/types/src/core/plugin.d.ts.map +1 -1
- package/dist/types/src/core/registry.d.ts +101 -0
- package/dist/types/src/core/registry.d.ts.map +1 -0
- package/dist/types/src/core/url-loader.d.ts +127 -0
- package/dist/types/src/core/url-loader.d.ts.map +1 -0
- package/dist/types/src/core/url-loader.test.d.ts +2 -0
- package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
- package/dist/types/src/helpers.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/OperationPlugin.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/history/capability.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/history/errors.d.ts +30 -3
- package/dist/types/src/plugin-operation/history/errors.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/history/history-tracker.d.ts +1 -1
- package/dist/types/src/plugin-operation/history/history-tracker.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/history/types.d.ts +1 -1
- package/dist/types/src/plugin-operation/history/types.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/history/undo-mapping.d.ts +1 -1
- package/dist/types/src/plugin-operation/history/undo-mapping.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/history/undo-registry.d.ts +1 -1
- package/dist/types/src/plugin-operation/history/undo-registry.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/invoker-capability.d.ts +1 -1
- package/dist/types/src/plugin-operation/invoker-capability.d.ts.map +1 -1
- package/dist/types/src/plugin-operation/testing.d.ts +27 -77
- package/dist/types/src/plugin-operation/testing.d.ts.map +1 -1
- package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts.map +1 -1
- package/dist/types/src/plugin-runtime/capability.d.ts +1 -1
- package/dist/types/src/plugin-runtime/capability.d.ts.map +1 -1
- package/dist/types/src/testing/harness.d.ts +67 -0
- package/dist/types/src/testing/harness.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/react.d.ts +27 -0
- package/dist/types/src/testing/react.d.ts.map +1 -0
- package/dist/types/src/testing/react.test.d.ts +2 -0
- package/dist/types/src/testing/react.test.d.ts.map +1 -0
- package/dist/types/src/testing/service.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/App/App.d.ts +3 -2
- package/dist/types/src/ui/components/App/App.d.ts.map +1 -1
- package/dist/types/src/ui/components/App/App.stories.d.ts +2 -2
- package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts +64 -0
- package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts.map +1 -0
- package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts +19 -0
- package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts.map +1 -0
- package/dist/types/src/ui/components/Placeholder/index.d.ts +2 -0
- package/dist/types/src/ui/components/Placeholder/index.d.ts.map +1 -0
- package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +16 -4
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
- package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/index.d.ts +22 -6
- package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/types.d.ts +110 -9
- package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/types.test.d.ts +2 -0
- package/dist/types/src/ui/components/Surface/types.test.d.ts.map +1 -0
- package/dist/types/src/ui/components/index.d.ts +1 -0
- package/dist/types/src/ui/components/index.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/index.d.ts +0 -1
- package/dist/types/src/ui/hooks/index.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useApp.d.ts +43 -4
- package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
- package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
- package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -1
- package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts +34 -0
- package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/boot-loader/index.d.ts +52 -0
- package/dist/types/src/vite-plugin/boot-loader/index.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/composer/index.d.ts +34 -0
- package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/import-map/index.d.ts +28 -0
- package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/index.d.ts +5 -0
- package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/manifest.d.ts +41 -0
- package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/manifest.test.d.ts +2 -0
- package/dist/types/src/vite-plugin/manifest.test.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/packages.d.ts +13 -0
- package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/moon.yml +15 -0
- package/package.json +48 -53
- package/src/cli/cli.ts +3 -3
- package/src/common/activation-events.ts +6 -6
- package/src/common/annotations.ts +3 -0
- package/src/common/capabilities.ts +18 -23
- package/src/common/operations.ts +7 -10
- package/src/context.ts +1 -1
- package/src/core/activation-event.ts +5 -2
- package/src/core/capability-manager.test.ts +1 -1
- package/src/core/capability-manager.ts +22 -1
- package/src/core/capability.ts +13 -2
- package/src/core/edge-registry-plugin-provider.ts +92 -0
- package/src/core/index.ts +6 -0
- package/src/core/plugin-asset-cache.ts +60 -0
- package/src/core/plugin-manager.test.ts +855 -29
- package/src/core/plugin-manager.ts +808 -188
- package/src/core/plugin-manifest.test.ts +75 -0
- package/src/core/plugin-manifest.ts +134 -0
- package/src/core/plugin.ts +144 -12
- package/src/core/registry.ts +157 -0
- package/src/core/url-loader.test.ts +221 -0
- package/src/core/url-loader.ts +388 -0
- package/src/plugin-operation/OperationPlugin.ts +2 -3
- package/src/plugin-operation/history/capability.ts +1 -2
- package/src/plugin-operation/history/errors.ts +2 -6
- package/src/plugin-operation/history/history-tracker.test.ts +37 -43
- package/src/plugin-operation/history/history-tracker.ts +1 -2
- package/src/plugin-operation/history/types.ts +1 -1
- package/src/plugin-operation/history/undo-mapping.ts +1 -1
- package/src/plugin-operation/history/undo-registry.test.ts +3 -4
- package/src/plugin-operation/history/undo-registry.ts +1 -1
- package/src/plugin-operation/invoker-capability.ts +19 -4
- package/src/plugin-operation/meta.ts +1 -1
- package/src/plugin-operation/testing.ts +26 -45
- package/src/plugin-runtime/RuntimePlugin.ts +2 -3
- package/src/plugin-runtime/meta.ts +1 -1
- package/src/testing/harness.ts +229 -0
- package/src/testing/index.ts +1 -0
- package/src/testing/react.test.tsx +48 -0
- package/src/testing/react.tsx +113 -0
- package/src/testing/service.ts +3 -3
- package/src/testing/withPluginManager.stories.tsx +1 -2
- package/src/testing/withPluginManager.tsx +40 -18
- package/src/ui/components/App/App.stories.tsx +5 -5
- package/src/ui/components/App/App.tsx +29 -5
- package/src/ui/components/Placeholder/Placeholder.stories.tsx +77 -0
- package/src/ui/components/Placeholder/Placeholder.tsx +155 -0
- package/src/ui/components/Placeholder/index.ts +5 -0
- package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +8 -6
- package/src/ui/components/Surface/SurfaceComponent.stories.tsx +16 -15
- package/src/ui/components/Surface/SurfaceComponent.tsx +109 -53
- package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
- package/src/ui/components/Surface/index.ts +35 -1
- package/src/ui/components/Surface/types.test.ts +126 -0
- package/src/ui/components/Surface/types.ts +164 -12
- package/src/ui/components/index.ts +1 -0
- package/src/ui/hooks/index.ts +0 -1
- package/src/ui/hooks/useApp.test.tsx +159 -0
- package/src/ui/hooks/useApp.tsx +226 -15
- package/src/ui/hooks/useLoading.tsx +14 -6
- package/src/vite-plugin/boot-loader/BootLoader.stories.tsx +263 -0
- package/src/vite-plugin/boot-loader/boot-loader.css +294 -0
- package/src/vite-plugin/boot-loader/boot-loader.js +274 -0
- package/src/vite-plugin/boot-loader/index.ts +112 -0
- package/src/vite-plugin/composer/index.ts +306 -0
- package/src/vite-plugin/import-map/index.ts +524 -0
- package/src/vite-plugin/index.ts +10 -0
- package/src/vite-plugin/manifest.test.ts +46 -0
- package/src/vite-plugin/manifest.ts +57 -0
- package/src/vite-plugin/packages.ts +188 -0
- package/tsconfig.json +19 -1
- package/tsconfig.node.json +1 -1
- package/vitest.config.ts +1 -1
- package/.swc/plugins/linux_x86_64_19.0.0/727453fb3a62f7f1d952a41e051ca8a6f88cadc45cee43c6a4d1aa45f9b75665.wasmer-v7 +0 -0
- package/dist/lib/browser/capability-7RLVE42K.mjs.map +0 -7
- package/dist/lib/browser/chunk-4CTRO67U.mjs +0 -703
- package/dist/lib/browser/chunk-4CTRO67U.mjs.map +0 -7
- package/dist/lib/browser/chunk-FHQTHCX7.mjs +0 -8
- package/dist/lib/browser/chunk-FNKT2QQ2.mjs.map +0 -7
- package/dist/lib/browser/chunk-HE27PNNQ.mjs +0 -824
- package/dist/lib/browser/chunk-HE27PNNQ.mjs.map +0 -7
- package/dist/lib/browser/chunk-NPUEVX42.mjs +0 -34
- package/dist/lib/browser/chunk-NPUEVX42.mjs.map +0 -7
- package/dist/lib/browser/chunk-PKQT6C53.mjs.map +0 -7
- package/dist/lib/browser/chunk-REORGDJT.mjs.map +0 -7
- package/dist/lib/browser/chunk-YAFEA4GV.mjs +0 -1
- package/dist/lib/browser/chunk-YNFPIQGB.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZRWBPIZG.mjs.map +0 -7
- package/dist/lib/browser/invoker-capability-BNLVNYHU.mjs.map +0 -7
- package/dist/lib/node-esm/capability-EVZK4REM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2A4PRBIX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-7CPNAEGV.mjs +0 -704
- package/dist/lib/node-esm/chunk-7CPNAEGV.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-7OWSHPYK.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-CJCQS2YL.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-DTCHT2X2.mjs +0 -825
- package/dist/lib/node-esm/chunk-DTCHT2X2.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JAZVHID3.mjs +0 -35
- package/dist/lib/node-esm/chunk-JAZVHID3.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SB5ODNPX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-UFW652GS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-Z4TJPSMP.mjs +0 -2
- package/dist/lib/node-esm/invoker-capability-VF6SP44V.mjs.map +0 -7
- package/dist/types/src/ui/hooks/useOperationResolver.d.ts +0 -19
- package/dist/types/src/ui/hooks/useOperationResolver.d.ts.map +0 -1
- package/src/ui/hooks/useOperationResolver.ts +0 -40
- /package/dist/lib/{node-esm/capability-CHIMU6LX.mjs.map → browser/capability-LUKGKUQH.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-YAFEA4GV.mjs.map → core/url-loader.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-Z4TJPSMP.mjs.map → core/url-loader.mjs.map} +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { assert, describe, it } from '@effect/vitest';
|
|
6
|
+
import { render, waitFor } from '@testing-library/react';
|
|
7
|
+
import * as Effect from 'effect/Effect';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
import { ActivationEvents, Capabilities } from '../../common';
|
|
11
|
+
import { Capability, Plugin, PluginManager } from '../../core';
|
|
12
|
+
import { useApp } from './useApp';
|
|
13
|
+
|
|
14
|
+
const String = Capability.make<{ string: string }>('org.dxos.test.string');
|
|
15
|
+
const testMeta = { id: 'org.dxos.plugin.test', name: 'Test' };
|
|
16
|
+
|
|
17
|
+
const pluginLoader = (plugins: Plugin.Plugin[]) =>
|
|
18
|
+
Effect.fn(function* (id: string) {
|
|
19
|
+
const plugin = plugins.find((plugin) => plugin.meta.id === id);
|
|
20
|
+
if (!plugin) {
|
|
21
|
+
return yield* Effect.fail(new Error(`Plugin not found: ${id}`));
|
|
22
|
+
}
|
|
23
|
+
return { plugin };
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const TestHost = ({ manager }: { manager: PluginManager.PluginManager }) => {
|
|
27
|
+
const App = useApp({ pluginManager: manager });
|
|
28
|
+
return <App />;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
describe('useApp cleanup integration', () => {
|
|
32
|
+
it.effect('external manager is not shut down when useApp does not own it', () =>
|
|
33
|
+
Effect.gen(function* () {
|
|
34
|
+
const plugin = Plugin.define(testMeta).pipe(
|
|
35
|
+
Plugin.addModule({
|
|
36
|
+
id: 'Hello',
|
|
37
|
+
activatesOn: ActivationEvents.Startup,
|
|
38
|
+
activate: () => Effect.succeed(Capability.contributes(String, { string: 'hello' })),
|
|
39
|
+
}),
|
|
40
|
+
Plugin.make,
|
|
41
|
+
)();
|
|
42
|
+
|
|
43
|
+
const manager = PluginManager.make({
|
|
44
|
+
pluginLoader: pluginLoader([plugin]),
|
|
45
|
+
plugins: [plugin],
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
manager.capabilities.contribute({
|
|
49
|
+
interface: Capabilities.PluginManager,
|
|
50
|
+
implementation: manager,
|
|
51
|
+
module: 'org.dxos.app-framework.plugin-manager',
|
|
52
|
+
});
|
|
53
|
+
manager.capabilities.contribute({
|
|
54
|
+
interface: Capabilities.AtomRegistry,
|
|
55
|
+
implementation: manager.registry,
|
|
56
|
+
module: 'org.dxos.app-framework.atom-registry',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const view = yield* Effect.promise(() => Promise.resolve(render(<TestHost manager={manager} />)));
|
|
60
|
+
yield* Effect.promise(() =>
|
|
61
|
+
waitFor(() => {
|
|
62
|
+
assert.strictEqual(manager.capabilities.getAll(Capabilities.PluginManager).length, 1);
|
|
63
|
+
assert.strictEqual(manager.capabilities.getAll(Capabilities.AtomRegistry).length, 1);
|
|
64
|
+
assert.strictEqual(manager.capabilities.getAll(String).length, 1);
|
|
65
|
+
assert.isTrue(manager.getActive().length > 0);
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
yield* Effect.promise(() => Promise.resolve(view.unmount()));
|
|
70
|
+
yield* Effect.promise(() =>
|
|
71
|
+
waitFor(() => {
|
|
72
|
+
assert.strictEqual(manager.capabilities.getAll(Capabilities.PluginManager).length, 1);
|
|
73
|
+
assert.strictEqual(manager.capabilities.getAll(Capabilities.AtomRegistry).length, 1);
|
|
74
|
+
assert.strictEqual(manager.capabilities.getAll(String).length, 1);
|
|
75
|
+
assert.isTrue(manager.getActive().length > 0);
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
yield* manager.shutdown();
|
|
80
|
+
|
|
81
|
+
assert.strictEqual(manager.capabilities.getAll(Capabilities.PluginManager).length, 1);
|
|
82
|
+
assert.strictEqual(manager.capabilities.getAll(Capabilities.AtomRegistry).length, 1);
|
|
83
|
+
assert.strictEqual(manager.capabilities.getAll(String).length, 0);
|
|
84
|
+
assert.deepStrictEqual(manager.getActive(), []);
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
it.effect('shutdown deactivates modules and clears bookkeeping', () =>
|
|
89
|
+
Effect.gen(function* () {
|
|
90
|
+
const plugin = Plugin.define(testMeta).pipe(
|
|
91
|
+
Plugin.addModule({
|
|
92
|
+
id: 'Hello',
|
|
93
|
+
activatesOn: ActivationEvents.Startup,
|
|
94
|
+
activate: () => Effect.succeed(Capability.contributes(String, { string: 'hello' })),
|
|
95
|
+
}),
|
|
96
|
+
Plugin.make,
|
|
97
|
+
)();
|
|
98
|
+
|
|
99
|
+
const manager = PluginManager.make({
|
|
100
|
+
pluginLoader: pluginLoader([plugin]),
|
|
101
|
+
plugins: [plugin],
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
manager.capabilities.contribute({
|
|
105
|
+
interface: Capabilities.PluginManager,
|
|
106
|
+
implementation: manager,
|
|
107
|
+
module: 'org.dxos.app-framework.plugin-manager',
|
|
108
|
+
});
|
|
109
|
+
manager.capabilities.contribute({
|
|
110
|
+
interface: Capabilities.AtomRegistry,
|
|
111
|
+
implementation: manager.registry,
|
|
112
|
+
module: 'org.dxos.app-framework.atom-registry',
|
|
113
|
+
});
|
|
114
|
+
yield* manager.activate(ActivationEvents.Startup);
|
|
115
|
+
|
|
116
|
+
assert.strictEqual(manager.capabilities.getAll(String).length, 1);
|
|
117
|
+
assert.isTrue(manager.getActive().length > 0);
|
|
118
|
+
|
|
119
|
+
yield* manager.shutdown();
|
|
120
|
+
|
|
121
|
+
assert.strictEqual(manager.capabilities.getAll(String).length, 0);
|
|
122
|
+
assert.deepStrictEqual(manager.getActive(), []);
|
|
123
|
+
assert.deepStrictEqual(manager.getEventsFired(), []);
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
it.effect('shutdown is idempotent when called multiple times', () =>
|
|
128
|
+
Effect.gen(function* () {
|
|
129
|
+
const plugin = Plugin.define(testMeta).pipe(
|
|
130
|
+
Plugin.addModule({
|
|
131
|
+
id: 'Hello',
|
|
132
|
+
activatesOn: ActivationEvents.Startup,
|
|
133
|
+
activate: () => Effect.succeed(Capability.contributes(String, { string: 'hello' })),
|
|
134
|
+
}),
|
|
135
|
+
Plugin.make,
|
|
136
|
+
)();
|
|
137
|
+
|
|
138
|
+
const manager = PluginManager.make({
|
|
139
|
+
pluginLoader: pluginLoader([plugin]),
|
|
140
|
+
plugins: [plugin],
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
manager.capabilities.contribute({
|
|
144
|
+
interface: Capabilities.PluginManager,
|
|
145
|
+
implementation: manager,
|
|
146
|
+
module: 'org.dxos.app-framework.plugin-manager',
|
|
147
|
+
});
|
|
148
|
+
yield* manager.activate(ActivationEvents.Startup);
|
|
149
|
+
|
|
150
|
+
yield* manager.shutdown();
|
|
151
|
+
assert.deepStrictEqual(manager.getActive(), []);
|
|
152
|
+
|
|
153
|
+
// Second shutdown should succeed without error.
|
|
154
|
+
const result = yield* manager.shutdown();
|
|
155
|
+
assert.isTrue(result);
|
|
156
|
+
assert.deepStrictEqual(manager.getActive(), []);
|
|
157
|
+
}),
|
|
158
|
+
);
|
|
159
|
+
});
|
package/src/ui/hooks/useApp.tsx
CHANGED
|
@@ -21,11 +21,54 @@ import { PluginManagerContext } from '../../context';
|
|
|
21
21
|
import { type ActivationEvent, type Plugin, PluginManager } from '../../core';
|
|
22
22
|
import { App, PluginManagerProvider } from '../components';
|
|
23
23
|
|
|
24
|
-
const ENABLED_KEY = 'dxos.
|
|
24
|
+
const ENABLED_KEY = 'org.dxos.app-framework.enabled';
|
|
25
|
+
|
|
26
|
+
export type StartupProgress = {
|
|
27
|
+
/** Number of modules that have been activated. */
|
|
28
|
+
activated: number;
|
|
29
|
+
/** Total number of modules registered. */
|
|
30
|
+
total: number;
|
|
31
|
+
/** Fractional progress (0-1). */
|
|
32
|
+
progress: number;
|
|
33
|
+
/**
|
|
34
|
+
* Raw activation event key (e.g. `org.dxos.app-framework.event.startup`).
|
|
35
|
+
* Set on event-level transitions, *and* on module-level transitions where
|
|
36
|
+
* it carries the parent activation event that first triggered the
|
|
37
|
+
* module's load (plumbed through `_loadCapabilitiesForModules` →
|
|
38
|
+
* `_loadModule`). Consumers can use this either as the primary id (when
|
|
39
|
+
* {@link module} is absent) or as an extra "context" field alongside
|
|
40
|
+
* {@link module}.
|
|
41
|
+
*/
|
|
42
|
+
event?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Raw module id (e.g. `org.dxos.plugin.observability.module.ReactSurface`)
|
|
45
|
+
* when the in-flight activation is module-level. When present,
|
|
46
|
+
* {@link event} may also be set, identifying the parent activation that
|
|
47
|
+
* triggered this module's load.
|
|
48
|
+
*/
|
|
49
|
+
module?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Pre-humanized label for the currently surfaced transition (module
|
|
52
|
+
* label if {@link module} is set, otherwise the event label), supplied
|
|
53
|
+
* for consumers that want a sensible default. Hosts that prefer to
|
|
54
|
+
* render their own label can read the raw {@link event}/{@link module}
|
|
55
|
+
* fields and ignore this — the framework leaves the policy choice
|
|
56
|
+
* (which transitions to surface, how to format them, whether to drop
|
|
57
|
+
* sub-modules entirely) to the host's `Placeholder`.
|
|
58
|
+
*/
|
|
59
|
+
humanizedName?: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type PlaceholderProps = {
|
|
63
|
+
stage?: number;
|
|
64
|
+
progress?: StartupProgress;
|
|
65
|
+
};
|
|
25
66
|
|
|
26
67
|
export type UseAppOptions = {
|
|
27
68
|
pluginManager?: PluginManager.PluginManager;
|
|
28
69
|
pluginLoader?: PluginManager.ManagerOptions['pluginLoader'];
|
|
70
|
+
onPluginRemove?: PluginManager.ManagerOptions['onRemove'];
|
|
71
|
+
pluginRegistryProvider?: PluginManager.ManagerOptions['pluginRegistryProvider'];
|
|
29
72
|
plugins?: Plugin.Plugin[];
|
|
30
73
|
core?: string[];
|
|
31
74
|
defaults?: string[];
|
|
@@ -39,7 +82,7 @@ export type UseAppOptions = {
|
|
|
39
82
|
debounce?: number;
|
|
40
83
|
timeout?: number;
|
|
41
84
|
fallback?: FC<FallbackProps>;
|
|
42
|
-
placeholder?: FC<
|
|
85
|
+
placeholder?: FC<PlaceholderProps>;
|
|
43
86
|
};
|
|
44
87
|
|
|
45
88
|
/**
|
|
@@ -70,6 +113,8 @@ export type UseAppOptions = {
|
|
|
70
113
|
export const useApp = ({
|
|
71
114
|
pluginManager,
|
|
72
115
|
pluginLoader: pluginLoaderProp,
|
|
116
|
+
onPluginRemove,
|
|
117
|
+
pluginRegistryProvider,
|
|
73
118
|
plugins: pluginsProp,
|
|
74
119
|
core: coreProp,
|
|
75
120
|
defaults: defaultsProp,
|
|
@@ -86,7 +131,6 @@ export const useApp = ({
|
|
|
86
131
|
const defaults = useDefaultValue(defaultsProp, () => []);
|
|
87
132
|
const setupEvents = useDefaultValue(setupEventsProp, () => []);
|
|
88
133
|
|
|
89
|
-
// TODO(wittjosiah): Provide a custom plugin loader which supports loading via url.
|
|
90
134
|
const pluginLoader = useMemo(
|
|
91
135
|
() =>
|
|
92
136
|
pluginLoaderProp ??
|
|
@@ -94,7 +138,7 @@ export const useApp = ({
|
|
|
94
138
|
Effect.sync(() => {
|
|
95
139
|
const plugin = plugins.find((plugin) => plugin.meta.id === id);
|
|
96
140
|
invariant(plugin, `Plugin not found: ${id}`);
|
|
97
|
-
return plugin;
|
|
141
|
+
return { plugin };
|
|
98
142
|
})),
|
|
99
143
|
[pluginLoaderProp, plugins],
|
|
100
144
|
);
|
|
@@ -103,16 +147,32 @@ export const useApp = ({
|
|
|
103
147
|
const [ready, setReady] = useState(false);
|
|
104
148
|
const errorRef = useRef<unknown>(null);
|
|
105
149
|
const [error, setError] = useState<unknown>(null);
|
|
150
|
+
const [startupProgress, setStartupProgress] = useState<StartupProgress>({
|
|
151
|
+
activated: 0,
|
|
152
|
+
total: 0,
|
|
153
|
+
progress: 0,
|
|
154
|
+
});
|
|
106
155
|
// TODO(wittjosiah): Migrate to Atom.kvs for isomorphic storage.
|
|
107
156
|
const cached: string[] = useMemo(() => JSON.parse(localStorage.getItem(ENABLED_KEY) ?? '[]'), []);
|
|
108
157
|
const enabled = useMemo(
|
|
109
158
|
() => (safeMode ? [] : cacheEnabled && cached.length > 0 ? cached : defaults),
|
|
110
159
|
[safeMode, cacheEnabled, cached, defaults],
|
|
111
160
|
);
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
161
|
+
const isExternalManager = !!pluginManager;
|
|
162
|
+
const manager = useMemo(() => {
|
|
163
|
+
const mgr =
|
|
164
|
+
pluginManager ??
|
|
165
|
+
PluginManager.make({
|
|
166
|
+
pluginLoader,
|
|
167
|
+
plugins,
|
|
168
|
+
core,
|
|
169
|
+
enabled,
|
|
170
|
+
onRemove: onPluginRemove,
|
|
171
|
+
pluginRegistryProvider,
|
|
172
|
+
});
|
|
173
|
+
log('useApp: useMemo created/reused manager', { provided: !!pluginManager });
|
|
174
|
+
return mgr;
|
|
175
|
+
}, [pluginManager, pluginLoader, plugins, core, enabled, onPluginRemove, pluginRegistryProvider]);
|
|
116
176
|
|
|
117
177
|
useEffect(() => {
|
|
118
178
|
if (!cacheEnabled) {
|
|
@@ -128,28 +188,103 @@ export const useApp = ({
|
|
|
128
188
|
}, [manager]);
|
|
129
189
|
|
|
130
190
|
useAsyncEffect(async () => {
|
|
191
|
+
log('useApp: effect mount');
|
|
192
|
+
|
|
131
193
|
manager.capabilities.contribute({
|
|
132
194
|
interface: Capabilities.PluginManager,
|
|
133
195
|
implementation: manager,
|
|
134
|
-
module: 'dxos.
|
|
196
|
+
module: 'org.dxos.app-framework.plugin-manager',
|
|
135
197
|
});
|
|
136
198
|
|
|
137
199
|
manager.capabilities.contribute({
|
|
138
200
|
interface: Capabilities.AtomRegistry,
|
|
139
201
|
implementation: manager.registry,
|
|
140
|
-
module: 'dxos.
|
|
202
|
+
module: 'org.dxos.app-framework.atom-registry',
|
|
141
203
|
});
|
|
142
204
|
|
|
143
205
|
const fiber = Effect.gen(function* () {
|
|
144
206
|
const queue = yield* PubSub.subscribe(manager.activation);
|
|
145
207
|
const listener = yield* Effect.forkDaemon(
|
|
146
208
|
Queue.take(queue).pipe(
|
|
147
|
-
Effect.tap(({ event, state, error: error$ }) =>
|
|
209
|
+
Effect.tap(({ event, state, module, error: error$ }) =>
|
|
148
210
|
Effect.sync(() => {
|
|
149
|
-
|
|
211
|
+
// Event-level Startup activated (no `module` field) fires once,
|
|
212
|
+
// after every module triggered by Startup has finished. Module
|
|
213
|
+
// activations now also carry their parent event id (so the trace
|
|
214
|
+
// can attribute a module to its triggering event), which means
|
|
215
|
+
// each module activated under Startup publishes
|
|
216
|
+
// `{ event: 'startup', state: 'activated', module: <id> }`. Without
|
|
217
|
+
// the `!module` guard the listener would mark the app ready on
|
|
218
|
+
// the *first* such module rather than waiting for the event-level
|
|
219
|
+
// completion — leaving downstream capabilities (operation-invoker,
|
|
220
|
+
// app-graph, …) un-registered when the placeholder dismisses.
|
|
221
|
+
if (event === ActivationEvents.Startup.id && state === 'activated' && !module) {
|
|
150
222
|
clearTimeout(timeoutId);
|
|
151
223
|
setReady(true);
|
|
152
224
|
readyRef.current = true;
|
|
225
|
+
// Trigger startup profiler dump if available.
|
|
226
|
+
(globalThis as any).composer?.profiler?.dump();
|
|
227
|
+
// Notify any host observability layer that startup completed.
|
|
228
|
+
// A `CustomEvent` keeps this generic — app-framework doesn't
|
|
229
|
+
// import a provider, and consumers can capture the startup
|
|
230
|
+
// summary without us picking one.
|
|
231
|
+
if (typeof window !== 'undefined') {
|
|
232
|
+
window.dispatchEvent(new CustomEvent('app-framework:startup-activated'));
|
|
233
|
+
}
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
// `activating` is the start-of-load signal. Surface the raw
|
|
237
|
+
// `module` (or `event`) plus a pre-humanized label so the
|
|
238
|
+
// host placeholder can decide what to render — show
|
|
239
|
+
// everything, suppress noisy sub-modules, group by plugin,
|
|
240
|
+
// or apply its own formatting. We intentionally do NOT touch
|
|
241
|
+
// these fields on `activated`: pairing the two would cause
|
|
242
|
+
// back-to-back identical updates to the host's effect, which
|
|
243
|
+
// the boot loader treats as a re-trigger because
|
|
244
|
+
// `progress.progress` moved. Leaving the label alone on
|
|
245
|
+
// completion keeps it accurate ("now activating X") until
|
|
246
|
+
// the next module starts.
|
|
247
|
+
if (module && state === 'activating' && !readyRef.current) {
|
|
248
|
+
setStartupProgress((current) => ({
|
|
249
|
+
...current,
|
|
250
|
+
// `event` here is the activation event that first
|
|
251
|
+
// triggered this module load (plumbed through
|
|
252
|
+
// `_loadCapabilitiesForModules` → `_loadModule`).
|
|
253
|
+
// Falsy/empty falls back to undefined so consumers can
|
|
254
|
+
// tell "no parent context" from "parent context: <X>".
|
|
255
|
+
event: event || undefined,
|
|
256
|
+
module,
|
|
257
|
+
humanizedName: humanizeModuleId(module),
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
// Update the activation count when a module commits. The
|
|
261
|
+
// ring's fraction comes from this; `event`/`module`/
|
|
262
|
+
// `humanizedName` were set by the matching `activating`
|
|
263
|
+
// message above and are left alone so the count can advance
|
|
264
|
+
// without re-firing the host's status callback.
|
|
265
|
+
if (module && state === 'activated' && !readyRef.current) {
|
|
266
|
+
const active = manager.getActive();
|
|
267
|
+
const total = manager.getModules().length;
|
|
268
|
+
setStartupProgress((current) => ({
|
|
269
|
+
...current,
|
|
270
|
+
activated: active.length,
|
|
271
|
+
total,
|
|
272
|
+
progress: total > 0 ? active.length / total : 0,
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
// Event-level `activating` (no `module`) — fired at the start
|
|
276
|
+
// of `_activateModulesForEvent` and recursively for each
|
|
277
|
+
// before/after event. Surfaces a label during the gap before
|
|
278
|
+
// the first module-level message lands; subsequent module
|
|
279
|
+
// updates immediately overwrite this with a more specific
|
|
280
|
+
// label.
|
|
281
|
+
if (event && !module && state === 'activating' && !readyRef.current) {
|
|
282
|
+
setStartupProgress((current) => ({
|
|
283
|
+
...current,
|
|
284
|
+
event,
|
|
285
|
+
module: undefined,
|
|
286
|
+
humanizedName: humanizeEventKey(event),
|
|
287
|
+
}));
|
|
153
288
|
}
|
|
154
289
|
if (error$ && !readyRef.current) {
|
|
155
290
|
setError(error$);
|
|
@@ -184,20 +319,31 @@ export const useApp = ({
|
|
|
184
319
|
}, timeout);
|
|
185
320
|
|
|
186
321
|
return () => {
|
|
322
|
+
log('useApp: effect cleanup');
|
|
187
323
|
clearTimeout(timeoutId);
|
|
188
324
|
void runAndForwardErrors(Fiber.interrupt(fiber));
|
|
189
|
-
|
|
190
|
-
|
|
325
|
+
if (!isExternalManager) {
|
|
326
|
+
void runAndForwardErrors(manager.shutdown());
|
|
327
|
+
}
|
|
191
328
|
};
|
|
192
329
|
}, [manager]);
|
|
193
330
|
|
|
331
|
+
const progressRef = useRef(startupProgress);
|
|
332
|
+
progressRef.current = startupProgress;
|
|
333
|
+
|
|
194
334
|
return useCallback(
|
|
195
335
|
() => (
|
|
196
336
|
<ErrorBoundary name='app' FallbackComponent={fallback}>
|
|
197
337
|
<PluginManagerProvider value={manager}>
|
|
198
338
|
<ContextProtocolProvider value={manager} context={PluginManagerContext}>
|
|
199
339
|
<RegistryContext.Provider value={manager.registry}>
|
|
200
|
-
<App
|
|
340
|
+
<App
|
|
341
|
+
placeholder={placeholder}
|
|
342
|
+
ready={ready}
|
|
343
|
+
error={error}
|
|
344
|
+
debounce={debounce}
|
|
345
|
+
progress={progressRef.current}
|
|
346
|
+
/>
|
|
201
347
|
</RegistryContext.Provider>
|
|
202
348
|
</ContextProtocolProvider>
|
|
203
349
|
</PluginManagerProvider>
|
|
@@ -211,3 +357,68 @@ const setupDevtools = (manager: PluginManager.PluginManager) => {
|
|
|
211
357
|
(globalThis as any).composer ??= {};
|
|
212
358
|
(globalThis as any).composer.manager = manager;
|
|
213
359
|
};
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Extracts a human-readable label from a module ID.
|
|
363
|
+
*
|
|
364
|
+
* Module IDs follow `org.dxos.plugin.<plugin-slug>.module.<module-name>`,
|
|
365
|
+
* where `<plugin-slug>` is kebab-case and `<module-name>` is either an
|
|
366
|
+
* explicit string (often kebab-case, e.g. `'observability'`, `'namespace'`)
|
|
367
|
+
* or a capability tag in PascalCase from `Capability.getModuleTag(...)`
|
|
368
|
+
* (e.g. `'ReactSurface'`, `'AppGraphBuilder'`). The output is
|
|
369
|
+
* `"Title Case Plugin: kebab-module"` so the visible status names both the
|
|
370
|
+
* plugin and the aspect being activated, helping disambiguate the multiple
|
|
371
|
+
* modules a plugin contributes.
|
|
372
|
+
*
|
|
373
|
+
* Examples:
|
|
374
|
+
* - "org.dxos.plugin.markdown.module.ReactSurface" → "Markdown: react-surface"
|
|
375
|
+
* - "org.dxos.plugin.observability.module.AppGraphBuilder" → "Observability: app-graph-builder"
|
|
376
|
+
* - "org.dxos.plugin.observability.module.observability" → "Observability"
|
|
377
|
+
* (the module name matches the plugin slug — collapsed to avoid
|
|
378
|
+
* "Observability: observability" noise.)
|
|
379
|
+
*/
|
|
380
|
+
const humanizeModuleId = (moduleId: string): string => {
|
|
381
|
+
const match = moduleId.match(/\.plugin\.([^.]+)\.module\.(.+)$/);
|
|
382
|
+
if (!match) {
|
|
383
|
+
// Fallback: use the last segment.
|
|
384
|
+
const parts = moduleId.split('.');
|
|
385
|
+
return parts[parts.length - 1];
|
|
386
|
+
}
|
|
387
|
+
const [, pluginSlug, moduleName] = match;
|
|
388
|
+
const pluginLabel = pluginSlug
|
|
389
|
+
.split('-')
|
|
390
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
391
|
+
.join(' ');
|
|
392
|
+
// Normalise the module name to kebab-case so PascalCase capability tags
|
|
393
|
+
// ("ReactSurface") read consistently with explicit kebab IDs
|
|
394
|
+
// ("operation-handler"). The two-step substitution handles consecutive
|
|
395
|
+
// uppercase runs (`URLLoader` → `url-loader`) without splitting them
|
|
396
|
+
// mid-acronym.
|
|
397
|
+
const moduleLabel = moduleName
|
|
398
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
399
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
|
|
400
|
+
.toLowerCase();
|
|
401
|
+
// Capability modules whose name matches the plugin slug (e.g. the
|
|
402
|
+
// observability plugin's `observability` capability module) would render
|
|
403
|
+
// as "Observability: observability" — drop the redundant suffix.
|
|
404
|
+
if (moduleLabel === pluginSlug) {
|
|
405
|
+
return pluginLabel;
|
|
406
|
+
}
|
|
407
|
+
return `${pluginLabel}: ${moduleLabel}`;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Extracts a human-readable label from an activation event key.
|
|
412
|
+
* E.g., "org.dxos.app-framework.event.setup-react-surface" → "Setup React Surface".
|
|
413
|
+
*/
|
|
414
|
+
const humanizeEventKey = (eventKey: string): string => {
|
|
415
|
+
// Strip a leading specifier (composite key form: "<id>:<specifier>").
|
|
416
|
+
const id = eventKey.split(':')[0];
|
|
417
|
+
// Match the trailing segment after `.event.`.
|
|
418
|
+
const match = id.match(/\.event\.(.+)$/);
|
|
419
|
+
const slug = match ? match[1] : (id.split('.').pop() ?? id);
|
|
420
|
+
return slug
|
|
421
|
+
.split('-')
|
|
422
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
423
|
+
.join(' ');
|
|
424
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { useEffect, useState } from 'react';
|
|
5
|
+
import { useEffect, useRef, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
export enum LoadingState {
|
|
8
8
|
Loading = 0,
|
|
@@ -23,6 +23,14 @@ export enum LoadingState {
|
|
|
23
23
|
*/
|
|
24
24
|
export const useLoading = (ready: boolean, debounce = 0) => {
|
|
25
25
|
const [stage, setStage] = useState<LoadingState>(LoadingState.Loading);
|
|
26
|
+
// Mirror `ready` into a ref so the interval's `setStage` callback can read
|
|
27
|
+
// the latest value without depending on the effect re-running. The pure
|
|
28
|
+
// closure-capture pattern (with `ready` in deps) sticks the FSM at
|
|
29
|
+
// `FadeIn` whenever HMR doesn't propagate the dep change end-to-end —
|
|
30
|
+
// a ref sidesteps that entirely and fires the read on every tick.
|
|
31
|
+
const readyRef = useRef(ready);
|
|
32
|
+
readyRef.current = ready;
|
|
33
|
+
|
|
26
34
|
useEffect(() => {
|
|
27
35
|
if (!debounce) {
|
|
28
36
|
return;
|
|
@@ -30,18 +38,18 @@ export const useLoading = (ready: boolean, debounce = 0) => {
|
|
|
30
38
|
|
|
31
39
|
const i = setInterval(() => {
|
|
32
40
|
setStage((stage) => {
|
|
41
|
+
const isReady = readyRef.current;
|
|
33
42
|
switch (stage) {
|
|
34
43
|
case LoadingState.Loading: {
|
|
35
|
-
if (!
|
|
44
|
+
if (!isReady) {
|
|
36
45
|
return LoadingState.FadeIn;
|
|
37
|
-
} else {
|
|
38
|
-
clearInterval(i);
|
|
39
|
-
return LoadingState.Done;
|
|
40
46
|
}
|
|
47
|
+
clearInterval(i);
|
|
48
|
+
return LoadingState.Done;
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
case LoadingState.FadeIn: {
|
|
44
|
-
if (
|
|
52
|
+
if (isReady) {
|
|
45
53
|
return LoadingState.FadeOut;
|
|
46
54
|
}
|
|
47
55
|
break;
|