@dxos/app-framework 0.8.4-main.937b3ca → 0.8.4-main.9be5663bfe
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/.storybook/main.mts +1 -3
- package/dist/lib/browser/{capability-7PCNSWBT.mjs → capability-BBBBAPDI.mjs} +16 -11
- package/dist/lib/browser/capability-BBBBAPDI.mjs.map +7 -0
- package/dist/lib/browser/capability-OP63CD5N.mjs +35 -0
- package/dist/lib/browser/capability-OP63CD5N.mjs.map +7 -0
- package/dist/lib/browser/{chunk-6Y7PZV72.mjs → chunk-2CKCJ6PN.mjs} +6 -4
- package/dist/lib/browser/chunk-2CKCJ6PN.mjs.map +7 -0
- package/dist/lib/browser/{chunk-7IQHKD4U.mjs → chunk-F7FW2RK2.mjs} +9 -12
- package/dist/lib/browser/chunk-F7FW2RK2.mjs.map +7 -0
- package/dist/lib/browser/{chunk-TCLLRCS3.mjs → chunk-FU4GAFUQ.mjs} +10 -7
- package/dist/lib/browser/chunk-FU4GAFUQ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FMZN33N4.mjs → chunk-GX4TUNM6.mjs} +343 -187
- package/dist/lib/browser/chunk-GX4TUNM6.mjs.map +7 -0
- package/dist/lib/browser/chunk-I34GF4NG.mjs +34 -0
- package/dist/lib/browser/chunk-I34GF4NG.mjs.map +7 -0
- package/dist/lib/browser/chunk-JKWMHZP6.mjs +80 -0
- package/dist/lib/browser/chunk-JKWMHZP6.mjs.map +7 -0
- package/dist/lib/browser/chunk-LVJW5EFU.mjs +157 -0
- package/dist/lib/browser/chunk-LVJW5EFU.mjs.map +7 -0
- package/dist/lib/browser/{chunk-PKQT6C53.mjs → chunk-QSXYHXCE.mjs} +3 -2
- package/dist/lib/browser/chunk-QSXYHXCE.mjs.map +7 -0
- package/dist/lib/browser/chunk-RFSO3JRG.mjs +1 -0
- package/dist/lib/browser/chunk-T3Y4AEKX.mjs +42 -0
- package/dist/lib/browser/chunk-T3Y4AEKX.mjs.map +7 -0
- package/dist/lib/browser/chunk-TGX63LTL.mjs +8 -0
- package/dist/lib/browser/{chunk-FHQTHCX7.mjs.map → chunk-TGX63LTL.mjs.map} +1 -1
- package/dist/lib/browser/chunk-WPE6AL7I.mjs +905 -0
- package/dist/lib/browser/chunk-WPE6AL7I.mjs.map +7 -0
- package/dist/lib/browser/cli/index.mjs +90 -0
- package/dist/lib/browser/cli/index.mjs.map +7 -0
- package/dist/lib/browser/common/activation-events.mjs +24 -0
- package/dist/lib/browser/common/capabilities.mjs +46 -0
- 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 +4 -4
- package/dist/lib/browser/core/plugin.mjs +6 -4
- package/dist/lib/browser/core/url-loader.mjs +12 -0
- package/dist/lib/browser/index.mjs +40 -131
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/invoker-capability-H5PPENOC.mjs +43 -0
- package/dist/lib/browser/invoker-capability-H5PPENOC.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +56 -34
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/{react → ui}/index.mjs +19 -21
- package/dist/lib/browser/ui/index.mjs.map +7 -0
- package/dist/lib/node-esm/{capability-CFLQ2QQU.mjs → capability-AWBEMRYR.mjs} +16 -11
- package/dist/lib/node-esm/capability-AWBEMRYR.mjs.map +7 -0
- package/dist/lib/node-esm/capability-WFEG6CIZ.mjs +36 -0
- package/dist/lib/node-esm/capability-WFEG6CIZ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-STMXUEPO.mjs → chunk-42KBWDE4.mjs} +6 -4
- package/dist/lib/node-esm/chunk-42KBWDE4.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-4A3ZCMI3.mjs +158 -0
- package/dist/lib/node-esm/chunk-4A3ZCMI3.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-XYQTBFPA.mjs → chunk-BCEOLX47.mjs} +343 -187
- package/dist/lib/node-esm/chunk-BCEOLX47.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-EL3R25OQ.mjs +2 -0
- package/dist/lib/node-esm/chunk-EL3R25OQ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-UEWJDI2L.mjs → chunk-FKE4Z3D6.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-UEWJDI2L.mjs.map → chunk-FKE4Z3D6.mjs.map} +1 -1
- package/dist/lib/node-esm/chunk-G3RTFSNG.mjs +81 -0
- package/dist/lib/node-esm/chunk-G3RTFSNG.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-LQKOTNJW.mjs +906 -0
- package/dist/lib/node-esm/chunk-LQKOTNJW.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-GT6OKM5I.mjs → chunk-ULUEXB7Q.mjs} +10 -7
- package/dist/lib/node-esm/chunk-ULUEXB7Q.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-663A54LQ.mjs → chunk-URWHJQT2.mjs} +9 -12
- package/dist/lib/node-esm/chunk-URWHJQT2.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-VKHGNEDB.mjs +43 -0
- package/dist/lib/node-esm/chunk-VKHGNEDB.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-WZCSOX5Q.mjs +35 -0
- package/dist/lib/node-esm/chunk-WZCSOX5Q.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-7OWSHPYK.mjs → chunk-ZZ7CKK6W.mjs} +3 -2
- package/dist/lib/node-esm/chunk-ZZ7CKK6W.mjs.map +7 -0
- package/dist/lib/node-esm/cli/index.mjs +91 -0
- package/dist/lib/node-esm/cli/index.mjs.map +7 -0
- package/dist/lib/node-esm/common/activation-events.mjs +25 -0
- package/dist/lib/node-esm/common/activation-events.mjs.map +7 -0
- package/dist/lib/node-esm/common/capabilities.mjs +47 -0
- package/dist/lib/node-esm/common/capabilities.mjs.map +7 -0
- 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 +4 -4
- package/dist/lib/node-esm/core/plugin.mjs +6 -4
- package/dist/lib/node-esm/core/url-loader.mjs +13 -0
- package/dist/lib/node-esm/core/url-loader.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +40 -131
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/invoker-capability-S3ZA527J.mjs +44 -0
- package/dist/lib/node-esm/invoker-capability-S3ZA527J.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +56 -34
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/{react → ui}/index.mjs +19 -21
- package/dist/lib/node-esm/ui/index.mjs.map +7 -0
- package/dist/plugin/node-esm/index.mjs +384 -0
- package/dist/plugin/node-esm/index.mjs.map +7 -0
- package/dist/plugin/node-esm/meta.json +1 -0
- package/dist/types/src/{cli.d.ts → cli/cli.d.ts} +2 -2
- package/dist/types/src/cli/cli.d.ts.map +1 -0
- package/dist/types/src/cli/index.d.ts +2 -0
- package/dist/types/src/cli/index.d.ts.map +1 -0
- package/dist/types/src/common/activation-events.d.ts +27 -0
- package/dist/types/src/common/activation-events.d.ts.map +1 -0
- package/dist/types/src/common/capabilities.d.ts +110 -0
- package/dist/types/src/common/capabilities.d.ts.map +1 -0
- package/dist/types/src/common/index.d.ts +4 -9
- package/dist/types/src/common/index.d.ts.map +1 -1
- package/dist/types/src/common/operations.d.ts +8 -369
- package/dist/types/src/common/operations.d.ts.map +1 -1
- package/dist/types/src/common/translations.d.ts +0 -9
- package/dist/types/src/common/translations.d.ts.map +1 -1
- package/dist/types/src/core/activation-event.d.ts +1 -1
- 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 +13 -7
- package/dist/types/src/core/capability.d.ts.map +1 -1
- package/dist/types/src/core/index.d.ts +1 -0
- package/dist/types/src/core/index.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager.d.ts +9 -2
- package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin.d.ts +6 -1
- package/dist/types/src/core/plugin.d.ts.map +1 -1
- package/dist/types/src/core/url-loader.d.ts +25 -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/index.d.ts +1 -3
- package/dist/types/src/index.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 +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.map +1 -1
- package/dist/types/src/plugin-operation/history/undo-mapping.d.ts +11 -3
- package/dist/types/src/plugin-operation/history/undo-mapping.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 +26 -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 +2 -2
- package/dist/types/src/plugin-runtime/capability.d.ts.map +1 -1
- package/dist/types/src/testing/withPluginManager.d.ts +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/{react → ui/components/App}/App.d.ts +3 -2
- package/dist/types/src/ui/components/App/App.d.ts.map +1 -0
- package/dist/types/src/{react/Surface.stories.d.ts → ui/components/App/App.stories.d.ts} +7 -2
- package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -0
- package/dist/types/src/ui/components/App/index.d.ts +2 -0
- package/dist/types/src/ui/components/App/index.d.ts.map +1 -0
- package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -0
- package/dist/types/src/{react → ui/components/PluginManager}/PluginManagerProvider.d.ts +1 -1
- package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -0
- package/dist/types/src/ui/components/PluginManager/index.d.ts +2 -0
- package/dist/types/src/ui/components/PluginManager/index.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +12 -0
- package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -0
- package/dist/types/src/{react/App.stories.d.ts → ui/components/Surface/SurfaceComponent.stories.d.ts} +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -0
- 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/context.d.ts +5 -0
- package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -0
- package/dist/types/src/ui/components/Surface/index.d.ts +26 -0
- package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -0
- package/dist/types/src/{common/surface.d.ts → ui/components/Surface/types.d.ts} +20 -18
- package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -0
- package/dist/types/src/ui/components/index.d.ts +4 -0
- package/dist/types/src/ui/components/index.d.ts.map +1 -0
- package/dist/types/src/ui/hooks/index.d.ts +6 -0
- package/dist/types/src/ui/hooks/index.d.ts.map +1 -0
- package/dist/types/src/{react → ui/hooks}/useApp.d.ts +26 -9
- package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -0
- 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/{react → ui/hooks}/useCapabilities.d.ts +6 -1
- package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -0
- package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -0
- package/dist/types/src/{react/common.d.ts → ui/hooks/useSettingsState.d.ts} +1 -5
- package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -0
- package/dist/types/src/ui/hooks/useSurface.d.ts +3 -0
- package/dist/types/src/ui/hooks/useSurface.d.ts.map +1 -0
- package/dist/types/src/ui/index.d.ts +3 -0
- package/dist/types/src/ui/index.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/composer-plugin.d.ts +18 -0
- package/dist/types/src/vite-plugin/composer-plugin.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/import-map-plugin.d.ts +16 -0
- package/dist/types/src/vite-plugin/import-map-plugin.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/index.d.ts +3 -0
- package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
- package/dist/types/src/vite-plugin/packages.d.ts +7 -0
- package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/moon.yml +20 -6
- package/package.json +91 -64
- package/src/{cli.ts → cli/cli.ts} +10 -10
- package/src/{playground/debug → cli}/index.ts +1 -1
- package/src/common/activation-events.ts +44 -0
- package/src/common/capabilities.ts +172 -0
- package/src/common/index.ts +4 -9
- package/src/common/operations.ts +6 -383
- package/src/common/translations.ts +0 -12
- 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 +21 -10
- package/src/core/index.ts +1 -0
- package/src/core/plugin-manager.test.ts +314 -46
- package/src/core/plugin-manager.ts +344 -157
- package/src/core/plugin.ts +10 -2
- package/src/core/url-loader.test.ts +79 -0
- package/src/core/url-loader.ts +148 -0
- package/src/index.ts +1 -3
- package/src/plugin-operation/OperationPlugin.ts +5 -6
- package/src/plugin-operation/history/capability.ts +5 -6
- package/src/plugin-operation/history/errors.ts +2 -6
- package/src/plugin-operation/history/history-tracker.test.ts +36 -43
- package/src/plugin-operation/history/history-tracker.ts +0 -1
- package/src/plugin-operation/history/undo-mapping.ts +6 -3
- package/src/plugin-operation/history/undo-registry.test.ts +3 -4
- package/src/plugin-operation/invoker-capability.ts +21 -7
- package/src/plugin-operation/meta.ts +1 -1
- package/src/plugin-operation/testing.ts +25 -45
- package/src/plugin-runtime/RuntimePlugin.ts +4 -5
- package/src/plugin-runtime/capability.ts +5 -5
- package/src/plugin-runtime/meta.ts +1 -1
- package/src/testing/service.ts +6 -6
- package/src/testing/withPluginManager.stories.tsx +6 -7
- package/src/testing/withPluginManager.tsx +44 -19
- package/src/ui/components/App/App.stories.tsx +92 -0
- package/src/{react → ui/components/App}/App.tsx +9 -11
- package/src/{playground/layout → ui/components/App}/index.ts +1 -1
- package/src/{react → ui/components/PluginManager}/PluginManagerContext.stories.tsx +13 -14
- package/src/{react → ui/components/PluginManager}/PluginManagerProvider.ts +1 -1
- package/src/ui/components/PluginManager/index.ts +5 -0
- package/src/{react/Surface.stories.tsx → ui/components/Surface/SurfaceComponent.stories.tsx} +31 -28
- package/src/{react/Surface.tsx → ui/components/Surface/SurfaceComponent.tsx} +59 -60
- package/src/{react → ui/components/Surface}/SurfaceInfo.tsx +2 -2
- package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
- package/src/ui/components/Surface/context.ts +12 -0
- package/src/ui/components/Surface/index.ts +35 -0
- package/src/{common/surface.ts → ui/components/Surface/types.ts} +22 -25
- package/src/ui/components/index.ts +7 -0
- package/src/ui/hooks/index.ts +9 -0
- package/src/ui/hooks/useApp.test.tsx +159 -0
- package/src/{react → ui/hooks}/useApp.tsx +110 -30
- package/src/{react → ui/hooks}/useCapabilities.ts +9 -5
- package/src/{react/common.ts → ui/hooks/useSettingsState.ts} +0 -11
- package/src/ui/hooks/useSurface.ts +13 -0
- package/src/ui/index.ts +6 -0
- package/src/vite-plugin/composer-plugin.ts +128 -0
- package/src/vite-plugin/import-map-plugin.ts +314 -0
- package/src/vite-plugin/index.ts +6 -0
- package/src/vite-plugin/packages.ts +29 -0
- package/tsconfig.json +4 -28
- package/tsconfig.node.json +2 -4
- package/typedoc.json +2 -4
- package/vitest.config.ts +1 -1
- package/dist/lib/browser/app-graph-builder-M2VPYQC6.mjs +0 -149
- package/dist/lib/browser/app-graph-builder-M2VPYQC6.mjs.map +0 -7
- package/dist/lib/browser/capability-7PCNSWBT.mjs.map +0 -7
- package/dist/lib/browser/capability-KP3PFEXD.mjs +0 -31
- package/dist/lib/browser/capability-KP3PFEXD.mjs.map +0 -7
- package/dist/lib/browser/chunk-6Y7PZV72.mjs.map +0 -7
- package/dist/lib/browser/chunk-7IQHKD4U.mjs.map +0 -7
- package/dist/lib/browser/chunk-BLQJSGL3.mjs +0 -732
- package/dist/lib/browser/chunk-BLQJSGL3.mjs.map +0 -7
- package/dist/lib/browser/chunk-FHQTHCX7.mjs +0 -8
- package/dist/lib/browser/chunk-FMZN33N4.mjs.map +0 -7
- package/dist/lib/browser/chunk-H4WPA7U7.mjs +0 -77
- package/dist/lib/browser/chunk-H4WPA7U7.mjs.map +0 -7
- package/dist/lib/browser/chunk-PKQT6C53.mjs.map +0 -7
- package/dist/lib/browser/chunk-TCLLRCS3.mjs.map +0 -7
- package/dist/lib/browser/chunk-XYNO72GQ.mjs +0 -746
- package/dist/lib/browser/chunk-XYNO72GQ.mjs.map +0 -7
- package/dist/lib/browser/common/index.mjs +0 -38
- package/dist/lib/browser/invoker-capability-SZRSTHEH.mjs +0 -32
- package/dist/lib/browser/invoker-capability-SZRSTHEH.mjs.map +0 -7
- package/dist/lib/browser/operation-resolver-6MP2MYOY.mjs +0 -64
- package/dist/lib/browser/operation-resolver-6MP2MYOY.mjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-LROHGJEM.mjs +0 -150
- package/dist/lib/node-esm/app-graph-builder-LROHGJEM.mjs.map +0 -7
- package/dist/lib/node-esm/capability-CFLQ2QQU.mjs.map +0 -7
- package/dist/lib/node-esm/capability-RCUNM2M7.mjs +0 -32
- package/dist/lib/node-esm/capability-RCUNM2M7.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-663A54LQ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-6WXBT3EC.mjs +0 -747
- package/dist/lib/node-esm/chunk-6WXBT3EC.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-7OWSHPYK.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GQEBIGKD.mjs +0 -733
- package/dist/lib/node-esm/chunk-GQEBIGKD.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GT6OKM5I.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-STMXUEPO.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XR6NMKEP.mjs +0 -78
- package/dist/lib/node-esm/chunk-XR6NMKEP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XYQTBFPA.mjs.map +0 -7
- package/dist/lib/node-esm/common/index.mjs +0 -39
- package/dist/lib/node-esm/invoker-capability-PNMA5JOS.mjs +0 -33
- package/dist/lib/node-esm/invoker-capability-PNMA5JOS.mjs.map +0 -7
- package/dist/lib/node-esm/operation-resolver-7YWDMTNU.mjs +0 -65
- package/dist/lib/node-esm/operation-resolver-7YWDMTNU.mjs.map +0 -7
- package/dist/types/src/cli.d.ts.map +0 -1
- package/dist/types/src/common/activation-event.d.ts +0 -66
- package/dist/types/src/common/activation-event.d.ts.map +0 -1
- package/dist/types/src/common/capability.d.ts +0 -265
- package/dist/types/src/common/capability.d.ts.map +0 -1
- package/dist/types/src/common/collaboration.d.ts +0 -26
- package/dist/types/src/common/collaboration.d.ts.map +0 -1
- package/dist/types/src/common/file.d.ts +0 -14
- package/dist/types/src/common/file.d.ts.map +0 -1
- package/dist/types/src/common/graph.d.ts +0 -21
- package/dist/types/src/common/graph.d.ts.map +0 -1
- package/dist/types/src/common/plugin.d.ts +0 -201
- package/dist/types/src/common/plugin.d.ts.map +0 -1
- package/dist/types/src/common/surface.d.ts.map +0 -1
- package/dist/types/src/playground/debug/Debug.d.ts +0 -8
- package/dist/types/src/playground/debug/Debug.d.ts.map +0 -1
- package/dist/types/src/playground/debug/index.d.ts +0 -2
- package/dist/types/src/playground/debug/index.d.ts.map +0 -1
- package/dist/types/src/playground/debug/plugin.d.ts +0 -3
- package/dist/types/src/playground/debug/plugin.d.ts.map +0 -1
- package/dist/types/src/playground/generator/Main.d.ts +0 -8
- package/dist/types/src/playground/generator/Main.d.ts.map +0 -1
- package/dist/types/src/playground/generator/Toolbar.d.ts +0 -8
- package/dist/types/src/playground/generator/Toolbar.d.ts.map +0 -1
- package/dist/types/src/playground/generator/generator.d.ts +0 -19
- package/dist/types/src/playground/generator/generator.d.ts.map +0 -1
- package/dist/types/src/playground/generator/index.d.ts +0 -3
- package/dist/types/src/playground/generator/index.d.ts.map +0 -1
- package/dist/types/src/playground/generator/plugin.d.ts +0 -3
- package/dist/types/src/playground/generator/plugin.d.ts.map +0 -1
- package/dist/types/src/playground/layout/Layout.d.ts +0 -10
- package/dist/types/src/playground/layout/Layout.d.ts.map +0 -1
- package/dist/types/src/playground/layout/index.d.ts +0 -2
- package/dist/types/src/playground/layout/index.d.ts.map +0 -1
- package/dist/types/src/playground/layout/plugin.d.ts +0 -3
- package/dist/types/src/playground/layout/plugin.d.ts.map +0 -1
- package/dist/types/src/playground/logger/Toolbar.d.ts +0 -8
- package/dist/types/src/playground/logger/Toolbar.d.ts.map +0 -1
- package/dist/types/src/playground/logger/index.d.ts +0 -2
- package/dist/types/src/playground/logger/index.d.ts.map +0 -1
- package/dist/types/src/playground/logger/plugin.d.ts +0 -3
- package/dist/types/src/playground/logger/plugin.d.ts.map +0 -1
- package/dist/types/src/playground/logger/schema.d.ts +0 -27
- package/dist/types/src/playground/logger/schema.d.ts.map +0 -1
- package/dist/types/src/playground/playground.stories.d.ts +0 -11
- package/dist/types/src/playground/playground.stories.d.ts.map +0 -1
- package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +0 -3
- package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +0 -1
- package/dist/types/src/plugin-settings/actions.d.ts +0 -61
- package/dist/types/src/plugin-settings/actions.d.ts.map +0 -1
- package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -6
- package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
- package/dist/types/src/plugin-settings/index.d.ts +0 -3
- package/dist/types/src/plugin-settings/index.d.ts.map +0 -1
- package/dist/types/src/plugin-settings/meta.d.ts +0 -3
- package/dist/types/src/plugin-settings/meta.d.ts.map +0 -1
- package/dist/types/src/plugin-settings/operation-resolver.d.ts +0 -6
- package/dist/types/src/plugin-settings/operation-resolver.d.ts.map +0 -1
- package/dist/types/src/plugin-settings/translations.d.ts +0 -11
- package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
- package/dist/types/src/react/App.d.ts.map +0 -1
- package/dist/types/src/react/App.stories.d.ts.map +0 -1
- package/dist/types/src/react/DefaultFallback.d.ts +0 -8
- package/dist/types/src/react/DefaultFallback.d.ts.map +0 -1
- package/dist/types/src/react/ErrorBoundary.d.ts +0 -30
- package/dist/types/src/react/ErrorBoundary.d.ts.map +0 -1
- package/dist/types/src/react/PluginManagerContext.stories.d.ts.map +0 -1
- package/dist/types/src/react/PluginManagerProvider.d.ts.map +0 -1
- package/dist/types/src/react/Surface.d.ts +0 -14
- package/dist/types/src/react/Surface.d.ts.map +0 -1
- package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
- package/dist/types/src/react/SurfaceInfo.d.ts.map +0 -1
- package/dist/types/src/react/common.d.ts.map +0 -1
- package/dist/types/src/react/index.d.ts +0 -9
- package/dist/types/src/react/index.d.ts.map +0 -1
- package/dist/types/src/react/types.d.ts +0 -12
- package/dist/types/src/react/types.d.ts.map +0 -1
- package/dist/types/src/react/useApp.d.ts.map +0 -1
- package/dist/types/src/react/useCapabilities.d.ts.map +0 -1
- package/dist/types/src/react/useLoading.d.ts.map +0 -1
- package/dist/types/src/react/useOperationResolver.d.ts +0 -19
- package/dist/types/src/react/useOperationResolver.d.ts.map +0 -1
- package/src/common/activation-event.ts +0 -99
- package/src/common/capability.ts +0 -343
- package/src/common/collaboration.ts +0 -31
- package/src/common/file.ts +0 -22
- package/src/common/graph.ts +0 -30
- package/src/common/plugin.ts +0 -364
- package/src/playground/debug/Debug.tsx +0 -49
- package/src/playground/debug/plugin.ts +0 -16
- package/src/playground/generator/Main.tsx +0 -80
- package/src/playground/generator/Toolbar.tsx +0 -57
- package/src/playground/generator/generator.ts +0 -48
- package/src/playground/generator/index.ts +0 -6
- package/src/playground/generator/plugin.ts +0 -21
- package/src/playground/layout/Layout.tsx +0 -37
- package/src/playground/layout/plugin.ts +0 -18
- package/src/playground/logger/Toolbar.tsx +0 -33
- package/src/playground/logger/index.ts +0 -5
- package/src/playground/logger/plugin.ts +0 -42
- package/src/playground/logger/schema.ts +0 -22
- package/src/playground/playground.stories.tsx +0 -54
- package/src/plugin-settings/SettingsPlugin.ts +0 -19
- package/src/plugin-settings/actions.ts +0 -64
- package/src/plugin-settings/app-graph-builder.ts +0 -140
- package/src/plugin-settings/index.ts +0 -6
- package/src/plugin-settings/meta.ts +0 -10
- package/src/plugin-settings/operation-resolver.ts +0 -55
- package/src/plugin-settings/translations.ts +0 -19
- package/src/react/App.stories.tsx +0 -63
- package/src/react/DefaultFallback.tsx +0 -26
- package/src/react/ErrorBoundary.tsx +0 -56
- package/src/react/index.ts +0 -14
- package/src/react/types.ts +0 -27
- package/src/react/useOperationResolver.ts +0 -40
- /package/dist/lib/{node-esm/react/index.mjs.map → browser/chunk-RFSO3JRG.mjs.map} +0 -0
- /package/dist/lib/{node-esm/common/index.mjs.map → browser/common/activation-events.mjs.map} +0 -0
- /package/dist/lib/browser/{react/index.mjs.map → common/capabilities.mjs.map} +0 -0
- /package/dist/lib/browser/{common/index.mjs.map → core/url-loader.mjs.map} +0 -0
- /package/dist/types/src/{react → ui/components/PluginManager}/PluginManagerContext.stories.d.ts +0 -0
- /package/dist/types/src/{react → ui/components/Surface}/SurfaceInfo.d.ts +0 -0
- /package/dist/types/src/{react → ui/hooks}/useLoading.d.ts +0 -0
- /package/src/{react → ui/hooks}/useLoading.tsx +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { assert, describe, it } from '@effect/vitest';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
|
|
8
|
+
import * as Plugin from './plugin';
|
|
9
|
+
import * as UrlLoader from './url-loader';
|
|
10
|
+
|
|
11
|
+
const testMeta = { id: 'org.dxos.plugin.test', name: 'Test' };
|
|
12
|
+
|
|
13
|
+
describe('UrlLoader', () => {
|
|
14
|
+
describe('make', () => {
|
|
15
|
+
it.effect('resolves built-in plugins by meta.id', () =>
|
|
16
|
+
Effect.gen(function* () {
|
|
17
|
+
const testPlugin = Plugin.make(Plugin.define(testMeta))();
|
|
18
|
+
const loader = UrlLoader.make([testPlugin]);
|
|
19
|
+
const result = yield* loader(testMeta.id);
|
|
20
|
+
assert.strictEqual(result.meta.id, testMeta.id);
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
it.effect('fails for unknown non-URL locator', () =>
|
|
25
|
+
Effect.gen(function* () {
|
|
26
|
+
const loader = UrlLoader.make([]);
|
|
27
|
+
const exit = yield* Effect.exit(loader('not-a-url'));
|
|
28
|
+
assert.isTrue(exit._tag === 'Failure');
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('preload', () => {
|
|
34
|
+
it('returns empty array when storage has no entries', async ({ expect }) => {
|
|
35
|
+
const storage: UrlLoader.Storage = {
|
|
36
|
+
get: () => null,
|
|
37
|
+
set: () => {},
|
|
38
|
+
};
|
|
39
|
+
const result = await UrlLoader.preload({ storage });
|
|
40
|
+
expect(result).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('returns empty array when storage has invalid JSON', async ({ expect }) => {
|
|
44
|
+
const storage: UrlLoader.Storage = {
|
|
45
|
+
get: () => '{{invalid json',
|
|
46
|
+
set: () => {},
|
|
47
|
+
};
|
|
48
|
+
const result = await UrlLoader.preload({ storage });
|
|
49
|
+
expect(result).toEqual([]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('returns empty array when storage contains null', async ({ expect }) => {
|
|
53
|
+
const storage: UrlLoader.Storage = {
|
|
54
|
+
get: () => 'null',
|
|
55
|
+
set: () => {},
|
|
56
|
+
};
|
|
57
|
+
const result = await UrlLoader.preload({ storage });
|
|
58
|
+
expect(result).toEqual([]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('returns empty array when storage contains an object', async ({ expect }) => {
|
|
62
|
+
const storage: UrlLoader.Storage = {
|
|
63
|
+
get: () => '{}',
|
|
64
|
+
set: () => {},
|
|
65
|
+
};
|
|
66
|
+
const result = await UrlLoader.preload({ storage });
|
|
67
|
+
expect(result).toEqual([]);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('returns empty array when entries are missing required fields', async ({ expect }) => {
|
|
71
|
+
const storage: UrlLoader.Storage = {
|
|
72
|
+
get: () => '[{"title":"no url"}]',
|
|
73
|
+
set: () => {},
|
|
74
|
+
};
|
|
75
|
+
const result = await UrlLoader.preload({ storage });
|
|
76
|
+
expect(result).toEqual([]);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
|
|
7
|
+
import { log } from '@dxos/log';
|
|
8
|
+
|
|
9
|
+
import * as Plugin from './plugin';
|
|
10
|
+
|
|
11
|
+
const DEFAULT_KEY = 'org.dxos.composer.remote-plugins';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Abstraction over key-value storage (defaults to localStorage).
|
|
15
|
+
*/
|
|
16
|
+
export type Storage = {
|
|
17
|
+
get(key: string): string | null;
|
|
18
|
+
set(key: string, value: string): void;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Options for configuring the URL loader.
|
|
23
|
+
*/
|
|
24
|
+
export type Options = {
|
|
25
|
+
storage?: Storage;
|
|
26
|
+
key?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type RemotePluginEntry = { id: string; url: string };
|
|
30
|
+
|
|
31
|
+
const defaultStorage = (): Storage => ({
|
|
32
|
+
get: (key) => localStorage.getItem(key),
|
|
33
|
+
set: (key, value) => localStorage.setItem(key, value),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const getPersistedRemotePlugins = (storage: Storage, key: string): RemotePluginEntry[] => {
|
|
37
|
+
try {
|
|
38
|
+
const parsed: unknown = JSON.parse(storage.get(key) ?? '[]');
|
|
39
|
+
if (!Array.isArray(parsed)) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
return parsed.filter(
|
|
43
|
+
(entry): entry is RemotePluginEntry =>
|
|
44
|
+
typeof entry === 'object' && entry !== null && typeof entry.id === 'string' && typeof entry.url === 'string',
|
|
45
|
+
);
|
|
46
|
+
} catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const persistRemotePlugin = (storage: Storage, key: string, entry: RemotePluginEntry): void => {
|
|
52
|
+
try {
|
|
53
|
+
const entries = getPersistedRemotePlugins(storage, key).filter((existing) => existing.id !== entry.id);
|
|
54
|
+
entries.push(entry);
|
|
55
|
+
storage.set(key, JSON.stringify(entries));
|
|
56
|
+
} catch (error) {
|
|
57
|
+
log.warn('failed to persist remote plugin entry', { entry, error });
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const isUrl = (locator: string): boolean => {
|
|
62
|
+
try {
|
|
63
|
+
const url = new URL(locator);
|
|
64
|
+
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const normalizePluginExport = (mod: Record<string, unknown>): Plugin.Plugin => {
|
|
71
|
+
const exported = mod.default;
|
|
72
|
+
if (Plugin.isPlugin(exported)) {
|
|
73
|
+
return exported;
|
|
74
|
+
}
|
|
75
|
+
if (typeof exported === 'function') {
|
|
76
|
+
const result = (exported as () => unknown)();
|
|
77
|
+
if (Plugin.isPlugin(result)) {
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
throw new Error('Remote module default export is not a Plugin or a zero-arg plugin factory.');
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const loadRemotePlugin = async (url: string): Promise<Plugin.Plugin> => {
|
|
85
|
+
log.info('loading remote plugin', { url });
|
|
86
|
+
const mod = await import(/* @vite-ignore */ url);
|
|
87
|
+
const plugin = normalizePluginExport(mod);
|
|
88
|
+
if (!plugin.meta.id || !plugin.meta.name) {
|
|
89
|
+
throw new Error(`Remote plugin at ${url} is missing required meta.id or meta.name.`);
|
|
90
|
+
}
|
|
91
|
+
return plugin;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Preloads previously persisted remote plugins from storage.
|
|
96
|
+
*/
|
|
97
|
+
export const preload = async (options: Options = {}): Promise<Plugin.Plugin[]> => {
|
|
98
|
+
const storage = options.storage ?? defaultStorage();
|
|
99
|
+
const key = options.key ?? DEFAULT_KEY;
|
|
100
|
+
|
|
101
|
+
const entries = getPersistedRemotePlugins(storage, key);
|
|
102
|
+
if (entries.length === 0) {
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
log.info('preloading remote plugins', { count: entries.length });
|
|
106
|
+
const results = await Promise.allSettled(entries.map((entry) => loadRemotePlugin(entry.url)));
|
|
107
|
+
const plugins: Plugin.Plugin[] = [];
|
|
108
|
+
for (let index = 0; index < results.length; index++) {
|
|
109
|
+
const result = results[index];
|
|
110
|
+
if (result.status === 'fulfilled') {
|
|
111
|
+
plugins.push(result.value);
|
|
112
|
+
} else {
|
|
113
|
+
log.warn('failed to preload remote plugin', { entry: entries[index], error: result.reason });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return plugins;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Creates a plugin loader that resolves built-in plugins by ID or loads remote plugins from URLs.
|
|
121
|
+
*/
|
|
122
|
+
export const make = (builtinPlugins: Plugin.Plugin[], options: Options = {}) => {
|
|
123
|
+
const storage = options.storage ?? defaultStorage();
|
|
124
|
+
const key = options.key ?? DEFAULT_KEY;
|
|
125
|
+
|
|
126
|
+
return (locator: string): Effect.Effect<Plugin.Plugin, Error> =>
|
|
127
|
+
Effect.gen(function* () {
|
|
128
|
+
const builtin = builtinPlugins.find((plugin) => plugin.meta.id === locator);
|
|
129
|
+
if (builtin) {
|
|
130
|
+
return builtin;
|
|
131
|
+
}
|
|
132
|
+
if (!isUrl(locator)) {
|
|
133
|
+
return yield* Effect.fail(new Error(`Plugin not found and locator is not a URL: ${locator}`));
|
|
134
|
+
}
|
|
135
|
+
const plugin = yield* Effect.tryPromise({
|
|
136
|
+
try: () => loadRemotePlugin(locator),
|
|
137
|
+
catch: (error) => new Error(`Failed to load remote plugin from ${locator}: ${error}`),
|
|
138
|
+
});
|
|
139
|
+
const duplicate = builtinPlugins.find((existing) => existing.meta.id === plugin.meta.id);
|
|
140
|
+
if (duplicate) {
|
|
141
|
+
return yield* Effect.fail(
|
|
142
|
+
new Error(`Remote plugin ${plugin.meta.id} conflicts with built-in plugin of the same id.`),
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
persistRemotePlugin(storage, key, { id: plugin.meta.id, url: locator });
|
|
146
|
+
return plugin;
|
|
147
|
+
});
|
|
148
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
export * from './
|
|
6
|
-
export * as Common from './common';
|
|
5
|
+
export * from './common';
|
|
7
6
|
export * from './context';
|
|
8
7
|
export * from './core';
|
|
9
8
|
export * from './plugin-operation';
|
|
10
9
|
export * from './plugin-runtime';
|
|
11
|
-
export * from './plugin-settings';
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import { ActivationEvents } from '../common';
|
|
6
6
|
import { Capability, Plugin } from '../core';
|
|
7
|
-
|
|
8
7
|
import { meta } from './meta';
|
|
9
8
|
|
|
10
9
|
const OperationInvoker = Capability.lazy('OperationInvoker', () => import('./invoker-capability'));
|
|
@@ -12,13 +11,13 @@ const HistoryCapabilities = Capability.lazy('HistoryCapabilities', () => import(
|
|
|
12
11
|
|
|
13
12
|
export const OperationPlugin = Plugin.define(meta).pipe(
|
|
14
13
|
Plugin.addModule({
|
|
15
|
-
activatesOn:
|
|
16
|
-
activatesBefore: [
|
|
17
|
-
activatesAfter: [
|
|
14
|
+
activatesOn: ActivationEvents.ManagedRuntimeReady,
|
|
15
|
+
activatesBefore: [ActivationEvents.SetupOperationHandler],
|
|
16
|
+
activatesAfter: [ActivationEvents.OperationInvokerReady],
|
|
18
17
|
activate: OperationInvoker,
|
|
19
18
|
}),
|
|
20
19
|
Plugin.addModule({
|
|
21
|
-
activatesOn:
|
|
20
|
+
activatesOn: ActivationEvents.OperationInvokerReady,
|
|
22
21
|
activate: HistoryCapabilities,
|
|
23
22
|
}),
|
|
24
23
|
Plugin.make,
|
|
@@ -6,9 +6,8 @@ import * as Effect from 'effect/Effect';
|
|
|
6
6
|
|
|
7
7
|
import { type OperationInvoker } from '@dxos/operation';
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import { Capabilities } from '../../common';
|
|
10
10
|
import { Capability } from '../../core';
|
|
11
|
-
|
|
12
11
|
import * as HistoryTracker from './history-tracker';
|
|
13
12
|
import * as UndoRegistry from './undo-registry';
|
|
14
13
|
|
|
@@ -22,16 +21,16 @@ export default Capability.makeModule(
|
|
|
22
21
|
const capabilities = yield* Capability.Service;
|
|
23
22
|
|
|
24
23
|
// Create UndoRegistry.
|
|
25
|
-
const undoRegistry = UndoRegistry.make(() => capabilities.getAll(
|
|
24
|
+
const undoRegistry = UndoRegistry.make(() => capabilities.getAll(Capabilities.UndoMapping).flat());
|
|
26
25
|
|
|
27
26
|
// Create HistoryTracker (depends on UndoRegistry and OperationInvoker).
|
|
28
|
-
const invoker = yield* Capability.get(
|
|
27
|
+
const invoker = yield* Capability.get(Capabilities.OperationInvoker);
|
|
29
28
|
// Cast to internal type - the factory always returns OperationInvokerInternal.
|
|
30
29
|
const historyTracker = HistoryTracker.make(invoker as OperationInvoker.OperationInvokerInternal, undoRegistry);
|
|
31
30
|
|
|
32
31
|
return [
|
|
33
|
-
Capability.contributes(
|
|
34
|
-
Capability.contributes(
|
|
32
|
+
Capability.contributes(Capabilities.UndoRegistry, undoRegistry),
|
|
33
|
+
Capability.contributes(Capabilities.HistoryTracker, historyTracker),
|
|
35
34
|
];
|
|
36
35
|
}),
|
|
37
36
|
);
|
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { BaseError } from '@dxos/errors';
|
|
6
6
|
|
|
7
|
-
export class EmptyHistoryError extends
|
|
8
|
-
constructor() {
|
|
9
|
-
super('EMPTY_HISTORY', 'Cannot undo: history is empty.');
|
|
10
|
-
}
|
|
11
|
-
}
|
|
7
|
+
export class EmptyHistoryError extends BaseError.extend('EmptyHistoryError', 'Cannot undo: history is empty.') {}
|
|
@@ -5,10 +5,14 @@
|
|
|
5
5
|
import { it } from '@effect/vitest';
|
|
6
6
|
import * as Effect from 'effect/Effect';
|
|
7
7
|
import * as Fiber from 'effect/Fiber';
|
|
8
|
+
import * as Layer from 'effect/Layer';
|
|
9
|
+
import * as ManagedRuntime from 'effect/ManagedRuntime';
|
|
8
10
|
import * as TestClock from 'effect/TestClock';
|
|
9
11
|
import { describe, expect } from 'vitest';
|
|
10
12
|
|
|
11
|
-
import {
|
|
13
|
+
import { Operation, OperationInvoker } from '@dxos/operation';
|
|
14
|
+
|
|
15
|
+
const testRuntime = ManagedRuntime.make(Layer.empty) as unknown as ManagedRuntime.ManagedRuntime<any, any>;
|
|
12
16
|
|
|
13
17
|
import { UndoOperation } from '../../common';
|
|
14
18
|
import {
|
|
@@ -21,7 +25,6 @@ import {
|
|
|
21
25
|
toStringHandler,
|
|
22
26
|
waitUntil,
|
|
23
27
|
} from '../testing';
|
|
24
|
-
|
|
25
28
|
import * as HistoryTracker from './history-tracker';
|
|
26
29
|
import * as UndoMapping from './undo-mapping';
|
|
27
30
|
import * as UndoRegistry from './undo-registry';
|
|
@@ -35,7 +38,7 @@ describe('HistoryTracker', () => {
|
|
|
35
38
|
deriveContext: (_input, output) => ({ value: output.value }),
|
|
36
39
|
});
|
|
37
40
|
|
|
38
|
-
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]));
|
|
41
|
+
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]), testRuntime);
|
|
39
42
|
const undoRegistry = UndoRegistry.make(() => [undoMapping]);
|
|
40
43
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
41
44
|
|
|
@@ -55,7 +58,7 @@ describe('HistoryTracker', () => {
|
|
|
55
58
|
|
|
56
59
|
it.effect('does not track operations without undo mapping', () =>
|
|
57
60
|
Effect.gen(function* () {
|
|
58
|
-
const invoker = OperationInvoker.make(() => Effect.succeed([toStringHandler]));
|
|
61
|
+
const invoker = OperationInvoker.make(() => Effect.succeed([toStringHandler]), testRuntime);
|
|
59
62
|
const undoRegistry = UndoRegistry.make(() => []);
|
|
60
63
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
61
64
|
const collector = yield* createEventCollector(invoker);
|
|
@@ -81,15 +84,12 @@ describe('HistoryTracker', () => {
|
|
|
81
84
|
});
|
|
82
85
|
|
|
83
86
|
let halveWasCalled = false;
|
|
84
|
-
const trackingHalveHandler =
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
halveWasCalled = true;
|
|
88
|
-
return Effect.succeed({ value: data.value / 2 });
|
|
89
|
-
},
|
|
87
|
+
const trackingHalveHandler = Operation.withHandler(HalveCompute, (data) => {
|
|
88
|
+
halveWasCalled = true;
|
|
89
|
+
return Effect.succeed({ value: data.value / 2 });
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, trackingHalveHandler]));
|
|
92
|
+
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, trackingHalveHandler]), testRuntime);
|
|
93
93
|
const undoRegistry = UndoRegistry.make(() => [undoMapping]);
|
|
94
94
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
95
95
|
|
|
@@ -117,7 +117,7 @@ describe('HistoryTracker', () => {
|
|
|
117
117
|
deriveContext: (_input, output) => ({ value: output.value }),
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
-
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]));
|
|
120
|
+
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]), testRuntime);
|
|
121
121
|
const undoRegistry = UndoRegistry.make(() => [undoMapping]);
|
|
122
122
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
123
123
|
const collector = yield* createEventCollector(invoker);
|
|
@@ -152,15 +152,12 @@ describe('HistoryTracker', () => {
|
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
const halveInputs: number[] = [];
|
|
155
|
-
const trackingHalveHandler =
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
halveInputs.push(data.value);
|
|
159
|
-
return Effect.succeed({ value: data.value / 2 });
|
|
160
|
-
},
|
|
155
|
+
const trackingHalveHandler = Operation.withHandler(HalveCompute, (data) => {
|
|
156
|
+
halveInputs.push(data.value);
|
|
157
|
+
return Effect.succeed({ value: data.value / 2 });
|
|
161
158
|
});
|
|
162
159
|
|
|
163
|
-
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, trackingHalveHandler]));
|
|
160
|
+
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, trackingHalveHandler]), testRuntime);
|
|
164
161
|
const undoRegistry = UndoRegistry.make(() => [undoMapping]);
|
|
165
162
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
166
163
|
const collector = yield* createEventCollector(invoker);
|
|
@@ -194,7 +191,7 @@ describe('HistoryTracker', () => {
|
|
|
194
191
|
|
|
195
192
|
it.effect('undo on empty history returns error', () =>
|
|
196
193
|
Effect.gen(function* () {
|
|
197
|
-
const invoker = OperationInvoker.make(() => Effect.succeed([]));
|
|
194
|
+
const invoker = OperationInvoker.make(() => Effect.succeed([]), testRuntime);
|
|
198
195
|
const undoRegistry = UndoRegistry.make(() => []);
|
|
199
196
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
200
197
|
|
|
@@ -208,7 +205,7 @@ describe('HistoryTracker', () => {
|
|
|
208
205
|
|
|
209
206
|
it.effect('fires ShowUndo operation when undoable operation is tracked', () =>
|
|
210
207
|
Effect.gen(function* () {
|
|
211
|
-
const testMessage: [string, { ns: string }] = ['test
|
|
208
|
+
const testMessage: [string, { ns: string }] = ['test-undo.message', { ns: 'test' }];
|
|
212
209
|
const undoMapping = UndoMapping.make({
|
|
213
210
|
operation: Compute,
|
|
214
211
|
inverse: HalveCompute,
|
|
@@ -218,17 +215,15 @@ describe('HistoryTracker', () => {
|
|
|
218
215
|
|
|
219
216
|
let showUndoWasCalled = false;
|
|
220
217
|
let showUndoMessage: unknown = undefined;
|
|
221
|
-
const showUndoHandler =
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
showUndoMessage = input.message;
|
|
226
|
-
return Effect.succeed(undefined);
|
|
227
|
-
},
|
|
218
|
+
const showUndoHandler = Operation.withHandler(UndoOperation.ShowUndo, (input) => {
|
|
219
|
+
showUndoWasCalled = true;
|
|
220
|
+
showUndoMessage = input.message;
|
|
221
|
+
return Effect.succeed(undefined);
|
|
228
222
|
});
|
|
229
223
|
|
|
230
|
-
const invoker = OperationInvoker.make(
|
|
231
|
-
Effect.succeed([computeHandler, halveComputeHandler, showUndoHandler]),
|
|
224
|
+
const invoker = OperationInvoker.make(
|
|
225
|
+
() => Effect.succeed([computeHandler, halveComputeHandler, showUndoHandler]),
|
|
226
|
+
testRuntime,
|
|
232
227
|
);
|
|
233
228
|
const undoRegistry = UndoRegistry.make(() => [undoMapping]);
|
|
234
229
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
@@ -254,7 +249,7 @@ describe('HistoryTracker', () => {
|
|
|
254
249
|
Effect.gen(function* () {
|
|
255
250
|
// Dynamic message that depends on input/output.
|
|
256
251
|
const dynamicMessage = (input: { value: number }, output: { value: number }): [string, { ns: string }] => [
|
|
257
|
-
`computed
|
|
252
|
+
`computed-${input.value}-to-${output.value}`,
|
|
258
253
|
{ ns: 'test' },
|
|
259
254
|
];
|
|
260
255
|
const undoMapping = UndoMapping.make({
|
|
@@ -266,17 +261,15 @@ describe('HistoryTracker', () => {
|
|
|
266
261
|
|
|
267
262
|
let showUndoWasCalled = false;
|
|
268
263
|
let showUndoMessage: unknown = undefined;
|
|
269
|
-
const showUndoHandler =
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
showUndoMessage = input.message;
|
|
274
|
-
return Effect.succeed(undefined);
|
|
275
|
-
},
|
|
264
|
+
const showUndoHandler = Operation.withHandler(UndoOperation.ShowUndo, (input) => {
|
|
265
|
+
showUndoWasCalled = true;
|
|
266
|
+
showUndoMessage = input.message;
|
|
267
|
+
return Effect.succeed(undefined);
|
|
276
268
|
});
|
|
277
269
|
|
|
278
|
-
const invoker = OperationInvoker.make(
|
|
279
|
-
Effect.succeed([computeHandler, halveComputeHandler, showUndoHandler]),
|
|
270
|
+
const invoker = OperationInvoker.make(
|
|
271
|
+
() => Effect.succeed([computeHandler, halveComputeHandler, showUndoHandler]),
|
|
272
|
+
testRuntime,
|
|
280
273
|
);
|
|
281
274
|
const undoRegistry = UndoRegistry.make(() => [undoMapping]);
|
|
282
275
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
@@ -295,7 +288,7 @@ describe('HistoryTracker', () => {
|
|
|
295
288
|
yield* waitUntil(() => showUndoWasCalled);
|
|
296
289
|
expect(showUndoWasCalled).toBe(true);
|
|
297
290
|
// Compute 2 * 2 = 4, so message should be 'computed 2 to 4'.
|
|
298
|
-
expect(showUndoMessage).toEqual(['computed
|
|
291
|
+
expect(showUndoMessage).toEqual(['computed-2-to-4', { ns: 'test' }]);
|
|
299
292
|
}),
|
|
300
293
|
);
|
|
301
294
|
|
|
@@ -314,7 +307,7 @@ describe('HistoryTracker', () => {
|
|
|
314
307
|
},
|
|
315
308
|
});
|
|
316
309
|
|
|
317
|
-
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]));
|
|
310
|
+
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]), testRuntime);
|
|
318
311
|
const undoRegistry = UndoRegistry.make(() => [undoMapping]);
|
|
319
312
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
320
313
|
const collector = yield* createEventCollector(invoker);
|
|
@@ -352,7 +345,7 @@ describe('HistoryTracker', () => {
|
|
|
352
345
|
},
|
|
353
346
|
});
|
|
354
347
|
|
|
355
|
-
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]));
|
|
348
|
+
const invoker = OperationInvoker.make(() => Effect.succeed([computeHandler, halveComputeHandler]), testRuntime);
|
|
356
349
|
const undoRegistry = UndoRegistry.make(() => [undoMapping]);
|
|
357
350
|
const tracker = HistoryTracker.make(invoker, undoRegistry);
|
|
358
351
|
const collector = yield* createEventCollector(invoker);
|
|
@@ -10,7 +10,6 @@ import { log } from '@dxos/log';
|
|
|
10
10
|
import { type OperationInvoker } from '@dxos/operation';
|
|
11
11
|
|
|
12
12
|
import { UndoOperation } from '../../common';
|
|
13
|
-
|
|
14
13
|
import { EmptyHistoryError } from './errors';
|
|
15
14
|
import type { HistoryEntry } from './types';
|
|
16
15
|
import { resolveMessage } from './undo-mapping';
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
import type { Operation } from '@dxos/operation';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Label type for translatable text (canonical definition in @dxos/app-toolkit).
|
|
9
|
+
*/
|
|
10
|
+
type Label = string | [string, { ns: string; count?: number; defaultValue?: string }];
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* Extract the input type from an OperationDefinition.
|
|
@@ -95,7 +98,7 @@ export interface UndoMappingProps<
|
|
|
95
98
|
* thread: output.thread,
|
|
96
99
|
* anchor: output.anchor,
|
|
97
100
|
* }),
|
|
98
|
-
* message: ['thread deleted label', { ns: 'plugin-thread' }],
|
|
101
|
+
* message: ['thread deleted label', { ns: '@dxos/plugin-thread' }],
|
|
99
102
|
* });
|
|
100
103
|
*
|
|
101
104
|
* // Dynamic message based on input/output
|
|
@@ -106,7 +109,7 @@ export interface UndoMappingProps<
|
|
|
106
109
|
* message: (input, _output) =>
|
|
107
110
|
* input.objects.length === 1
|
|
108
111
|
* ? ['object deleted label', { ns: getTypename(input.objects[0]) }]
|
|
109
|
-
* : ['objects deleted label', { ns: 'plugin-space' }],
|
|
112
|
+
* : ['objects deleted label', { ns: '@dxos/plugin-space' }],
|
|
110
113
|
* });
|
|
111
114
|
* ```
|
|
112
115
|
*/
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import { describe, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { Compute, HalveCompute } from '../testing';
|
|
8
|
-
|
|
9
8
|
import * as UndoMapping from './undo-mapping';
|
|
10
9
|
import * as UndoRegistry from './undo-registry';
|
|
11
10
|
|
|
@@ -52,18 +51,18 @@ describe('resolveMessage', () => {
|
|
|
52
51
|
});
|
|
53
52
|
|
|
54
53
|
test('returns static label as-is', ({ expect }) => {
|
|
55
|
-
const staticMessage: [string, { ns: string }] = ['test
|
|
54
|
+
const staticMessage: [string, { ns: string }] = ['test.message', { ns: 'test' }];
|
|
56
55
|
const result = UndoMapping.resolveMessage(staticMessage, { value: 1 }, { value: 2 });
|
|
57
56
|
expect(result).toEqual(staticMessage);
|
|
58
57
|
});
|
|
59
58
|
|
|
60
59
|
test('calls function message with input and output', ({ expect }) => {
|
|
61
60
|
const messageFunc = (input: { value: number }, output: { value: number }): [string, { ns: string }] => [
|
|
62
|
-
`input
|
|
61
|
+
`input-${input.value}-output-${output.value}`,
|
|
63
62
|
{ ns: 'test' },
|
|
64
63
|
];
|
|
65
64
|
const result = UndoMapping.resolveMessage(messageFunc, { value: 5 }, { value: 10 });
|
|
66
|
-
expect(result).toEqual(['input
|
|
65
|
+
expect(result).toEqual(['input-5-output-10', { ns: 'test' }]);
|
|
67
66
|
});
|
|
68
67
|
|
|
69
68
|
test('returns string label as-is', ({ expect }) => {
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Effect from 'effect/Effect';
|
|
6
6
|
|
|
7
|
-
import { OperationInvoker } from '@dxos/operation';
|
|
7
|
+
import { OperationHandlerSet, OperationInvoker } from '@dxos/operation';
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import { ActivationEvents, Capabilities } from '../common';
|
|
10
10
|
import { Capability, Plugin } from '../core';
|
|
11
11
|
|
|
12
12
|
//
|
|
@@ -20,21 +20,35 @@ export default Capability.makeModule(
|
|
|
20
20
|
const pluginManager = yield* Plugin.Service;
|
|
21
21
|
|
|
22
22
|
// Get the ManagedRuntime capability (should be available since we activate after ManagedRuntimeReady).
|
|
23
|
-
const
|
|
24
|
-
|
|
23
|
+
const managedRuntime = yield* Capability.get(Capabilities.ManagedRuntime);
|
|
24
|
+
|
|
25
|
+
// Cache the merged handler promise to prevent concurrent module loading.
|
|
26
|
+
// Multiple Effects can invoke getHandlers simultaneously; without caching each
|
|
27
|
+
// creates a new merge() which triggers parallel dynamic imports that race in
|
|
28
|
+
// WebKit's module evaluator, causing TDZ errors on export default bindings.
|
|
29
|
+
let cachedSets: readonly OperationHandlerSet.OperationHandlerSet[] | undefined;
|
|
30
|
+
let cachedHandlers: ReturnType<OperationHandlerSet.OperationHandlerSet['getHandlers']> | undefined;
|
|
25
31
|
|
|
26
32
|
const invoker = OperationInvoker.make(
|
|
27
33
|
() =>
|
|
28
34
|
Effect.gen(function* () {
|
|
29
|
-
yield* Plugin.activate(
|
|
30
|
-
|
|
35
|
+
yield* Plugin.activate(ActivationEvents.SetupOperationHandler);
|
|
36
|
+
const sets = yield* Capability.getAll(Capabilities.OperationHandler);
|
|
37
|
+
|
|
38
|
+
if (sets !== cachedSets) {
|
|
39
|
+
cachedSets = sets;
|
|
40
|
+
cachedHandlers = OperationHandlerSet.merge(...sets).getHandlers();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return yield* Effect.promise(() => cachedHandlers!);
|
|
31
44
|
}).pipe(
|
|
32
45
|
Effect.provideService(Capability.Service, capabilityManager),
|
|
33
46
|
Effect.provideService(Plugin.Service, pluginManager),
|
|
47
|
+
Effect.orDie,
|
|
34
48
|
),
|
|
35
49
|
managedRuntime,
|
|
36
50
|
);
|
|
37
51
|
|
|
38
|
-
return Capability.contributes(
|
|
52
|
+
return Capability.contributes(Capabilities.OperationInvoker, invoker);
|
|
39
53
|
}),
|
|
40
54
|
);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { type Plugin } from '../core';
|
|
6
6
|
|
|
7
7
|
export const meta: Plugin.Meta = {
|
|
8
|
-
id: 'dxos.
|
|
8
|
+
id: 'org.dxos.plugin.operation',
|
|
9
9
|
name: 'Operation Plugin',
|
|
10
10
|
description: 'Provides operation invocation, undo registry, and history tracking.',
|
|
11
11
|
};
|