@platforma-sdk/ui-vue 1.61.3 → 1.62.0

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/.oxfmtrc.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "extends": ["node_modules/@milaboratories/ts-builder/configs/oxfmt.json"],
3
- "ignorePatterns": ["dist", "CHANGELOG.md"]
3
+ "ignorePatterns": ["dist", "coverage", "CHANGELOG.md"]
4
4
  }
@@ -1,17 +1,17 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-sdk/ui-vue@1.61.3 build /home/runner/_work/platforma/platforma/sdk/ui-vue
3
+ > @platforma-sdk/ui-vue@1.62.0 build /home/runner/_work/platforma/platforma/sdk/ui-vue
4
4
  > ts-builder build --target browser-lib
5
5
 
6
6
  Building browser-lib project...
7
7
  ↳ vite.js build --config /configs/vite.browser-lib.config.js --mode production
8
8
  vite v8.0.0-beta.15 building client environment for production...
9
9
  [warn] `inlineDynamicImports` option is deprecated, please use `codeSplitting: false` instead.
10
- 
10
+ 
11
11
  rendering chunks...
12
12
 
13
13
  [vite:dts] Start generate declaration files...
14
- [vite:dts] Declaration files built in 5319ms.
14
+ [vite:dts] Declaration files built in 5102ms.
15
15
 
16
16
  computing gzip size...
17
17
  dist/components/PlAnnotations/components/PlAnnotations.vue?vue&type=style&index=0&lang.css 0.04 kB │ gzip: 0.06 kB
@@ -142,6 +142,7 @@ dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue_vue_type_script_setup_tr
142
142
  dist/objectHash.js 0.53 kB │ gzip: 0.37 kB │ map: 1.14 kB
143
143
  dist/AgGridVue/ag-override.js 0.61 kB │ gzip: 0.30 kB │ map: 0.73 kB
144
144
  dist/components/PlAdvancedFilter/FilterEditor.vue_vue_type_style_index_0_lang.module.js 0.62 kB │ gzip: 0.33 kB │ map: 0.92 kB
145
+ dist/internal/service_factories.js 0.64 kB │ gzip: 0.38 kB │ map: 1.07 kB
145
146
  dist/components/PlAgDataTable/PlAgOverlayNoRows.vue_vue_type_script_setup_true_lang.js 0.65 kB │ gzip: 0.44 kB │ map: 1.56 kB
146
147
  dist/plugins/Monetization/LimitCard.vue_vue_type_style_index_0_lang.module.js 0.68 kB │ gzip: 0.34 kB │ map: 0.93 kB
147
148
  dist/_virtual/_rolldown/runtime.js 0.68 kB │ gzip: 0.40 kB
@@ -169,7 +170,7 @@ dist/lib/util/helpers/dist/prettyBytes.js
169
170
  dist/AgGridVue/AgGridTheme.js 1.25 kB │ gzip: 0.57 kB │ map: 2.06 kB
170
171
  dist/components/PlBtnExportArchive/Item.vue_vue_type_script_setup_true_lang.js 1.26 kB │ gzip: 0.57 kB │ map: 2.58 kB
171
172
  dist/components/PlAgDataTable/types.js 1.27 kB │ gzip: 0.50 kB │ map: 7.63 kB
172
- dist/usePlugin.js 1.29 kB │ gzip: 0.70 kB │ map: 2.63 kB
173
+ dist/usePlugin.js 1.29 kB │ gzip: 0.70 kB │ map: 2.76 kB
173
174
  dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue_vue_type_script_setup_true_lang.js 1.34 kB │ gzip: 0.73 kB │ map: 3.42 kB
174
175
  dist/internal/createAppModel.js 1.42 kB │ gzip: 0.72 kB │ map: 3.89 kB
175
176
  dist/components/PlAgCsvExporter/export-csv.js 1.44 kB │ gzip: 0.70 kB │ map: 3.50 kB
@@ -193,7 +194,7 @@ dist/lib/util/helpers/dist/objects.js
193
194
  dist/lib.js 2.60 kB │ gzip: 0.56 kB │ map: 3.84 kB
194
195
  dist/components/PlAgDataTable/compositions/useGrid.js 2.72 kB │ gzip: 1.20 kB │ map: 6.27 kB
195
196
  dist/components/PlAgDataTable/sources/row-number.js 2.92 kB │ gzip: 1.28 kB │ map: 7.42 kB
196
- dist/defineApp.js 2.98 kB │ gzip: 1.04 kB │ map: 13.94 kB
197
+ dist/defineApp.js 2.98 kB │ gzip: 1.04 kB │ map: 14.38 kB
197
198
  dist/plugins/Monetization/LimitCard.vue_vue_type_script_setup_true_lang.js 3.21 kB │ gzip: 1.09 kB │ map: 9.08 kB
198
199
  dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue_vue_type_script_setup_true_lang.js 3.26 kB │ gzip: 1.46 kB │ map: 5.77 kB
199
200
  dist/AgGridVue/createAgGridColDef.js 3.26 kB │ gzip: 1.27 kB │ map: 9.25 kB
@@ -209,18 +210,18 @@ dist/components/PlBtnExportArchive/PlBtnExportArchive.vue_vue_type_script_setup_
209
210
  dist/AgGridVue/useAgGridOptions.js 5.74 kB │ gzip: 1.79 kB │ map: 14.21 kB
210
211
  dist/internal/createAppV2.js 6.00 kB │ gzip: 2.27 kB │ map: 17.80 kB
211
212
  dist/components/PlAgDataTable/sources/table-source-v2.js 6.44 kB │ gzip: 2.56 kB │ map: 19.12 kB
212
- dist/internal/createAppV3.js 6.66 kB │ gzip: 2.55 kB │ map: 20.28 kB
213
+ dist/internal/createAppV3.js 6.94 kB │ gzip: 2.68 kB │ map: 21.43 kB
213
214
  dist/components/PlAdvancedFilter/PlAdvancedFilter.vue_vue_type_script_setup_true_lang.js 7.06 kB │ gzip: 2.28 kB │ map: 14.91 kB
214
215
  dist/components/PlAdvancedFilter/FilterEditor.vue_vue_type_script_setup_true_lang.js 10.14 kB │ gzip: 3.05 kB │ map: 21.57 kB
215
216
  dist/components/PlAgDataTable/PlAgDataTableV2.vue_vue_type_script_setup_true_lang.js 11.51 kB │ gzip: 3.68 kB │ map: 27.94 kB
216
217
 
217
218
  [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:
218
- - sourcemaps (39%)
219
- - vite:dts (19%)
220
- - vite:vue (11%)
219
+ - sourcemaps (36%)
220
+ - vite:dts (27%)
221
221
  - vite:css-post (10%)
222
- - vite:build-import-analysis (7%)
222
+ - vite:vue (9%)
223
+ - vite:css (7%)
223
224
  See https://rolldown.rs/options/checks#plugintimings for more details.
224
225
  
225
- ✓ built in 6.35s
226
+ ✓ built in 5.90s
226
227
  Build completed successfully
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-sdk/ui-vue@1.61.3 formatter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
3
+ > @platforma-sdk/ui-vue@1.62.0 formatter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
4
4
  > ts-builder formatter --check
5
5
 
6
6
  Checking formatting...
@@ -8,5 +8,5 @@ Checking formatting...
8
8
  Checking formatting...
9
9
 
10
10
  All matched files use the correct format.
11
- Finished in 886ms on 127 files using 8 threads.
11
+ Finished in 3217ms on 128 files using 8 threads.
12
12
  Format check completed successfully
@@ -1,10 +1,10 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-sdk/ui-vue@1.61.3 linter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
3
+ > @platforma-sdk/ui-vue@1.62.0 linter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
4
4
  > ts-builder linter --check
5
5
 
6
6
  Linting project...
7
7
  ↳ oxlint --config /home/runner/_work/platforma/platforma/sdk/ui-vue/.oxlintrc.json --deny-warnings
8
8
  Found 0 warnings and 0 errors.
9
- Finished in 29ms on 110 files with 98 rules using 8 threads.
9
+ Finished in 45ms on 111 files with 98 rules using 8 threads.
10
10
  Linting completed successfully
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-sdk/ui-vue@1.61.3 types:check /home/runner/_work/platforma/platforma/sdk/ui-vue
3
+ > @platforma-sdk/ui-vue@1.62.0 types:check /home/runner/_work/platforma/platforma/sdk/ui-vue
4
4
  > ts-builder type-check --target browser-lib
5
5
 
6
6
  ↳ vue-tsc.js --noEmit --project ./tsconfig.json --customConditions ,
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @platforma-sdk/ui-vue
2
2
 
3
+ ## 1.62.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 74a2ffa: Add block-level services infrastructure (PFrameSpec, PFrame)
8
+
9
+ - Introduce `Services` registry in pl-model-common with service definitions, feature flags, and typed driver interfaces
10
+ - Add `PFrameSpec` service: synchronous WASM-based spec operations (createSpecFrame, discoverColumns, evaluateQuery)
11
+ - Wire services through block model, plugin model, and UI layers with compile-time `RequireServices` constraints
12
+ - Add `ColumnCollection` with `dispose()` for deterministic spec frame cleanup. **Breaking:** `ColumnCollection` and `AnchoredColumnCollection` now extend `Disposable` — custom implementations must add a `dispose()` method
13
+ - Add `createPlDataTable` v3 API using `ColumnCollectionBuilder` with include/exclude column selectors
14
+ - Auto-dispose leaked SpecFrame handles via `addOnDestroy` in computable lifecycle. **Breaking:** `PFrameSpecDriver.createSpecFrame` now returns `PoolEntry<SpecFrameHandle>` instead of `SpecFrameHandle`; `disposeSpecFrame` removed — use `entry.unref()` instead
15
+ - Add `PoolEntry`, `PoolEntryGuard` to pl-model-common for cross-package pool entry lifecycle management
16
+ - Add `ServiceRegistryBase.dispose()` for proper service cleanup; wire disposal in middle layer and UI
17
+ - Migrate `PFramePool` from `RefCountManualPoolBase` to `RefCountPoolBase` with idempotent unref; remove `RefCountManualPoolBase`
18
+ - Add `requireComputableCtx` getter to centralize computable context guards; migrate `createPFrame`/`createPTable`/`createPTableV2` to use `PoolEntryGuard` for leak-safe resource handling
19
+ - Move pf-spec-driver logging before WASM calls for better crash diagnostics
20
+ - Fix outputWithStatus in plugin model
21
+ - Fix table row selection not propagating to selection model
22
+ - Fix linker columns with `pl7.app/parents` annotation failing WASM validation ("must have exactly 2 connected components") by resolving annotation-based parents to numeric `parentAxes` before passing specs to Rust/WASM engine
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependencies [74a2ffa]
27
+ - @milaboratories/pl-model-common@1.30.0
28
+ - @milaboratories/pf-spec-driver@1.2.0
29
+ - @platforma-sdk/model@1.62.0
30
+ - @milaboratories/uikit@2.11.4
31
+
3
32
  ## 1.61.3
4
33
 
5
34
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotations.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = BaseProps & {\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\n// Models\nconst annotation = defineModel<Annotation>(\"annotation\", { required: true });\n// Props\nconst props = defineProps<Props>();\n// State\nconst selectedStepId = shallowRef<number | undefined>(undefined);\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(annotation.value)\n ? undefined\n : annotation.value.steps.find((step) => step.id === selectedStepId.value);\n});\n\n// Watchers\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && annotation.value.steps.length > 0) {\n selectedStepId.value = annotation.value.steps[0].id;\n }\n});\n// Hooks\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n// Actions\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n</script>\n\n<template>\n <PlSidebarGroup>\n <template #item-0>\n <AnnotationsSidebar\n v-model:annotation=\"annotation\"\n v-model:selectedStepId=\"selectedStepId\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n v-model:step=\"selectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :selectedStepId=\"selectedStepId\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAkBA,IAAM,IAAa,EAAuB,GAAC,aAAiC,EAEtE,IAAQ,GAER,IAAiB,EAA+B,KAAA,EAAU,EAC1D,IAAe,QACZ,EAAM,EAAe,MAAM,IAAI,EAAM,EAAW,MAAK,GACxD,KAAA,IACA,EAAW,MAAM,MAAM,MAAM,MAAS,EAAK,OAAO,EAAe,MAAM,CAC3E;AAGF,IAAO,WAA4B;AACjC,GAAI,EAAe,UAAU,KAAA,KAAa,EAAW,MAAM,MAAM,SAAS,MACxE,EAAe,QAAQ,EAAW,MAAM,MAAM,GAAG;IAEnD;EAEF,IAAM,IAAqB,EAAW;GACpC,OAAO;GACP,SAAS;GACT,cAAc;GACd,aAAa;GACd,CAAC;EAEF,eAAe,IAAqB;AAClC,GAAI,MAAM,GAAoB,KAC5B,EAAe,QAAQ,KAAA,GACvB,EAAM,kBAAkB;;yBAM1B,EAsBiB,EAAA,EAAA,EAAA,MAAA;GArBJ,UAAM,QAOb,CANF,EAME,GAAA;IALQ,YAAY,EAAA;6CAAU,QAAA;IACtB,gBAAgB,EAAA;iDAAc,QAAA;IACrC,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,SAAS,EAAM;IACf,gBAAe;;;;;;;GAGT,UAAM,QAWH,CATJ,EAAA,SAAA,GAAA,EADR,EASE,GAAA;;IAPQ,MAAM,EAAA;uCAAY,QAAA;IACzB,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,SAAS,EAAM;IACf,uBAAqB,EAAM;IAC3B,gBAAgB,EAAA;IAChB,oBAAoB,EAAM;IAC1B,6BAA6B,EAAM"}
1
+ {"version":3,"file":"PlAnnotations.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = BaseProps & {\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\n// Models\nconst annotation = defineModel<Annotation>(\"annotation\", { required: true });\n// Props\nconst props = defineProps<Props>();\n// State\nconst selectedStepId = shallowRef<number | undefined>(undefined);\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(annotation.value)\n ? undefined\n : annotation.value.steps.find((step) => step.id === selectedStepId.value);\n});\n\n// Watchers\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && annotation.value.steps.length > 0) {\n selectedStepId.value = annotation.value.steps[0].id;\n }\n});\n// Hooks\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n// Actions\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n</script>\n\n<template>\n <PlSidebarGroup>\n <template #item-0>\n <AnnotationsSidebar\n v-model:annotation=\"annotation\"\n v-model:selectedStepId=\"selectedStepId\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n v-model:step=\"selectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :selectedStepId=\"selectedStepId\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAkBA,IAAM,IAAa,EAAuB,GAAC,aAAiC,EAEtE,IAAQ,GAER,IAAiB,EAA+B,KAAA,EAAU,EAC1D,IAAe,QACZ,EAAM,EAAe,MAAM,IAAI,EAAM,EAAW,MAAK,GACxD,KAAA,IACA,EAAW,MAAM,MAAM,MAAM,MAAS,EAAK,OAAO,EAAe,MAAM,CAC3E;AAGF,IAAO,WAA4B;AACjC,GAAI,EAAe,UAAU,KAAA,KAAa,EAAW,MAAM,MAAM,SAAS,MACxE,EAAe,QAAQ,EAAW,MAAM,MAAM,GAAG;IAEnD;EAEF,IAAM,IAAqB,EAAW;GACpC,OAAO;GACP,SAAS;GACT,cAAc;GACd,aAAa;GACd,CAAC;EAEF,eAAe,IAAqB;AAClC,GAAI,MAAM,GAAoB,KAC5B,EAAe,QAAQ,KAAA,GACvB,EAAM,kBAAkB;;yBAM1B,EAsBiB,EAAA,EAAA,EAAA,MAAA;GArBJ,UAAM,QAOb,CANF,EAME,GAAA;IALQ,YAAY,EAAA;6CAAU,QAAA;IACtB,gBAAgB,EAAA;iDAAc,QAAA;IACrC,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,SAAS,EAAM;IACf,gBAAe;;;;;;;GAGT,UAAM,QAUb,CARM,EAAA,SAAA,GAAA,EADR,EASE,GAAA;;IAPQ,MAAM,EAAA;uCAAY,QAAA;IACzB,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,SAAS,EAAM;IACf,uBAAqB,EAAM;IAC3B,gBAAgB,EAAA;IAChB,oBAAoB,EAAM;IAC1B,6BAA6B,EAAM"}
@@ -1,4 +1,4 @@
1
- import { PlatformaV3, PlatformaV1, PlatformaV2, BlockCodeKnownFeatureFlags, BlockOutputsBase, BlockModelInfo } from '@platforma-sdk/model';
1
+ import { PlatformaV3, PlatformaV1, PlatformaV2, BlockCodeKnownFeatureFlags, UiServices as AllUiServices, BlockOutputsBase, BlockModelInfo } from '@platforma-sdk/model';
2
2
  import { App as VueApp, Component, Reactive } from 'vue';
3
3
  import { BaseAppV1 } from './internal/createAppV1';
4
4
  import { BaseAppV2 } from './internal/createAppV2';
@@ -13,16 +13,16 @@ export declare function defineApp<Args = unknown, Outputs extends BlockOutputsBa
13
13
  export declare function defineApp<Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, UiState = unknown, Href extends `/${string}` = `/${string}`, Extend extends ExtendSettings<Href> = ExtendSettings<Href>>(platforma: PlatformaV2<Args, Outputs, UiState, Href> & {
14
14
  blockModelInfo: BlockModelInfo;
15
15
  }, extendApp: (app: BaseAppV2<Args, Outputs, UiState, Href>) => Extend, settings?: AppSettings): SdkPluginV2<Args, Outputs, UiState, Href, Extend>;
16
- export declare function defineAppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>, Extend extends ExtendSettings<Href> = ExtendSettings<Href>>(platforma: PlatformaV3<Data, Args, Outputs, Href, Plugins> & {
16
+ export declare function defineAppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>, UiServices extends Partial<AllUiServices> = Partial<AllUiServices>, Extend extends ExtendSettings<Href> = ExtendSettings<Href>>(platforma: PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices> & {
17
17
  blockModelInfo: BlockModelInfo;
18
- }, extendApp: (app: BaseAppV3<Data, Args, Outputs, Href, Plugins>) => Extend, settings?: AppSettings): SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend>;
18
+ }, extendApp: (app: BaseAppV3<Data, Args, Outputs, Href, Plugins, UiServices>) => Extend, settings?: AppSettings): SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices>;
19
19
  export type AppV1<Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, UiState = unknown, Href extends `/${string}` = `/${string}`, Local extends ExtendSettings<Href> = ExtendSettings<Href>> = BaseAppV1<Args, Outputs, UiState, Href> & Reactive<Omit<Local, "routes">> & {
20
20
  getRoute(href: Href): Component | undefined;
21
21
  };
22
22
  export type AppV2<Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, UiState = unknown, Href extends `/${string}` = `/${string}`, Local extends ExtendSettings<Href> = ExtendSettings<Href>> = BaseAppV2<Args, Outputs, UiState, Href> & Reactive<Omit<Local, "routes">> & {
23
23
  getRoute(href: Href): Component | undefined;
24
24
  };
25
- export type AppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = NonNullable<unknown>, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>, Local extends ExtendSettings<Href> = ExtendSettings<Href>> = BaseAppV3<Data, Args, Outputs, Href, Plugins> & Reactive<Omit<Local, "routes">> & {
25
+ export type AppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = NonNullable<unknown>, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>, Local extends ExtendSettings<Href> = ExtendSettings<Href>, UiServices extends Partial<AllUiServices> = Partial<AllUiServices>> = BaseAppV3<Data, Args, Outputs, Href, Plugins, UiServices> & Reactive<Omit<Local, "routes">> & {
26
26
  getRoute(href: Href): Component | undefined;
27
27
  };
28
28
  export type SdkPluginV1<Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, UiState = unknown, Href extends `/${string}` = `/${string}`, Local extends ExtendSettings<Href> = ExtendSettings<Href>> = {
@@ -41,12 +41,12 @@ export type SdkPluginV2<Args = unknown, Outputs extends BlockOutputsBase = Block
41
41
  useApp<PageHref extends Href = Href>(): AppV2<Args, Outputs, UiState, PageHref, Local>;
42
42
  install(app: VueApp): void;
43
43
  };
44
- export type SdkPluginV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>, Local extends ExtendSettings<Href> = ExtendSettings<Href>> = {
44
+ export type SdkPluginV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>, Local extends ExtendSettings<Href> = ExtendSettings<Href>, UiServices extends Partial<AllUiServices> = Partial<AllUiServices>> = {
45
45
  apiVersion: 3;
46
46
  featureFlags: BlockCodeKnownFeatureFlags;
47
47
  loaded: boolean;
48
48
  error: unknown;
49
- useApp<PageHref extends Href = Href>(): AppV3<Data, Args, Outputs, PageHref, Plugins, Local>;
49
+ useApp<PageHref extends Href = Href>(): AppV3<Data, Args, Outputs, PageHref, Plugins, Local, UiServices>;
50
50
  install(app: VueApp): void;
51
51
  };
52
52
  export type SdkPlugin = SdkPluginV1 | SdkPluginV2 | SdkPluginV3;
@@ -1 +1 @@
1
- {"version":3,"file":"defineApp.d.ts","sourceRoot":"","sources":["../src/defineApp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"defineApp.d.ts","sourceRoot":"","sources":["../src/defineApp.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"defineApp.js","names":[],"sources":["../src/defineApp.ts"],"sourcesContent":["import { notEmpty } from \"@milaboratories/helpers\";\nimport type {\n PlatformaExtended,\n PlatformaV3,\n PlatformaV1,\n PlatformaV2,\n BlockCodeKnownFeatureFlags,\n} from \"@platforma-sdk/model\";\nimport {\n getPlatformaApiVersion,\n unwrapResult,\n type BlockOutputsBase,\n type BlockModelInfo,\n} from \"@platforma-sdk/model\";\nimport type { App as VueApp, Component, Reactive } from \"vue\";\nimport { inject, markRaw, reactive } from \"vue\";\nimport { createAppV1, type BaseAppV1 } from \"./internal/createAppV1\";\nimport { createAppV2, type BaseAppV2 } from \"./internal/createAppV2\";\nimport { createAppV3, type BaseAppV3 } from \"./internal/createAppV3\";\nimport type { AppSettings, ExtendSettings, Routes } from \"./types\";\n\nconst pluginKey = Symbol(\"sdk-vue\");\nexport const pluginDataKey = Symbol(\"plugin-data-access\");\n\nexport function useSdkPlugin(): SdkPlugin {\n return inject(pluginKey)!;\n}\n\nexport function useFeatureFlags() {\n const sdk = useSdkPlugin();\n return sdk.featureFlags;\n}\n\nexport function defineApp<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Extend extends ExtendSettings<Href> = ExtendSettings<Href>,\n>(\n platforma: PlatformaV1<Args, Outputs, UiState, Href> & {\n blockModelInfo: BlockModelInfo;\n },\n extendApp: (app: BaseAppV1<Args, Outputs, UiState, Href>) => Extend,\n settings?: AppSettings,\n): SdkPluginV1<Args, Outputs, UiState, Href, Extend>;\n\nexport function defineApp<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Extend extends ExtendSettings<Href> = ExtendSettings<Href>,\n>(\n platforma: PlatformaV2<Args, Outputs, UiState, Href> & {\n blockModelInfo: BlockModelInfo;\n },\n extendApp: (app: BaseAppV2<Args, Outputs, UiState, Href>) => Extend,\n settings?: AppSettings,\n): SdkPluginV2<Args, Outputs, UiState, Href, Extend>;\n\nexport function defineApp<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Extend extends ExtendSettings<Href> = ExtendSettings<Href>,\n>(\n platforma: PlatformaExtended<\n PlatformaV1<Args, Outputs, UiState, Href> | PlatformaV2<Args, Outputs, UiState, Href>\n >,\n\n //\n extendApp: (app: any) => Extend,\n settings: AppSettings = {},\n):\n | SdkPluginV1<Args, Outputs, UiState, Href, Extend>\n | SdkPluginV2<Args, Outputs, UiState, Href, Extend> {\n let app:\n | AppV1<Args, Outputs, UiState, Href, Extend>\n | AppV2<Args, Outputs, UiState, Href, Extend>\n | undefined = undefined;\n\n const runtimeApiVersion = platforma.apiVersion ?? 1; // undefined means 1 (backward compatibility)\n const blockRequestedApiVersion = getPlatformaApiVersion();\n\n const loadApp = async () => {\n if (blockRequestedApiVersion !== runtimeApiVersion) {\n throw new Error(`Block requested API version ${blockRequestedApiVersion} but runtime API version is ${runtimeApiVersion}.\n Please update the desktop app to use the latest API version.`);\n }\n\n if (platforma.apiVersion === undefined || platforma.apiVersion === 1) {\n await platforma.loadBlockState().then((state) => {\n plugin.loaded = true;\n const baseApp = createAppV1<Args, Outputs, UiState, Href>(state, platforma, settings);\n\n const localState = extendApp(baseApp);\n\n const routes = Object.fromEntries(\n Object.entries(localState.routes as Routes<Href>).map(([href, component]) => {\n const c = typeof component === \"function\" ? component() : component;\n return [href, markRaw(c as Component)];\n }),\n );\n\n app = Object.assign(baseApp, {\n ...localState,\n getRoute(href: Href): Component | undefined {\n return routes[href];\n },\n } as unknown as AppV1<Args, Outputs, UiState, Href, Extend>);\n });\n } else if (platforma.apiVersion === 2) {\n await platforma.loadBlockState().then((stateOrError) => {\n const state = unwrapResult(stateOrError);\n plugin.loaded = true;\n const baseApp = createAppV2<Args, Outputs, UiState, Href>(state, platforma, settings);\n\n const localState = extendApp(baseApp);\n\n const routes = Object.fromEntries(\n Object.entries(localState.routes as Routes<Href>).map(([href, component]) => {\n const c = typeof component === \"function\" ? component() : component;\n return [href, markRaw(c as Component)];\n }),\n );\n\n app = Object.assign(baseApp, {\n ...localState,\n getRoute(href: Href): Component | undefined {\n return routes[href];\n },\n } as unknown as AppV2<Args, Outputs, UiState, Href, Extend>);\n });\n }\n };\n\n const plugin = reactive({\n apiVersion: platforma.apiVersion ?? 1,\n featureFlags: platforma.blockModelInfo.featureFlags,\n loaded: false,\n error: undefined as unknown,\n useApp<PageHref extends Href = Href>() {\n return notEmpty(app, \"App is not loaded\") as\n | AppV1<Args, Outputs, UiState, PageHref, Extend>\n | AppV2<Args, Outputs, UiState, PageHref, Extend>;\n },\n install(app: VueApp) {\n app.provide(pluginKey, this);\n loadApp().catch((err) => {\n console.error(\"load initial state error\", err);\n plugin.error = err;\n });\n },\n });\n\n return plugin as\n | SdkPluginV1<Args, Outputs, UiState, Href, Extend>\n | SdkPluginV2<Args, Outputs, UiState, Href, Extend>;\n}\n\nexport function defineAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n Extend extends ExtendSettings<Href> = ExtendSettings<Href>,\n>(\n platforma: PlatformaV3<Data, Args, Outputs, Href, Plugins> & {\n blockModelInfo: BlockModelInfo;\n },\n extendApp: (app: BaseAppV3<Data, Args, Outputs, Href, Plugins>) => Extend,\n settings: AppSettings = {},\n): SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend> {\n let app: AppV3<Data, Args, Outputs, Href, Plugins, Extend> | undefined = undefined;\n\n // Captured during install() so V3 can provide plugin data access after async load\n let vueAppInstance: VueApp | undefined;\n\n const runtimeApiVersion = 3;\n const blockRequestedApiVersion = getPlatformaApiVersion();\n\n const loadApp = async () => {\n if (blockRequestedApiVersion !== runtimeApiVersion) {\n throw new Error(`Block requested API version ${blockRequestedApiVersion} but runtime API version is ${runtimeApiVersion}.\n Please update the desktop app to use the latest API version.`);\n }\n\n await platforma.loadBlockState().then((stateOrError) => {\n const state = unwrapResult(stateOrError);\n plugin.loaded = true;\n const { app: baseApp, pluginAccess } = createAppV3<Data, Args, Outputs, Href, Plugins>(\n state,\n platforma,\n settings,\n );\n\n if (!vueAppInstance) {\n throw new Error(\n \"Plugin data injection failed: Vue app instance not captured during install()\",\n );\n }\n vueAppInstance.provide(pluginDataKey, pluginAccess);\n\n const localState = extendApp(baseApp);\n\n const routes = Object.fromEntries(\n Object.entries(localState.routes as Routes<Href>).map(([href, component]) => {\n const c = typeof component === \"function\" ? component() : component;\n return [href, markRaw(c as Component)];\n }),\n );\n\n app = Object.assign(baseApp, {\n ...localState,\n getRoute(href: Href): Component | undefined {\n return routes[href];\n },\n } as AppV3<Data, Args, Outputs, Href, Plugins, Extend>);\n });\n };\n\n const plugin = reactive({\n apiVersion: 3,\n featureFlags: platforma.blockModelInfo.featureFlags,\n loaded: false,\n error: undefined,\n useApp<PageHref extends Href = Href>() {\n return notEmpty(app, \"App is not loaded\") as AppV3<\n Data,\n Args,\n Outputs,\n PageHref,\n Plugins,\n Extend\n >;\n },\n install(app: VueApp) {\n vueAppInstance = app;\n app.provide(pluginKey, this);\n loadApp().catch((err) => {\n console.error(\"load initial state error\", err);\n plugin.error = err;\n });\n },\n });\n\n return plugin as SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend>;\n}\n\nexport type AppV1<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = BaseAppV1<Args, Outputs, UiState, Href> &\n Reactive<Omit<Local, \"routes\">> & { getRoute(href: Href): Component | undefined };\n\nexport type AppV2<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = BaseAppV2<Args, Outputs, UiState, Href> &\n Reactive<Omit<Local, \"routes\">> & { getRoute(href: Href): Component | undefined };\n\nexport type AppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = NonNullable<unknown>,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = BaseAppV3<Data, Args, Outputs, Href, Plugins> &\n Reactive<Omit<Local, \"routes\">> & { getRoute(href: Href): Component | undefined };\n\n// ---------------------------------------------------------------------------\n// SdkPlugin types\n// ---------------------------------------------------------------------------\n\nexport type SdkPluginV1<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = {\n apiVersion: 1;\n featureFlags: BlockCodeKnownFeatureFlags;\n loaded: boolean;\n error: unknown;\n useApp<PageHref extends Href = Href>(): AppV1<Args, Outputs, UiState, PageHref, Local>;\n install(app: VueApp): void;\n};\n\nexport type SdkPluginV2<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = {\n apiVersion: 2;\n featureFlags: BlockCodeKnownFeatureFlags;\n loaded: boolean;\n error: unknown;\n useApp<PageHref extends Href = Href>(): AppV2<Args, Outputs, UiState, PageHref, Local>;\n install(app: VueApp): void;\n};\n\nexport type SdkPluginV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = {\n apiVersion: 3;\n featureFlags: BlockCodeKnownFeatureFlags;\n loaded: boolean;\n error: unknown;\n useApp<PageHref extends Href = Href>(): AppV3<Data, Args, Outputs, PageHref, Plugins, Local>;\n install(app: VueApp): void;\n};\n\nexport type SdkPlugin = SdkPluginV1 | SdkPluginV2 | SdkPluginV3;\n"],"mappings":"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"}
1
+ {"version":3,"file":"defineApp.js","names":[],"sources":["../src/defineApp.ts"],"sourcesContent":["import { notEmpty } from \"@milaboratories/helpers\";\nimport type {\n PlatformaExtended,\n PlatformaV3,\n PlatformaV1,\n PlatformaV2,\n BlockCodeKnownFeatureFlags,\n UiServices as AllUiServices,\n} from \"@platforma-sdk/model\";\nimport {\n getPlatformaApiVersion,\n unwrapResult,\n type BlockOutputsBase,\n type BlockModelInfo,\n} from \"@platforma-sdk/model\";\nimport type { App as VueApp, Component, Reactive } from \"vue\";\nimport { inject, markRaw, reactive } from \"vue\";\nimport { createAppV1, type BaseAppV1 } from \"./internal/createAppV1\";\nimport { createAppV2, type BaseAppV2 } from \"./internal/createAppV2\";\nimport { createAppV3, type BaseAppV3 } from \"./internal/createAppV3\";\nimport type { AppSettings, ExtendSettings, Routes } from \"./types\";\n\nconst pluginKey = Symbol(\"sdk-vue\");\nexport const pluginDataKey = Symbol(\"plugin-data-access\");\n\nexport function useSdkPlugin(): SdkPlugin {\n return inject(pluginKey)!;\n}\n\nexport function useFeatureFlags() {\n const sdk = useSdkPlugin();\n return sdk.featureFlags;\n}\n\nexport function defineApp<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Extend extends ExtendSettings<Href> = ExtendSettings<Href>,\n>(\n platforma: PlatformaV1<Args, Outputs, UiState, Href> & {\n blockModelInfo: BlockModelInfo;\n },\n extendApp: (app: BaseAppV1<Args, Outputs, UiState, Href>) => Extend,\n settings?: AppSettings,\n): SdkPluginV1<Args, Outputs, UiState, Href, Extend>;\n\nexport function defineApp<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Extend extends ExtendSettings<Href> = ExtendSettings<Href>,\n>(\n platforma: PlatformaV2<Args, Outputs, UiState, Href> & {\n blockModelInfo: BlockModelInfo;\n },\n extendApp: (app: BaseAppV2<Args, Outputs, UiState, Href>) => Extend,\n settings?: AppSettings,\n): SdkPluginV2<Args, Outputs, UiState, Href, Extend>;\n\nexport function defineApp<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Extend extends ExtendSettings<Href> = ExtendSettings<Href>,\n>(\n platforma: PlatformaExtended<\n PlatformaV1<Args, Outputs, UiState, Href> | PlatformaV2<Args, Outputs, UiState, Href>\n >,\n\n //\n extendApp: (app: any) => Extend,\n settings: AppSettings = {},\n):\n | SdkPluginV1<Args, Outputs, UiState, Href, Extend>\n | SdkPluginV2<Args, Outputs, UiState, Href, Extend> {\n let app:\n | AppV1<Args, Outputs, UiState, Href, Extend>\n | AppV2<Args, Outputs, UiState, Href, Extend>\n | undefined = undefined;\n\n const runtimeApiVersion = platforma.apiVersion ?? 1; // undefined means 1 (backward compatibility)\n const blockRequestedApiVersion = getPlatformaApiVersion();\n\n const loadApp = async () => {\n if (blockRequestedApiVersion !== runtimeApiVersion) {\n throw new Error(`Block requested API version ${blockRequestedApiVersion} but runtime API version is ${runtimeApiVersion}.\n Please update the desktop app to use the latest API version.`);\n }\n\n if (platforma.apiVersion === undefined || platforma.apiVersion === 1) {\n await platforma.loadBlockState().then((state) => {\n plugin.loaded = true;\n const baseApp = createAppV1<Args, Outputs, UiState, Href>(state, platforma, settings);\n\n const localState = extendApp(baseApp);\n\n const routes = Object.fromEntries(\n Object.entries(localState.routes as Routes<Href>).map(([href, component]) => {\n const c = typeof component === \"function\" ? component() : component;\n return [href, markRaw(c as Component)];\n }),\n );\n\n app = Object.assign(baseApp, {\n ...localState,\n getRoute(href: Href): Component | undefined {\n return routes[href];\n },\n } as unknown as AppV1<Args, Outputs, UiState, Href, Extend>);\n });\n } else if (platforma.apiVersion === 2) {\n await platforma.loadBlockState().then((stateOrError) => {\n const state = unwrapResult(stateOrError);\n plugin.loaded = true;\n const baseApp = createAppV2<Args, Outputs, UiState, Href>(state, platforma, settings);\n\n const localState = extendApp(baseApp);\n\n const routes = Object.fromEntries(\n Object.entries(localState.routes as Routes<Href>).map(([href, component]) => {\n const c = typeof component === \"function\" ? component() : component;\n return [href, markRaw(c as Component)];\n }),\n );\n\n app = Object.assign(baseApp, {\n ...localState,\n getRoute(href: Href): Component | undefined {\n return routes[href];\n },\n } as unknown as AppV2<Args, Outputs, UiState, Href, Extend>);\n });\n }\n };\n\n const plugin = reactive({\n apiVersion: platforma.apiVersion ?? 1,\n featureFlags: platforma.blockModelInfo.featureFlags,\n loaded: false,\n error: undefined as unknown,\n useApp<PageHref extends Href = Href>() {\n return notEmpty(app, \"App is not loaded\") as\n | AppV1<Args, Outputs, UiState, PageHref, Extend>\n | AppV2<Args, Outputs, UiState, PageHref, Extend>;\n },\n install(app: VueApp) {\n app.provide(pluginKey, this);\n loadApp().catch((err) => {\n console.error(\"load initial state error\", err);\n plugin.error = err;\n });\n },\n });\n\n return plugin as\n | SdkPluginV1<Args, Outputs, UiState, Href, Extend>\n | SdkPluginV2<Args, Outputs, UiState, Href, Extend>;\n}\n\nexport function defineAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n Extend extends ExtendSettings<Href> = ExtendSettings<Href>,\n>(\n platforma: PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices> & {\n blockModelInfo: BlockModelInfo;\n },\n extendApp: (app: BaseAppV3<Data, Args, Outputs, Href, Plugins, UiServices>) => Extend,\n settings: AppSettings = {},\n): SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices> {\n let app: AppV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices> | undefined = undefined;\n\n // Captured during install() so V3 can provide plugin data access after async load\n let vueAppInstance: VueApp | undefined;\n\n const runtimeApiVersion = 3;\n const blockRequestedApiVersion = getPlatformaApiVersion();\n\n const loadApp = async () => {\n if (blockRequestedApiVersion !== runtimeApiVersion) {\n throw new Error(`Block requested API version ${blockRequestedApiVersion} but runtime API version is ${runtimeApiVersion}.\n Please update the desktop app to use the latest API version.`);\n }\n\n await platforma.loadBlockState().then((stateOrError) => {\n const state = unwrapResult(stateOrError);\n plugin.loaded = true;\n const { app: baseApp, pluginAccess } = createAppV3<\n Data,\n Args,\n Outputs,\n Href,\n Plugins,\n UiServices\n >(state, platforma, settings);\n\n if (!vueAppInstance) {\n throw new Error(\n \"Plugin data injection failed: Vue app instance not captured during install()\",\n );\n }\n vueAppInstance.provide(pluginDataKey, pluginAccess);\n\n const localState = extendApp(baseApp);\n\n const routes = Object.fromEntries(\n Object.entries(localState.routes as Routes<Href>).map(([href, component]) => {\n const c = typeof component === \"function\" ? component() : component;\n return [href, markRaw(c as Component)];\n }),\n );\n\n app = Object.assign(baseApp, {\n ...localState,\n getRoute(href: Href): Component | undefined {\n return routes[href];\n },\n } as AppV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices>);\n });\n };\n\n const plugin = reactive({\n apiVersion: 3,\n featureFlags: platforma.blockModelInfo.featureFlags,\n loaded: false,\n error: undefined,\n useApp<PageHref extends Href = Href>() {\n return notEmpty(app, \"App is not loaded\") as AppV3<\n Data,\n Args,\n Outputs,\n PageHref,\n Plugins,\n Extend,\n UiServices\n >;\n },\n install(app: VueApp) {\n vueAppInstance = app;\n app.provide(pluginKey, this);\n loadApp().catch((err) => {\n console.error(\"load initial state error\", err);\n plugin.error = err;\n });\n },\n });\n\n return plugin as SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices>;\n}\n\nexport type AppV1<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = BaseAppV1<Args, Outputs, UiState, Href> &\n Reactive<Omit<Local, \"routes\">> & { getRoute(href: Href): Component | undefined };\n\nexport type AppV2<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = BaseAppV2<Args, Outputs, UiState, Href> &\n Reactive<Omit<Local, \"routes\">> & { getRoute(href: Href): Component | undefined };\n\nexport type AppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = NonNullable<unknown>,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n> = BaseAppV3<Data, Args, Outputs, Href, Plugins, UiServices> &\n Reactive<Omit<Local, \"routes\">> & { getRoute(href: Href): Component | undefined };\n\n// ---------------------------------------------------------------------------\n// SdkPlugin types\n// ---------------------------------------------------------------------------\n\nexport type SdkPluginV1<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = {\n apiVersion: 1;\n featureFlags: BlockCodeKnownFeatureFlags;\n loaded: boolean;\n error: unknown;\n useApp<PageHref extends Href = Href>(): AppV1<Args, Outputs, UiState, PageHref, Local>;\n install(app: VueApp): void;\n};\n\nexport type SdkPluginV2<\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n UiState = unknown,\n Href extends `/${string}` = `/${string}`,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n> = {\n apiVersion: 2;\n featureFlags: BlockCodeKnownFeatureFlags;\n loaded: boolean;\n error: unknown;\n useApp<PageHref extends Href = Href>(): AppV2<Args, Outputs, UiState, PageHref, Local>;\n install(app: VueApp): void;\n};\n\nexport type SdkPluginV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n Local extends ExtendSettings<Href> = ExtendSettings<Href>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n> = {\n apiVersion: 3;\n featureFlags: BlockCodeKnownFeatureFlags;\n loaded: boolean;\n error: unknown;\n useApp<PageHref extends Href = Href>(): AppV3<\n Data,\n Args,\n Outputs,\n PageHref,\n Plugins,\n Local,\n UiServices\n >;\n install(app: VueApp): void;\n};\n\nexport type SdkPlugin = SdkPluginV1 | SdkPluginV2 | SdkPluginV3;\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { Mutable } from '@milaboratories/helpers';
2
2
  import { NavigationState, BlockOutputsBase, BlockStateV3, PlatformaV3, ValueWithUTag, AuthorMarker, PlatformaExtended, InferPluginHandles } from '@platforma-sdk/model';
3
+ import { UiServices as AllUiServices } from '@milaboratories/pl-model-common';
3
4
  import { OutputValues, OutputErrors, AppSettings } from '../types';
4
5
  import { PluginAccess } from '../usePlugin';
5
6
  export declare const patchPoolingDelay = 150;
@@ -18,7 +19,7 @@ export declare const createNextAuthorMarker: (marker: AuthorMarker | undefined)
18
19
  *
19
20
  * @returns A reactive application object with methods, getters, and state.
20
21
  */
21
- export declare function createAppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>>(state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>, platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins>>, settings: AppSettings): {
22
+ export declare function createAppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>, UiServices extends Partial<AllUiServices> = Partial<AllUiServices>>(state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>, platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices>>, settings: AppSettings): {
22
23
  app: {
23
24
  error: string;
24
25
  model: {
@@ -33,6 +34,7 @@ export declare function createAppV3<Data = unknown, Args = unknown, Outputs exte
33
34
  navigationState: NavigationState<Href>;
34
35
  };
35
36
  plugins: import('vue').UnwrapRef<InferPluginHandles<Plugins>>;
37
+ services: import('vue').UnwrapRef<import('vue').Raw<UiServices>>;
36
38
  queryParams: import('../types').ParseQuery<Href>;
37
39
  href: Href;
38
40
  hasErrors: boolean;
@@ -58,5 +60,5 @@ export declare function createAppV3<Data = unknown, Args = unknown, Outputs exte
58
60
  };
59
61
  pluginAccess: PluginAccess;
60
62
  };
61
- export type BaseAppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>> = ReturnType<typeof createAppV3<Data, Args, Outputs, Href, Plugins>>["app"];
63
+ export type BaseAppV3<Data = unknown, Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, Href extends `/${string}` = `/${string}`, Plugins extends Record<string, unknown> = Record<string, unknown>, UiServices extends Partial<AllUiServices> = Partial<AllUiServices>> = ReturnType<typeof createAppV3<Data, Args, Outputs, Href, Plugins, UiServices>>["app"];
62
64
  //# sourceMappingURL=createAppV3.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createAppV3.d.ts","sourceRoot":"","sources":["../../src/internal/createAppV3.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAKnB,MAAM,sBAAsB,CAAC;AAW9B,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAMxE,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAUrC,eAAO,MAAM,sBAAsB,GAAI,QAAQ,YAAY,GAAG,SAAS,KAAG,YAGxE,CAAC;AAUH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,IAAI,GAAG,OAAO,EACd,IAAI,GAAG,OAAO,EACd,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,EACxC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjE,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EACvD,SAAS,EAAE,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,EAC7E,QAAQ,EAAE,WAAW;;eAuHZ,MAAM;;;;;;;;qBAvDJ,OAAO,CAAC,OAAO,CAAC;0BACX,OAAO;6BACJ,eAAe,CAAC,IAAI,CAAC;;;;;;;yBA+IkB,IAAI;oCAEf,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAK3E;;;;;;WAMG;uBACY,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAMtD;;;;;WAKG;yBACc,IAAI;;;;EAkHxB;AAED,MAAM,MAAM,SAAS,CACnB,IAAI,GAAG,OAAO,EACd,IAAI,GAAG,OAAO,EACd,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,EACxC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D,UAAU,CAAC,OAAO,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"createAppV3.d.ts","sourceRoot":"","sources":["../../src/internal/createAppV3.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAMnB,MAAM,sBAAsB,CAAC;AAW9B,OAAO,EAAE,KAAK,UAAU,IAAI,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAInF,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAMxE,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAWrC,eAAO,MAAM,sBAAsB,GAAI,QAAQ,YAAY,GAAG,SAAS,KAAG,YAGxE,CAAC;AAUH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,IAAI,GAAG,OAAO,EACd,IAAI,GAAG,OAAO,EACd,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,EACxC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,UAAU,SAAS,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,EAElE,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EACvD,SAAS,EAAE,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,EACzF,QAAQ,EAAE,WAAW;;eAuHZ,MAAM;;;;;;;;qBAvDJ,OAAO,CAAC,OAAO,CAAC;0BACX,OAAO;6BACJ,eAAe,CAAC,IAAI,CAAC;;;;;;;;yBA8IkB,IAAI;oCAEf,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAK3E;;;;;;WAMG;uBACY,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAMtD;;;;;WAKG;yBACc,IAAI;;;;EAgIxB;AAED,MAAM,MAAM,SAAS,CACnB,IAAI,GAAG,OAAO,EACd,IAAI,GAAG,OAAO,EACd,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE,EACxC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,UAAU,SAAS,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,IAChE,UAAU,CAAC,OAAO,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC"}
@@ -5,15 +5,16 @@ import "../lib/util/helpers/dist/index.js";
5
5
  import { MultiError as r, ensureOutputHasStableFlag as i } from "../utils.js";
6
6
  import { parseQuery as a } from "../urls.js";
7
7
  import { UpdateSerializer as o } from "./UpdateSerializer.js";
8
- import { computed as s, reactive as c, ref as l } from "vue";
9
- import { deriveDataFromStorage as u, getPluginData as d, hasAbortError as f, isPluginOutputKey as p, pluginOutputPrefix as m, unwrapResult as h } from "@platforma-sdk/model";
10
- import { watchIgnorable as g } from "@vueuse/core";
11
- import { applyPatch as _ } from "fast-json-patch";
12
- const v = (e) => ({
8
+ import { createUiServiceRegistry as s } from "./service_factories.js";
9
+ import { computed as c, markRaw as l, reactive as u, ref as d } from "vue";
10
+ import { buildServices as f, createNodeServiceProxy as p, deriveDataFromStorage as m, getPluginData as h, hasAbortError as g, isPluginOutputKey as _, pluginOutputPrefix as v, unwrapResult as y } from "@platforma-sdk/model";
11
+ import { watchIgnorable as b } from "@vueuse/core";
12
+ import { applyPatch as x } from "fast-json-patch";
13
+ const S = (e) => ({
13
14
  authorId: e?.authorId ?? t(),
14
15
  localVersion: (e?.localVersion ?? 0) + 1
15
16
  });
16
- var y = (e) => {
17
+ var C = (e) => {
17
18
  try {
18
19
  return JSON.stringify(e, null, 2);
19
20
  } catch (e) {
@@ -34,130 +35,132 @@ var y = (e) => {
34
35
  *
35
36
  * @returns A reactive application object with methods, getters, and state.
36
37
  */
37
- function b(b, x, S) {
38
- let C = (e, ...t) => {
39
- S.debug && console.log(`%c>>> %c${e}`, "color: orange; font-weight: bold", "color: orange", ...t.map((e) => y(e)));
40
- }, w = (e, ...t) => {
41
- console.error(`%c>>> %c${e}`, "color: red; font-weight: bold", "color: red", ...t.map((e) => y(e)));
42
- }, T = {
38
+ function w(w, T, E) {
39
+ let D = (e, ...t) => {
40
+ E.debug && console.log(`%c>>> %c${e}`, "color: orange; font-weight: bold", "color: orange", ...t.map((e) => C(e)));
41
+ }, O = (e, ...t) => {
42
+ console.error(`%c>>> %c${e}`, "color: red; font-weight: bold", "color: red", ...t.map((e) => C(e)));
43
+ }, k = {
43
44
  isExternalSnapshot: !1,
44
45
  author: {
45
46
  authorId: t(),
46
47
  localVersion: 0
47
48
  }
48
- }, E = () => (T.author = v(T.author), C("nextAuthorMarker", T.author), T.author), D = l(!1), O = l(b.uTag), k = S.debounceSpan ?? 200, A = new o({ debounceSpan: k }), j = /* @__PURE__ */ new Map(), M = (e) => {
49
- let t = j.get(e);
50
- return t || (t = new o({ debounceSpan: k }), j.set(e, t)), t;
51
- }, N = new o({ debounceSpan: k }), P = /* @__PURE__ */ new Map(), F = l(b.value), I = async (e) => x.mutateStorage({
49
+ }, A = () => (k.author = S(k.author), D("nextAuthorMarker", k.author), k.author), j = d(!1), M = d(w.uTag), N = E.debounceSpan ?? 200, P = new o({ debounceSpan: N }), F = /* @__PURE__ */ new Map(), I = (e) => {
50
+ let t = F.get(e);
51
+ return t || (t = new o({ debounceSpan: N }), F.set(e, t)), t;
52
+ }, L = new o({ debounceSpan: N }), R = /* @__PURE__ */ new Map(), z = d(w.value), B = async (e) => T.mutateStorage({
52
53
  operation: "update-block-data",
53
54
  value: e
54
- }, E()), L = async (e, t) => x.mutateStorage({
55
+ }, A()), V = async (e, t) => T.mutateStorage({
55
56
  operation: "update-plugin-data",
56
57
  pluginId: e,
57
58
  value: t
58
- }, E()), R = async (e) => x.setNavigationState(e), z = s(() => {
59
- let e = Object.entries(F.value.outputs).filter(([e]) => !p(e)).map(([e, t]) => x.blockModelInfo.outputs[e]?.withStatus ? [e, i(t)] : [e, t.ok && t.value !== void 0 ? t.value : void 0]);
59
+ }, A()), H = async (e) => T.setNavigationState(e), U = c(() => {
60
+ let e = Object.entries(z.value.outputs).filter(([e]) => !_(e)).map(([e, t]) => T.blockModelInfo.outputs[e]?.withStatus ? [e, i(t)] : [e, t.ok && t.value !== void 0 ? t.value : void 0]);
60
61
  return Object.fromEntries(e);
61
- }), B = s(() => {
62
- let e = Object.entries(F.value.outputs).filter(([e]) => !p(e)).map(([e, t]) => [e, t && t.ok === !1 ? new r(t.errors) : void 0]);
62
+ }), W = c(() => {
63
+ let e = Object.entries(z.value.outputs).filter(([e]) => !_(e)).map(([e, t]) => [e, t && t.ok === !1 ? new r(t.errors) : void 0]);
63
64
  return Object.fromEntries(e);
64
- }), V = c({
65
+ }), G = u({
65
66
  apiVersion: 3,
66
67
  error: "",
67
68
  model: {
68
- data: n(u(F.value.blockStorage)),
69
- outputs: z,
70
- outputErrors: B
69
+ data: n(m(z.value.blockStorage)),
70
+ outputs: U,
71
+ outputErrors: W
71
72
  }
72
- }), { ignoreUpdates: H } = g(() => V.model, (e) => {
73
+ }), { ignoreUpdates: K } = b(() => G.model, (e) => {
73
74
  let t = n(e);
74
- C("setDataQueue appModel.model, data", t.data), A.run(() => I(t.data).then(h));
75
- }, { deep: !0 }), U = (e) => {
76
- C("updateAppModel", e), V.model.data = n(e.data);
75
+ D("setDataQueue appModel.model, data", t.data), P.run(() => B(t.data).then(y));
76
+ }, { deep: !0 }), q = (e) => {
77
+ D("updateAppModel", e), G.model.data = n(e.data);
77
78
  };
78
79
  (async () => {
79
80
  for (window.addEventListener("beforeunload", () => {
80
- D.value = !0, x.dispose().then(h).catch((e) => {
81
- w("error in dispose", e);
81
+ j.value = !0, Promise.allSettled([Z.dispose(), T.dispose().then(y)]).catch((e) => {
82
+ O("error in dispose", e);
82
83
  });
83
- }); !D.value;) try {
84
- let e = await x.getPatches(O.value).then(h);
85
- if (C("patches.length", e.value.length), C("uTagRef.value", O.value), C("patches.uTag", e.uTag), C("patches.author", e.author), C("data.author", T.author), O.value = e.uTag, e.value.length === 0) {
84
+ }); !j.value;) try {
85
+ let e = await T.getPatches(M.value).then(y);
86
+ if (D("patches.length", e.value.length), D("uTagRef.value", M.value), D("patches.uTag", e.uTag), D("patches.author", e.author), D("data.author", k.author), M.value = e.uTag, e.value.length === 0) {
86
87
  await new Promise((e) => setTimeout(e, 150));
87
88
  continue;
88
89
  }
89
- let t = T.author?.authorId !== e.author?.authorId;
90
- t || T.isExternalSnapshot ? (C("got external changes, applying them to the snapshot", e.value), H(() => {
91
- F.value = _(F.value, e.value, !1, !1).newDocument, U({ data: u(F.value.blockStorage) });
92
- for (let [e, t] of P) t.ignoreUpdates(() => {
93
- t.model.data = n(d(F.value.blockStorage, e));
90
+ let t = k.author?.authorId !== e.author?.authorId;
91
+ t || k.isExternalSnapshot ? (D("got external changes, applying them to the snapshot", e.value), K(() => {
92
+ z.value = x(z.value, e.value, !1, !1).newDocument, q({ data: m(z.value.blockStorage) });
93
+ for (let [e, t] of R) t.ignoreUpdates(() => {
94
+ t.model.data = n(h(z.value.blockStorage, e));
94
95
  });
95
- T.isExternalSnapshot = t;
96
- })) : (C("outputs changed", e.value), H(() => {
97
- F.value = _(F.value, e.value).newDocument;
96
+ k.isExternalSnapshot = t;
97
+ })) : (D("outputs changed", e.value), K(() => {
98
+ z.value = x(z.value, e.value).newDocument;
98
99
  })), await new Promise((e) => setTimeout(e, 150));
99
100
  } catch (e) {
100
- f(e) ? (C("patches loop aborted"), D.value = !0) : (w("error in patches loop", e), await new Promise((e) => setTimeout(e, 1e3)));
101
+ g(e) ? (D("patches loop aborted"), j.value = !0) : (O("error in patches loop", e), await new Promise((e) => setTimeout(e, 1e3)));
101
102
  }
102
103
  })();
103
- let W = () => n(V.model.data), G = () => n(F.value.navigationState), K = {
104
- cloneData: W,
105
- cloneNavigationState: G,
104
+ let J = () => n(G.model.data), Y = () => n(z.value.navigationState), X = {
105
+ cloneData: J,
106
+ cloneNavigationState: Y,
106
107
  updateData(e) {
107
- let t = e(W());
108
- return C("updateData", t), V.model.data = t, A.run(() => I(t).then(h));
108
+ let t = e(J());
109
+ return D("updateData", t), G.model.data = t, P.run(() => B(t).then(y));
109
110
  },
110
111
  navigateTo(e) {
111
- let t = G();
112
- return t.href = e, N.run(() => R(t).then(h));
112
+ let t = Y();
113
+ return t.href = e, L.run(() => H(t).then(y));
113
114
  },
114
115
  async allSettled() {
115
116
  await e(0);
116
- let t = [A.allSettled(), ...Array.from(j.values()).map((e) => e.allSettled())];
117
+ let t = [P.allSettled(), ...Array.from(F.values()).map((e) => e.allSettled())];
117
118
  await Promise.all(t);
118
119
  }
119
- }, q = (e) => {
120
- let t = m(e), a = s(() => {
120
+ }, Z = s({ proxy: p(T.serviceDispatch) }), Q = f(T.serviceDispatch, Z), ee = (e) => {
121
+ let t = v(e), a = c(() => {
121
122
  let e = {};
122
- for (let [n, r] of Object.entries(F.value.outputs)) {
123
+ for (let [n, r] of Object.entries(z.value.outputs)) {
123
124
  if (!n.startsWith(t)) continue;
124
125
  let a = n.slice(t.length);
125
- x.blockModelInfo.outputs[n]?.withStatus ? e[a] = r ? i(r) : void 0 : e[a] = r.ok && r.value !== void 0 ? r.value : void 0;
126
+ T.blockModelInfo.outputs[n]?.withStatus ? e[a] = r ? i(r) : void 0 : e[a] = r.ok && r.value !== void 0 ? r.value : void 0;
126
127
  }
127
128
  return e;
128
- }), o = s(() => {
129
+ }), o = c(() => {
129
130
  let e = {};
130
- for (let [n, i] of Object.entries(F.value.outputs)) n.startsWith(t) && (e[n.slice(t.length)] = i && i.ok === !1 ? new r(i.errors) : void 0);
131
+ for (let [n, i] of Object.entries(z.value.outputs)) n.startsWith(t) && (e[n.slice(t.length)] = i && i.ok === !1 ? new r(i.errors) : void 0);
131
132
  return e;
132
- }), l = c({
133
- data: n(d(F.value.blockStorage, e)),
133
+ }), s = u({
134
+ data: n(h(z.value.blockStorage, e)),
134
135
  outputs: a,
135
136
  outputErrors: o
136
- }), { ignoreUpdates: u } = g(() => l.data, (t) => {
137
- t !== void 0 && (C("plugin setData", e, t), M(e).run(() => L(e, n(t)).then(h)));
137
+ }), { ignoreUpdates: d } = b(() => s.data, (t) => {
138
+ t !== void 0 && (D("plugin setData", e, t), I(e).run(() => V(e, n(t)).then(y)));
138
139
  }, { deep: !0 });
139
140
  return {
140
- model: l,
141
- ignoreUpdates: u
141
+ model: s,
142
+ services: l(Q),
143
+ ignoreUpdates: d
142
144
  };
143
- }, J = { getOrCreatePluginState(e) {
144
- let t = P.get(e);
145
+ }, te = { getOrCreatePluginState(e) {
146
+ let t = R.get(e);
145
147
  if (t) return t;
146
- let n = q(e);
147
- return P.set(e, n), n;
148
- } }, Y = {
149
- closedRef: D,
150
- snapshot: F,
151
- plugins: Object.fromEntries(x.blockModelInfo.pluginIds.map((e) => [e, { handle: e }])),
152
- queryParams: s(() => a(F.value.navigationState.href)),
153
- href: s(() => F.value.navigationState.href),
154
- hasErrors: s(() => Object.values(F.value.outputs).some((e) => !e?.ok))
155
- }, X = Object.assign(c(Object.assign(V, Y)), K);
156
- return S.debug && (globalThis.__block_app__ = X), {
157
- app: X,
158
- pluginAccess: J
148
+ let n = ee(e);
149
+ return R.set(e, n), n;
150
+ } }, ne = {
151
+ closedRef: j,
152
+ snapshot: z,
153
+ plugins: Object.fromEntries(T.blockModelInfo.pluginIds.map((e) => [e, { handle: e }])),
154
+ services: l(Q),
155
+ queryParams: c(() => a(z.value.navigationState.href)),
156
+ href: c(() => z.value.navigationState.href),
157
+ hasErrors: c(() => Object.values(z.value.outputs).some((e) => !e?.ok))
158
+ }, $ = Object.assign(u(Object.assign(G, ne)), X);
159
+ return E.debug && (globalThis.__block_app__ = $), {
160
+ app: $,
161
+ pluginAccess: te
159
162
  };
160
163
  }
161
- export { b as createAppV3 };
164
+ export { w as createAppV3 };
162
165
 
163
166
  //# sourceMappingURL=createAppV3.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createAppV3.js","names":[],"sources":["../../src/internal/createAppV3.ts"],"sourcesContent":["import { deepClone, delay, uniqueId } from \"@milaboratories/helpers\";\nimport type { Mutable } from \"@milaboratories/helpers\";\nimport type {\n NavigationState,\n BlockOutputsBase,\n BlockStateV3,\n PlatformaV3,\n ValueWithUTag,\n AuthorMarker,\n PlatformaExtended,\n InferPluginHandles,\n PluginHandle,\n InferFactoryData,\n InferFactoryOutputs,\n PluginFactoryLike,\n} from \"@platforma-sdk/model\";\nimport {\n hasAbortError,\n unwrapResult,\n deriveDataFromStorage,\n getPluginData,\n isPluginOutputKey,\n pluginOutputPrefix,\n} from \"@platforma-sdk/model\";\nimport type { Ref } from \"vue\";\nimport { reactive, computed, ref } from \"vue\";\nimport type { OutputValues, OutputErrors, AppSettings } from \"../types\";\nimport { parseQuery } from \"../urls\";\nimport { ensureOutputHasStableFlag, MultiError } from \"../utils\";\nimport { applyPatch } from \"fast-json-patch\";\nimport { UpdateSerializer } from \"./UpdateSerializer\";\nimport { watchIgnorable } from \"@vueuse/core\";\nimport type { PluginState, PluginAccess } from \"../usePlugin\";\n\nexport const patchPoolingDelay = 150;\n\n/** Internal per-plugin state with reconciliation support. */\ninterface InternalPluginState<Data = unknown, Outputs = unknown> extends PluginState<\n Data,\n Outputs\n> {\n readonly ignoreUpdates: (fn: () => void) => void;\n}\n\nexport const createNextAuthorMarker = (marker: AuthorMarker | undefined): AuthorMarker => ({\n authorId: marker?.authorId ?? uniqueId(),\n localVersion: (marker?.localVersion ?? 0) + 1,\n});\n\nconst stringifyForDebug = (v: unknown) => {\n try {\n return JSON.stringify(v, null, 2);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n};\n\n/**\n * Creates an application instance with reactive state management, outputs, and methods for state updates and navigation.\n *\n * @template Args - The type of arguments used in the application.\n * @template Outputs - The type of block outputs extending `BlockOutputsBase`.\n * @template Data - The type of the block data.\n * @template Href - The type of navigation href, defaulting to a string starting with `/`.\n *\n * @param state - Initial state of the application, including args, outputs, UI state, and navigation state.\n * @param platforma - A platform interface for interacting with block states.\n * @param settings - Application settings, such as debug flags.\n *\n * @returns A reactive application object with methods, getters, and state.\n */\nexport function createAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n>(\n state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>,\n platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins>>,\n settings: AppSettings,\n) {\n const debug = (msg: string, ...rest: unknown[]) => {\n if (settings.debug) {\n console.log(\n `%c>>> %c${msg}`,\n \"color: orange; font-weight: bold\",\n \"color: orange\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n }\n };\n\n const error = (msg: string, ...rest: unknown[]) => {\n console.error(\n `%c>>> %c${msg}`,\n \"color: red; font-weight: bold\",\n \"color: red\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n };\n\n const data = {\n isExternalSnapshot: false,\n author: {\n authorId: uniqueId(),\n localVersion: 0,\n },\n };\n\n const nextAuthorMarker = () => {\n data.author = createNextAuthorMarker(data.author);\n debug(\"nextAuthorMarker\", data.author);\n return data.author;\n };\n\n const closedRef = ref(false);\n\n const uTagRef = ref(state.uTag);\n\n const debounceSpan = settings.debounceSpan ?? 200;\n\n const setDataQueue = new UpdateSerializer({ debounceSpan });\n const pluginDataQueues = new Map<PluginHandle, UpdateSerializer>();\n const getPluginDataQueue = (handle: PluginHandle): UpdateSerializer => {\n let queue = pluginDataQueues.get(handle);\n if (!queue) {\n queue = new UpdateSerializer({ debounceSpan });\n pluginDataQueues.set(handle, queue);\n }\n return queue;\n };\n const setNavigationStateQueue = new UpdateSerializer({ debounceSpan });\n\n /** Lazily-created per-plugin reactive states. */\n const pluginStates = new Map<PluginHandle, InternalPluginState>();\n /**\n * Reactive snapshot of the application state, including args, outputs, UI state, and navigation state.\n */\n const snapshot = ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>(state.value) as Ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>;\n\n const updateData = async (value: Data) => {\n return platforma.mutateStorage({ operation: \"update-block-data\", value }, nextAuthorMarker());\n };\n\n const updatePluginData = async (handle: PluginHandle, value: unknown) => {\n return platforma.mutateStorage(\n { operation: \"update-plugin-data\", pluginId: handle, value },\n nextAuthorMarker(),\n );\n };\n\n const setNavigationState = async (state: NavigationState<Href>) => {\n return platforma.setNavigationState(state);\n };\n\n const outputs = computed<OutputValues<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>)\n .filter(([k]) => !isPluginOutputKey(k))\n .map(([k, outputWithStatus]) =>\n platforma.blockModelInfo.outputs[k]?.withStatus\n ? [k, ensureOutputHasStableFlag(outputWithStatus)]\n : [\n k,\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined,\n ],\n );\n return Object.fromEntries(entries);\n });\n\n const outputErrors = computed<OutputErrors<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>)\n .filter(([k]) => !isPluginOutputKey(k))\n .map(([k, vOrErr]) => [\n k,\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined,\n ]);\n return Object.fromEntries(entries);\n });\n\n const appModel = reactive({\n apiVersion: 3,\n error: \"\",\n model: {\n data: deepClone(deriveDataFromStorage<Data>(snapshot.value.blockStorage)) as Data,\n outputs,\n outputErrors,\n },\n }) as {\n error: string;\n model: {\n data: Data;\n outputs: OutputValues<Outputs>;\n outputErrors: OutputErrors<Outputs>;\n };\n };\n\n const { ignoreUpdates } = watchIgnorable(\n () => appModel.model,\n (_newData) => {\n const newData = deepClone(_newData);\n debug(\"setDataQueue appModel.model, data\", newData.data);\n setDataQueue.run(() => updateData(newData.data).then(unwrapResult));\n },\n { deep: true },\n );\n\n const updateAppModel = (newData: { data: Data }) => {\n debug(\"updateAppModel\", newData);\n appModel.model.data = deepClone(newData.data) as Data;\n };\n\n (async () => {\n window.addEventListener(\"beforeunload\", () => {\n closedRef.value = true;\n platforma\n .dispose()\n .then(unwrapResult)\n .catch((err) => {\n error(\"error in dispose\", err);\n });\n });\n\n while (!closedRef.value) {\n try {\n const patches = await platforma.getPatches(uTagRef.value).then(unwrapResult);\n\n debug(\"patches.length\", patches.value.length);\n debug(\"uTagRef.value\", uTagRef.value);\n debug(\"patches.uTag\", patches.uTag);\n debug(\"patches.author\", patches.author);\n debug(\"data.author\", data.author);\n\n uTagRef.value = patches.uTag;\n\n if (patches.value.length === 0) {\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n continue;\n }\n\n const isAuthorChanged = data.author?.authorId !== patches.author?.authorId;\n\n // Immutable behavior, apply external changes to the snapshot\n if (isAuthorChanged || data.isExternalSnapshot) {\n debug(\"got external changes, applying them to the snapshot\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value, false, false).newDocument;\n updateAppModel({ data: deriveDataFromStorage<Data>(snapshot.value.blockStorage) });\n // Reconcile plugin data from external source\n for (const [handle, pluginState] of pluginStates) {\n pluginState.ignoreUpdates(() => {\n pluginState.model.data = deepClone(\n getPluginData(snapshot.value.blockStorage, handle),\n );\n });\n }\n data.isExternalSnapshot = isAuthorChanged;\n });\n } else {\n // Mutable behavior\n debug(\"outputs changed\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value).newDocument;\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n } catch (err) {\n if (hasAbortError(err)) {\n debug(\"patches loop aborted\");\n closedRef.value = true;\n } else {\n error(\"error in patches loop\", err);\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n }\n })();\n\n const cloneData = () => deepClone(appModel.model.data) as Data;\n const cloneNavigationState = () =>\n deepClone(snapshot.value.navigationState) as Mutable<NavigationState<Href>>;\n\n const methods = {\n cloneData,\n cloneNavigationState,\n /**\n * Updates the UI state by applying a callback.\n *\n * @param cb - Callback to modify the current UI state.\n * @returns A promise resolving after the update is applied.\n * @todo Make it mutable since there is already an initial one\n */\n updateData(cb: (data: Data) => Data): Promise<boolean> {\n const newData = cb(cloneData());\n debug(\"updateData\", newData);\n appModel.model.data = newData;\n return setDataQueue.run(() => updateData(newData).then(unwrapResult));\n },\n /**\n * Navigates to a specific href by updating the navigation state.\n *\n * @param href - The target href to navigate to.\n * @returns A promise resolving after the navigation state is updated.\n */\n navigateTo(href: Href) {\n const newState = cloneNavigationState();\n newState.href = href;\n return setNavigationStateQueue.run(() => setNavigationState(newState).then(unwrapResult));\n },\n async allSettled() {\n await delay(0);\n const allQueues = [\n setDataQueue.allSettled(),\n ...Array.from(pluginDataQueues.values()).map((q) => q.allSettled()),\n ];\n await Promise.all(allQueues);\n },\n };\n\n /** Creates a lazily-cached per-plugin reactive state. */\n const createPluginState = <F extends PluginFactoryLike>(\n handle: PluginHandle<F>,\n ): InternalPluginState<InferFactoryData<F>, InferFactoryOutputs<F>> => {\n const prefix = pluginOutputPrefix(handle);\n\n const pluginOutputs = computed(() => {\n const result: Record<string, unknown> = {};\n for (const [key, outputWithStatus] of Object.entries(\n snapshot.value.outputs as Partial<Readonly<Outputs>>,\n )) {\n if (!key.startsWith(prefix)) continue;\n const outputKey = key.slice(prefix.length);\n if (platforma.blockModelInfo.outputs[key]?.withStatus) {\n result[outputKey] = outputWithStatus\n ? ensureOutputHasStableFlag(outputWithStatus)\n : undefined;\n } else {\n result[outputKey] =\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined;\n }\n }\n return result;\n });\n\n const pluginOutputErrors = computed(() => {\n const result: Record<string, Error | undefined> = {};\n for (const [key, vOrErr] of Object.entries(\n snapshot.value.outputs as Partial<Readonly<Outputs>>,\n )) {\n if (!key.startsWith(prefix)) continue;\n result[key.slice(prefix.length)] =\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined;\n }\n return result;\n });\n\n const pluginModel = reactive({\n data: deepClone(getPluginData(snapshot.value.blockStorage, handle)),\n outputs: pluginOutputs,\n outputErrors: pluginOutputErrors,\n }) as InternalPluginState<InferFactoryData<F>, InferFactoryOutputs<F>>[\"model\"];\n\n const { ignoreUpdates } = watchIgnorable(\n () => pluginModel.data,\n (newData) => {\n if (newData === undefined) return;\n debug(\"plugin setData\", handle, newData);\n getPluginDataQueue(handle).run(() =>\n updatePluginData(handle, deepClone(newData)).then(unwrapResult),\n );\n },\n { deep: true },\n );\n\n return {\n model: pluginModel,\n ignoreUpdates,\n };\n };\n\n /** Plugin internals — provided via separate injection key, not exposed on useApp(). */\n const pluginAccess: PluginAccess = {\n getOrCreatePluginState<F extends PluginFactoryLike>(handle: PluginHandle<F>) {\n const existing = pluginStates.get(handle);\n if (existing) {\n return existing as unknown as PluginState<InferFactoryData<F>, InferFactoryOutputs<F>>;\n }\n const state = createPluginState(handle);\n pluginStates.set(handle, state);\n return state;\n },\n };\n\n const plugins = Object.fromEntries(\n platforma.blockModelInfo.pluginIds.map((id) => [id, { handle: id }]),\n ) as InferPluginHandles<Plugins>;\n\n const getters = {\n closedRef,\n snapshot,\n plugins,\n queryParams: computed(() => parseQuery<Href>(snapshot.value.navigationState.href as Href)),\n href: computed(() => snapshot.value.navigationState.href),\n hasErrors: computed(() =>\n Object.values(snapshot.value.outputs as Partial<Readonly<Outputs>>).some((v) => !v?.ok),\n ),\n };\n\n const app = Object.assign(reactive(Object.assign(appModel, getters)), methods);\n\n if (settings.debug) {\n // @ts-expect-error (to inspect in console in debug mode)\n globalThis.__block_app__ = app;\n }\n\n return { app, pluginAccess };\n}\n\nexport type BaseAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n> = ReturnType<typeof createAppV3<Data, Args, Outputs, Href, Plugins>>[\"app\"];\n"],"mappings":";;;;;;;;;;;AA4CA,MAAa,KAA0B,OAAoD;CACzF,UAAU,GAAQ,YAAY,GAAU;CACxC,eAAe,GAAQ,gBAAgB,KAAK;CAC7C;AAED,IAAM,KAAqB,MAAe;AACxC,KAAI;AACF,SAAO,KAAK,UAAU,GAAG,MAAM,EAAE;UAC1B,GAAK;AACZ,SAAO,aAAe,QAAQ,EAAI,UAAU,OAAO,EAAI;;;;;;;;;;;;;;;;;AAkB3D,SAAgB,EAOd,GACA,GACA,GACA;CACA,IAAM,KAAS,GAAa,GAAG,MAAoB;AACjD,EAAI,EAAS,SACX,QAAQ,IACN,WAAW,KACX,oCACA,iBACA,GAAG,EAAK,KAAK,MAAM,EAAkB,EAAE,CAAC,CACzC;IAIC,KAAS,GAAa,GAAG,MAAoB;AACjD,UAAQ,MACN,WAAW,KACX,iCACA,cACA,GAAG,EAAK,KAAK,MAAM,EAAkB,EAAE,CAAC,CACzC;IAGG,IAAO;EACX,oBAAoB;EACpB,QAAQ;GACN,UAAU,GAAU;GACpB,cAAc;GACf;EACF,EAEK,WACJ,EAAK,SAAS,EAAuB,EAAK,OAAO,EACjD,EAAM,oBAAoB,EAAK,OAAO,EAC/B,EAAK,SAGR,IAAY,EAAI,GAAM,EAEtB,IAAU,EAAI,EAAM,KAAK,EAEzB,IAAe,EAAS,gBAAgB,KAExC,IAAe,IAAI,EAAiB,EAAE,iBAAc,CAAC,EACrD,oBAAmB,IAAI,KAAqC,EAC5D,KAAsB,MAA2C;EACrE,IAAI,IAAQ,EAAiB,IAAI,EAAO;AAKxC,SAJK,MACH,IAAQ,IAAI,EAAiB,EAAE,iBAAc,CAAC,EAC9C,EAAiB,IAAI,GAAQ,EAAM,GAE9B;IAEH,IAA0B,IAAI,EAAiB,EAAE,iBAAc,CAAC,EAGhE,oBAAe,IAAI,KAAwC,EAI3D,IAAW,EAId,EAAM,MAAM,EAMT,IAAa,OAAO,MACjB,EAAU,cAAc;EAAE,WAAW;EAAqB;EAAO,EAAE,GAAkB,CAAC,EAGzF,IAAmB,OAAO,GAAsB,MAC7C,EAAU,cACf;EAAE,WAAW;EAAsB,UAAU;EAAQ;EAAO,EAC5D,GAAkB,CACnB,EAGG,IAAqB,OAAO,MACzB,EAAU,mBAAmB,EAAM,EAGtC,IAAU,QAAsC;EACpD,IAAM,IAAU,OAAO,QAAQ,EAAS,MAAM,QAAsC,CACjF,QAAQ,CAAC,OAAO,CAAC,EAAkB,EAAE,CAAC,CACtC,KAAK,CAAC,GAAG,OACR,EAAU,eAAe,QAAQ,IAAI,aACjC,CAAC,GAAG,EAA0B,EAAiB,CAAC,GAChD,CACE,GACA,EAAiB,MAAM,EAAiB,UAAU,KAAA,IAC9C,EAAiB,QACjB,KAAA,EACL,CACN;AACH,SAAO,OAAO,YAAY,EAAQ;GAClC,EAEI,IAAe,QAAsC;EACzD,IAAM,IAAU,OAAO,QAAQ,EAAS,MAAM,QAAsC,CACjF,QAAQ,CAAC,OAAO,CAAC,EAAkB,EAAE,CAAC,CACtC,KAAK,CAAC,GAAG,OAAY,CACpB,GACA,KAAU,EAAO,OAAO,KAAQ,IAAI,EAAW,EAAO,OAAO,GAAG,KAAA,EACjE,CAAC;AACJ,SAAO,OAAO,YAAY,EAAQ;GAClC,EAEI,IAAW,EAAS;EACxB,YAAY;EACZ,OAAO;EACP,OAAO;GACL,MAAM,EAAU,EAA4B,EAAS,MAAM,aAAa,CAAC;GACzE;GACA;GACD;EACF,CAAC,EASI,EAAE,qBAAkB,QAClB,EAAS,QACd,MAAa;EACZ,IAAM,IAAU,EAAU,EAAS;AAEnC,EADA,EAAM,qCAAqC,EAAQ,KAAK,EACxD,EAAa,UAAU,EAAW,EAAQ,KAAK,CAAC,KAAK,EAAa,CAAC;IAErE,EAAE,MAAM,IAAM,CACf,EAEK,KAAkB,MAA4B;AAElD,EADA,EAAM,kBAAkB,EAAQ,EAChC,EAAS,MAAM,OAAO,EAAU,EAAQ,KAAK;;AAG/C,EAAC,YAAY;AAWX,OAVA,OAAO,iBAAiB,sBAAsB;AAE5C,GADA,EAAU,QAAQ,IAClB,EACG,SAAS,CACT,KAAK,EAAa,CAClB,OAAO,MAAQ;AACd,MAAM,oBAAoB,EAAI;KAC9B;IACJ,EAEK,CAAC,EAAU,OAChB,KAAI;GACF,IAAM,IAAU,MAAM,EAAU,WAAW,EAAQ,MAAM,CAAC,KAAK,EAAa;AAU5E,OARA,EAAM,kBAAkB,EAAQ,MAAM,OAAO,EAC7C,EAAM,iBAAiB,EAAQ,MAAM,EACrC,EAAM,gBAAgB,EAAQ,KAAK,EACnC,EAAM,kBAAkB,EAAQ,OAAO,EACvC,EAAM,eAAe,EAAK,OAAO,EAEjC,EAAQ,QAAQ,EAAQ,MAEpB,EAAQ,MAAM,WAAW,GAAG;AAC9B,UAAM,IAAI,SAAS,MAAY,WAAW,GAAA,IAA2B,CAAC;AACtE;;GAGF,IAAM,IAAkB,EAAK,QAAQ,aAAa,EAAQ,QAAQ;AA0BlE,GAvBI,KAAmB,EAAK,sBAC1B,EAAM,uDAAuD,EAAQ,MAAM,EAC3E,QAAoB;AAElB,IADA,EAAS,QAAQ,EAAW,EAAS,OAAO,EAAQ,OAAO,IAAO,GAAM,CAAC,aACzE,EAAe,EAAE,MAAM,EAA4B,EAAS,MAAM,aAAa,EAAE,CAAC;AAElF,SAAK,IAAM,CAAC,GAAQ,MAAgB,EAClC,GAAY,oBAAoB;AAC9B,OAAY,MAAM,OAAO,EACvB,EAAc,EAAS,MAAM,cAAc,EAAO,CACnD;MACD;AAEJ,MAAK,qBAAqB;KAC1B,KAGF,EAAM,mBAAmB,EAAQ,MAAM,EACvC,QAAoB;AAClB,MAAS,QAAQ,EAAW,EAAS,OAAO,EAAQ,MAAM,CAAC;KAC3D,GAGJ,MAAM,IAAI,SAAS,MAAY,WAAW,GAAA,IAA2B,CAAC;WAC/D,GAAK;AACZ,GAAI,EAAc,EAAI,IACpB,EAAM,uBAAuB,EAC7B,EAAU,QAAQ,OAElB,EAAM,yBAAyB,EAAI,EACnC,MAAM,IAAI,SAAS,MAAY,WAAW,GAAS,IAAK,CAAC;;KAI7D;CAEJ,IAAM,UAAkB,EAAU,EAAS,MAAM,KAAK,EAChD,UACJ,EAAU,EAAS,MAAM,gBAAgB,EAErC,IAAU;EACd;EACA;EAQA,WAAW,GAA4C;GACrD,IAAM,IAAU,EAAG,GAAW,CAAC;AAG/B,UAFA,EAAM,cAAc,EAAQ,EAC5B,EAAS,MAAM,OAAO,GACf,EAAa,UAAU,EAAW,EAAQ,CAAC,KAAK,EAAa,CAAC;;EAQvE,WAAW,GAAY;GACrB,IAAM,IAAW,GAAsB;AAEvC,UADA,EAAS,OAAO,GACT,EAAwB,UAAU,EAAmB,EAAS,CAAC,KAAK,EAAa,CAAC;;EAE3F,MAAM,aAAa;AACjB,SAAM,EAAM,EAAE;GACd,IAAM,IAAY,CAChB,EAAa,YAAY,EACzB,GAAG,MAAM,KAAK,EAAiB,QAAQ,CAAC,CAAC,KAAK,MAAM,EAAE,YAAY,CAAC,CACpE;AACD,SAAM,QAAQ,IAAI,EAAU;;EAE/B,EAGK,KACJ,MACqE;EACrE,IAAM,IAAS,EAAmB,EAAO,EAEnC,IAAgB,QAAe;GACnC,IAAM,IAAkC,EAAE;AAC1C,QAAK,IAAM,CAAC,GAAK,MAAqB,OAAO,QAC3C,EAAS,MAAM,QAChB,EAAE;AACD,QAAI,CAAC,EAAI,WAAW,EAAO,CAAE;IAC7B,IAAM,IAAY,EAAI,MAAM,EAAO,OAAO;AAC1C,IAAI,EAAU,eAAe,QAAQ,IAAM,aACzC,EAAO,KAAa,IAChB,EAA0B,EAAiB,GAC3C,KAAA,IAEJ,EAAO,KACL,EAAiB,MAAM,EAAiB,UAAU,KAAA,IAC9C,EAAiB,QACjB,KAAA;;AAGV,UAAO;IACP,EAEI,IAAqB,QAAe;GACxC,IAAM,IAA4C,EAAE;AACpD,QAAK,IAAM,CAAC,GAAK,MAAW,OAAO,QACjC,EAAS,MAAM,QAChB,CACM,GAAI,WAAW,EAAO,KAC3B,EAAO,EAAI,MAAM,EAAO,OAAO,IAC7B,KAAU,EAAO,OAAO,KAAQ,IAAI,EAAW,EAAO,OAAO,GAAG,KAAA;AAEpE,UAAO;IACP,EAEI,IAAc,EAAS;GAC3B,MAAM,EAAU,EAAc,EAAS,MAAM,cAAc,EAAO,CAAC;GACnE,SAAS;GACT,cAAc;GACf,CAAC,EAEI,EAAE,qBAAkB,QAClB,EAAY,OACjB,MAAY;AACP,SAAY,KAAA,MAChB,EAAM,kBAAkB,GAAQ,EAAQ,EACxC,EAAmB,EAAO,CAAC,UACzB,EAAiB,GAAQ,EAAU,EAAQ,CAAC,CAAC,KAAK,EAAa,CAChE;KAEH,EAAE,MAAM,IAAM,CACf;AAED,SAAO;GACL,OAAO;GACP;GACD;IAIG,IAA6B,EACjC,uBAAoD,GAAyB;EAC3E,IAAM,IAAW,EAAa,IAAI,EAAO;AACzC,MAAI,EACF,QAAO;EAET,IAAM,IAAQ,EAAkB,EAAO;AAEvC,SADA,EAAa,IAAI,GAAQ,EAAM,EACxB;IAEV,EAMK,IAAU;EACd;EACA;EACA,SAPc,OAAO,YACrB,EAAU,eAAe,UAAU,KAAK,MAAO,CAAC,GAAI,EAAE,QAAQ,GAAI,CAAC,CAAC,CACrE;EAMC,aAAa,QAAe,EAAiB,EAAS,MAAM,gBAAgB,KAAa,CAAC;EAC1F,MAAM,QAAe,EAAS,MAAM,gBAAgB,KAAK;EACzD,WAAW,QACT,OAAO,OAAO,EAAS,MAAM,QAAsC,CAAC,MAAM,MAAM,CAAC,GAAG,GAAG,CACxF;EACF,EAEK,IAAM,OAAO,OAAO,EAAS,OAAO,OAAO,GAAU,EAAQ,CAAC,EAAE,EAAQ;AAO9E,QALI,EAAS,UAEX,WAAW,gBAAgB,IAGtB;EAAE;EAAK;EAAc"}
1
+ {"version":3,"file":"createAppV3.js","names":[],"sources":["../../src/internal/createAppV3.ts"],"sourcesContent":["import { deepClone, delay, uniqueId } from \"@milaboratories/helpers\";\nimport type { Mutable } from \"@milaboratories/helpers\";\nimport type {\n NavigationState,\n BlockOutputsBase,\n BlockStateV3,\n PlatformaV3,\n ValueWithUTag,\n AuthorMarker,\n PlatformaExtended,\n InferPluginHandles,\n PluginHandle,\n InferFactoryData,\n InferFactoryOutputs,\n InferFactoryUiServices,\n PluginFactoryLike,\n} from \"@platforma-sdk/model\";\nimport {\n hasAbortError,\n unwrapResult,\n deriveDataFromStorage,\n getPluginData,\n isPluginOutputKey,\n pluginOutputPrefix,\n createNodeServiceProxy,\n buildServices,\n} from \"@platforma-sdk/model\";\nimport { type UiServices as AllUiServices } from \"@milaboratories/pl-model-common\";\nimport { createUiServiceRegistry } from \"./service_factories\";\nimport type { Ref } from \"vue\";\nimport { reactive, computed, ref, markRaw } from \"vue\";\nimport type { OutputValues, OutputErrors, AppSettings } from \"../types\";\nimport { parseQuery } from \"../urls\";\nimport { ensureOutputHasStableFlag, MultiError } from \"../utils\";\nimport { applyPatch } from \"fast-json-patch\";\nimport { UpdateSerializer } from \"./UpdateSerializer\";\nimport { watchIgnorable } from \"@vueuse/core\";\nimport type { PluginState, PluginAccess } from \"../usePlugin\";\n\nexport const patchPoolingDelay = 150;\n\n/** Internal per-plugin state with reconciliation support. */\ninterface InternalPluginState<\n Data = unknown,\n Outputs = unknown,\n Services = Record<string, unknown>,\n> extends PluginState<Data, Outputs, Services> {\n readonly ignoreUpdates: (fn: () => void) => void;\n}\n\nexport const createNextAuthorMarker = (marker: AuthorMarker | undefined): AuthorMarker => ({\n authorId: marker?.authorId ?? uniqueId(),\n localVersion: (marker?.localVersion ?? 0) + 1,\n});\n\nconst stringifyForDebug = (v: unknown) => {\n try {\n return JSON.stringify(v, null, 2);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n};\n\n/**\n * Creates an application instance with reactive state management, outputs, and methods for state updates and navigation.\n *\n * @template Args - The type of arguments used in the application.\n * @template Outputs - The type of block outputs extending `BlockOutputsBase`.\n * @template Data - The type of the block data.\n * @template Href - The type of navigation href, defaulting to a string starting with `/`.\n *\n * @param state - Initial state of the application, including args, outputs, UI state, and navigation state.\n * @param platforma - A platform interface for interacting with block states.\n * @param settings - Application settings, such as debug flags.\n *\n * @returns A reactive application object with methods, getters, and state.\n */\nexport function createAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n>(\n state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>,\n platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices>>,\n settings: AppSettings,\n) {\n const debug = (msg: string, ...rest: unknown[]) => {\n if (settings.debug) {\n console.log(\n `%c>>> %c${msg}`,\n \"color: orange; font-weight: bold\",\n \"color: orange\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n }\n };\n\n const error = (msg: string, ...rest: unknown[]) => {\n console.error(\n `%c>>> %c${msg}`,\n \"color: red; font-weight: bold\",\n \"color: red\",\n ...rest.map((r) => stringifyForDebug(r)),\n );\n };\n\n const data = {\n isExternalSnapshot: false,\n author: {\n authorId: uniqueId(),\n localVersion: 0,\n },\n };\n\n const nextAuthorMarker = () => {\n data.author = createNextAuthorMarker(data.author);\n debug(\"nextAuthorMarker\", data.author);\n return data.author;\n };\n\n const closedRef = ref(false);\n\n const uTagRef = ref(state.uTag);\n\n const debounceSpan = settings.debounceSpan ?? 200;\n\n const setDataQueue = new UpdateSerializer({ debounceSpan });\n const pluginDataQueues = new Map<PluginHandle, UpdateSerializer>();\n const getPluginDataQueue = (handle: PluginHandle): UpdateSerializer => {\n let queue = pluginDataQueues.get(handle);\n if (!queue) {\n queue = new UpdateSerializer({ debounceSpan });\n pluginDataQueues.set(handle, queue);\n }\n return queue;\n };\n const setNavigationStateQueue = new UpdateSerializer({ debounceSpan });\n\n /** Lazily-created per-plugin reactive states. */\n const pluginStates = new Map<PluginHandle, InternalPluginState>();\n /**\n * Reactive snapshot of the application state, including args, outputs, UI state, and navigation state.\n */\n const snapshot = ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>(state.value) as Ref<{\n outputs: Partial<Outputs>;\n blockStorage: unknown;\n navigationState: NavigationState<Href>;\n }>;\n\n const updateData = async (value: Data) => {\n return platforma.mutateStorage({ operation: \"update-block-data\", value }, nextAuthorMarker());\n };\n\n const updatePluginData = async (handle: PluginHandle, value: unknown) => {\n return platforma.mutateStorage(\n { operation: \"update-plugin-data\", pluginId: handle, value },\n nextAuthorMarker(),\n );\n };\n\n const setNavigationState = async (state: NavigationState<Href>) => {\n return platforma.setNavigationState(state);\n };\n\n const outputs = computed<OutputValues<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>)\n .filter(([k]) => !isPluginOutputKey(k))\n .map(([k, outputWithStatus]) =>\n platforma.blockModelInfo.outputs[k]?.withStatus\n ? [k, ensureOutputHasStableFlag(outputWithStatus)]\n : [\n k,\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined,\n ],\n );\n return Object.fromEntries(entries);\n });\n\n const outputErrors = computed<OutputErrors<Outputs>>(() => {\n const entries = Object.entries(snapshot.value.outputs as Partial<Readonly<Outputs>>)\n .filter(([k]) => !isPluginOutputKey(k))\n .map(([k, vOrErr]) => [\n k,\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined,\n ]);\n return Object.fromEntries(entries);\n });\n\n const appModel = reactive({\n apiVersion: 3,\n error: \"\",\n model: {\n data: deepClone(deriveDataFromStorage<Data>(snapshot.value.blockStorage)) as Data,\n outputs,\n outputErrors,\n },\n }) as {\n error: string;\n model: {\n data: Data;\n outputs: OutputValues<Outputs>;\n outputErrors: OutputErrors<Outputs>;\n };\n };\n\n const { ignoreUpdates } = watchIgnorable(\n () => appModel.model,\n (_newData) => {\n const newData = deepClone(_newData);\n debug(\"setDataQueue appModel.model, data\", newData.data);\n setDataQueue.run(() => updateData(newData.data).then(unwrapResult));\n },\n { deep: true },\n );\n\n const updateAppModel = (newData: { data: Data }) => {\n debug(\"updateAppModel\", newData);\n appModel.model.data = deepClone(newData.data) as Data;\n };\n\n (async () => {\n window.addEventListener(\"beforeunload\", () => {\n closedRef.value = true;\n Promise.allSettled([uiRegistry.dispose(), platforma.dispose().then(unwrapResult)]).catch(\n (err) => {\n error(\"error in dispose\", err);\n },\n );\n });\n\n while (!closedRef.value) {\n try {\n const patches = await platforma.getPatches(uTagRef.value).then(unwrapResult);\n\n debug(\"patches.length\", patches.value.length);\n debug(\"uTagRef.value\", uTagRef.value);\n debug(\"patches.uTag\", patches.uTag);\n debug(\"patches.author\", patches.author);\n debug(\"data.author\", data.author);\n\n uTagRef.value = patches.uTag;\n\n if (patches.value.length === 0) {\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n continue;\n }\n\n const isAuthorChanged = data.author?.authorId !== patches.author?.authorId;\n\n // Immutable behavior, apply external changes to the snapshot\n if (isAuthorChanged || data.isExternalSnapshot) {\n debug(\"got external changes, applying them to the snapshot\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value, false, false).newDocument;\n updateAppModel({ data: deriveDataFromStorage<Data>(snapshot.value.blockStorage) });\n // Reconcile plugin data from external source\n for (const [handle, pluginState] of pluginStates) {\n pluginState.ignoreUpdates(() => {\n pluginState.model.data = deepClone(\n getPluginData(snapshot.value.blockStorage, handle),\n );\n });\n }\n data.isExternalSnapshot = isAuthorChanged;\n });\n } else {\n // Mutable behavior\n debug(\"outputs changed\", patches.value);\n ignoreUpdates(() => {\n snapshot.value = applyPatch(snapshot.value, patches.value).newDocument;\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, patchPoolingDelay));\n } catch (err) {\n if (hasAbortError(err)) {\n debug(\"patches loop aborted\");\n closedRef.value = true;\n } else {\n error(\"error in patches loop\", err);\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n }\n })();\n\n const cloneData = () => deepClone(appModel.model.data) as Data;\n const cloneNavigationState = () =>\n deepClone(snapshot.value.navigationState) as Mutable<NavigationState<Href>>;\n\n const methods = {\n cloneData,\n cloneNavigationState,\n /**\n * Updates the UI state by applying a callback.\n *\n * @param cb - Callback to modify the current UI state.\n * @returns A promise resolving after the update is applied.\n * @todo Make it mutable since there is already an initial one\n */\n updateData(cb: (data: Data) => Data): Promise<boolean> {\n const newData = cb(cloneData());\n debug(\"updateData\", newData);\n appModel.model.data = newData;\n return setDataQueue.run(() => updateData(newData).then(unwrapResult));\n },\n /**\n * Navigates to a specific href by updating the navigation state.\n *\n * @param href - The target href to navigate to.\n * @returns A promise resolving after the navigation state is updated.\n */\n navigateTo(href: Href) {\n const newState = cloneNavigationState();\n newState.href = href;\n return setNavigationStateQueue.run(() => setNavigationState(newState).then(unwrapResult));\n },\n async allSettled() {\n await delay(0);\n const allQueues = [\n setDataQueue.allSettled(),\n ...Array.from(pluginDataQueues.values()).map((q) => q.allSettled()),\n ];\n await Promise.all(allQueues);\n },\n };\n\n const proxy = createNodeServiceProxy(platforma.serviceDispatch);\n const uiRegistry = createUiServiceRegistry({ proxy });\n const services = buildServices<UiServices>(platforma.serviceDispatch, uiRegistry);\n\n /** Creates a lazily-cached per-plugin reactive state. */\n const createPluginState = <F extends PluginFactoryLike>(\n handle: PluginHandle<F>,\n ): InternalPluginState<InferFactoryData<F>, InferFactoryOutputs<F>> => {\n const prefix = pluginOutputPrefix(handle);\n\n const pluginOutputs = computed(() => {\n const result: Record<string, unknown> = {};\n for (const [key, outputWithStatus] of Object.entries(\n snapshot.value.outputs as Partial<Readonly<Outputs>>,\n )) {\n if (!key.startsWith(prefix)) continue;\n const outputKey = key.slice(prefix.length);\n if (platforma.blockModelInfo.outputs[key]?.withStatus) {\n result[outputKey] = outputWithStatus\n ? ensureOutputHasStableFlag(outputWithStatus)\n : undefined;\n } else {\n result[outputKey] =\n outputWithStatus.ok && outputWithStatus.value !== undefined\n ? outputWithStatus.value\n : undefined;\n }\n }\n return result;\n });\n\n const pluginOutputErrors = computed(() => {\n const result: Record<string, Error | undefined> = {};\n for (const [key, vOrErr] of Object.entries(\n snapshot.value.outputs as Partial<Readonly<Outputs>>,\n )) {\n if (!key.startsWith(prefix)) continue;\n result[key.slice(prefix.length)] =\n vOrErr && vOrErr.ok === false ? new MultiError(vOrErr.errors) : undefined;\n }\n return result;\n });\n\n const pluginModel = reactive({\n data: deepClone(getPluginData(snapshot.value.blockStorage, handle)),\n outputs: pluginOutputs,\n outputErrors: pluginOutputErrors,\n }) as InternalPluginState<InferFactoryData<F>, InferFactoryOutputs<F>>[\"model\"];\n\n const { ignoreUpdates } = watchIgnorable(\n () => pluginModel.data,\n (newData) => {\n if (newData === undefined) return;\n debug(\"plugin setData\", handle, newData);\n getPluginDataQueue(handle).run(() =>\n updatePluginData(handle, deepClone(newData)).then(unwrapResult),\n );\n },\n { deep: true },\n );\n\n return {\n model: pluginModel,\n services: markRaw(services),\n ignoreUpdates,\n };\n };\n\n /** Plugin internals — provided via separate injection key, not exposed on useApp(). */\n const pluginAccess: PluginAccess = {\n getOrCreatePluginState<F extends PluginFactoryLike>(handle: PluginHandle<F>) {\n const existing = pluginStates.get(handle);\n if (existing) {\n return existing as unknown as PluginState<\n InferFactoryData<F>,\n InferFactoryOutputs<F>,\n InferFactoryUiServices<F>\n >;\n }\n const state = createPluginState(handle);\n pluginStates.set(handle, state);\n return state as unknown as PluginState<\n InferFactoryData<F>,\n InferFactoryOutputs<F>,\n InferFactoryUiServices<F>\n >;\n },\n };\n\n const plugins = Object.fromEntries(\n platforma.blockModelInfo.pluginIds.map((id) => [id, { handle: id }]),\n ) as InferPluginHandles<Plugins>;\n\n const getters = {\n closedRef,\n snapshot,\n plugins,\n services: markRaw(services),\n queryParams: computed(() => parseQuery<Href>(snapshot.value.navigationState.href as Href)),\n href: computed(() => snapshot.value.navigationState.href),\n hasErrors: computed(() =>\n Object.values(snapshot.value.outputs as Partial<Readonly<Outputs>>).some((v) => !v?.ok),\n ),\n };\n\n const app = Object.assign(reactive(Object.assign(appModel, getters)), methods);\n\n if (settings.debug) {\n // @ts-expect-error (to inspect in console in debug mode)\n globalThis.__block_app__ = app;\n }\n\n return { app, pluginAccess };\n}\n\nexport type BaseAppV3<\n Data = unknown,\n Args = unknown,\n Outputs extends BlockOutputsBase = BlockOutputsBase,\n Href extends `/${string}` = `/${string}`,\n Plugins extends Record<string, unknown> = Record<string, unknown>,\n UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,\n> = ReturnType<typeof createAppV3<Data, Args, Outputs, Href, Plugins, UiServices>>[\"app\"];\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { UiServiceRegistry } from '@milaboratories/pl-model-common';
2
+ import { NodeServiceProxy } from '@platforma-sdk/model';
3
+ export type UiServiceOptions = {
4
+ proxy: NodeServiceProxy;
5
+ };
6
+ export declare function createUiServiceRegistry(options: UiServiceOptions): UiServiceRegistry<{
7
+ PFrameSpec: import('@milaboratories/pl-model-common').Branded<"pframeSpec", import('@milaboratories/pl-model-common').ServiceTypesLike<import('@milaboratories/pl-model-common').PFrameSpecDriver, import('@milaboratories/pl-model-common').PFrameSpecDriver, "wasm">>;
8
+ PFrame: import('@milaboratories/pl-model-common').Branded<"pframe", import('@milaboratories/pl-model-common').ServiceTypesLike<import('@milaboratories/pl-model-common').PFrameModelDriver<import('@milaboratories/pl-model-common').PColumn<string | import('@milaboratories/pl-model-common').PColumnValues | import('@milaboratories/pl-model-common').DataInfo<string>>>, import('@milaboratories/pl-model-common').PFrameDriver, "node">>;
9
+ }>;
10
+ //# sourceMappingURL=service_factories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service_factories.d.ts","sourceRoot":"","sources":["../../src/internal/service_factories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAY,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,gBAAgB,CAAC;CACzB,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,gBAAgB;;;GAKhE"}
@@ -0,0 +1,19 @@
1
+ import { Services as e, UiServiceRegistry as t } from "@milaboratories/pl-model-common";
2
+ import { SpecDriver as n } from "@milaboratories/pf-spec-driver";
3
+ /**
4
+ * UI service factories — add a factory for each new service here.
5
+ *
6
+ * Each entry maps a Services key to a factory function that creates the
7
+ * UI-side driver instance:
8
+ * - WASM services: instantiated directly (e.g. SpecDriver)
9
+ * - Node services: proxied via IPC using NodeServiceProxy
10
+ */
11
+ function r(r) {
12
+ return new t(e, {
13
+ PFrameSpec: () => new n(),
14
+ PFrame: () => r.proxy(e.PFrame)
15
+ });
16
+ }
17
+ export { r as createUiServiceRegistry };
18
+
19
+ //# sourceMappingURL=service_factories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service_factories.js","names":[],"sources":["../../src/internal/service_factories.ts"],"sourcesContent":["/**\n * UI service factories — add a factory for each new service here.\n *\n * Each entry maps a Services key to a factory function that creates the\n * UI-side driver instance:\n * - WASM services: instantiated directly (e.g. SpecDriver)\n * - Node services: proxied via IPC using NodeServiceProxy\n */\n\nimport { Services, UiServiceRegistry } from \"@milaboratories/pl-model-common\";\nimport { SpecDriver } from \"@milaboratories/pf-spec-driver\";\nimport type { NodeServiceProxy } from \"@platforma-sdk/model\";\n\nexport type UiServiceOptions = {\n proxy: NodeServiceProxy;\n};\n\nexport function createUiServiceRegistry(options: UiServiceOptions) {\n return new UiServiceRegistry(Services, {\n PFrameSpec: () => new SpecDriver(),\n PFrame: () => options.proxy(Services.PFrame),\n });\n}\n"],"mappings":";;;;;;;;;;AAiBA,SAAgB,EAAwB,GAA2B;AACjE,QAAO,IAAI,EAAkB,GAAU;EACrC,kBAAkB,IAAI,GAAY;EAClC,cAAc,EAAQ,MAAM,EAAS,OAAO;EAC7C,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { Reactive } from 'vue';
2
- import { PluginHandle, InferFactoryData, InferFactoryOutputs, PluginFactoryLike } from '@platforma-sdk/model';
2
+ import { PluginHandle, InferFactoryData, InferFactoryOutputs, InferFactoryUiServices, PluginFactoryLike } from '@platforma-sdk/model';
3
3
  /** Per-plugin reactive model exposed to consumers via usePlugin(). */
4
- export interface PluginState<Data = unknown, Outputs = unknown> {
4
+ export interface PluginState<Data = unknown, Outputs = unknown, Services = Record<string, unknown>> {
5
5
  readonly model: Reactive<{
6
6
  data: Data;
7
7
  outputs: Outputs extends Record<string, unknown> ? {
@@ -11,10 +11,11 @@ export interface PluginState<Data = unknown, Outputs = unknown> {
11
11
  [K in keyof Outputs]?: Error;
12
12
  } : Record<string, Error | undefined>;
13
13
  }>;
14
+ readonly services: Services;
14
15
  }
15
16
  /** Internal interface for plugin access — provided via Vue injection to usePlugin(). */
16
17
  export interface PluginAccess {
17
- getOrCreatePluginState<F extends PluginFactoryLike>(handle: PluginHandle<F>): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>>;
18
+ getOrCreatePluginState<F extends PluginFactoryLike>(handle: PluginHandle<F>): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>, InferFactoryUiServices<F>>;
18
19
  }
19
20
  /**
20
21
  * Composable for accessing a plugin's reactive model: data, outputs, and outputErrors.
@@ -40,5 +41,5 @@ export interface PluginAccess {
40
41
  * </script>
41
42
  * ```
42
43
  */
43
- export declare function usePlugin<F extends PluginFactoryLike>(handle: PluginHandle<F>): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>>;
44
+ export declare function usePlugin<F extends PluginFactoryLike>(handle: PluginHandle<F>): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>, InferFactoryUiServices<F>>;
44
45
  //# sourceMappingURL=usePlugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePlugin.d.ts","sourceRoot":"","sources":["../src/usePlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,KAAK,CAAC;AAE5C,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAE9B,sEAAsE;AACtE,MAAM,WAAW,WAAW,CAAC,IAAI,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO;IAC5D,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;QACvB,IAAI,EAAE,IAAI,CAAC;QACX,OAAO,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5C;aAAG,CAAC,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS;SAAE,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC5B,YAAY,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjD;aAAG,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,KAAK;SAAE,GAChC,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,CAAC,CAAC;KACvC,CAAC,CAAC;CACJ;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,sBAAsB,CAAC,CAAC,SAAS,iBAAiB,EAChD,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7D;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,iBAAiB,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,4DAW7E"}
1
+ {"version":3,"file":"usePlugin.d.ts","sourceRoot":"","sources":["../src/usePlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,KAAK,CAAC;AAE5C,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAE9B,sEAAsE;AACtE,MAAM,WAAW,WAAW,CAC1B,IAAI,GAAG,OAAO,EACd,OAAO,GAAG,OAAO,EACjB,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAElC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;QACvB,IAAI,EAAE,IAAI,CAAC;QACX,OAAO,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5C;aAAG,CAAC,IAAI,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS;SAAE,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC5B,YAAY,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjD;aAAG,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,KAAK;SAAE,GAChC,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,CAAC,CAAC;KACvC,CAAC,CAAC;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,sBAAsB,CAAC,CAAC,SAAS,iBAAiB,EAChD,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GACtB,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;CACxF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,iBAAiB,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,uFAW7E"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePlugin.js","names":[],"sources":["../src/usePlugin.ts"],"sourcesContent":["import { inject, type Reactive } from \"vue\";\nimport { pluginDataKey } from \"./defineApp\";\nimport type {\n PluginHandle,\n InferFactoryData,\n InferFactoryOutputs,\n PluginFactoryLike,\n} from \"@platforma-sdk/model\";\n\n/** Per-plugin reactive model exposed to consumers via usePlugin(). */\nexport interface PluginState<Data = unknown, Outputs = unknown> {\n readonly model: Reactive<{\n data: Data;\n outputs: Outputs extends Record<string, unknown>\n ? { [K in keyof Outputs]: Outputs[K] | undefined }\n : Record<string, unknown>;\n outputErrors: Outputs extends Record<string, unknown>\n ? { [K in keyof Outputs]?: Error }\n : Record<string, Error | undefined>;\n }>;\n}\n\n/** Internal interface for plugin access — provided via Vue injection to usePlugin(). */\nexport interface PluginAccess {\n getOrCreatePluginState<F extends PluginFactoryLike>(\n handle: PluginHandle<F>,\n ): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>>;\n}\n\n/**\n * Composable for accessing a plugin's reactive model: data, outputs, and outputErrors.\n *\n * Mirrors the `app.model` access pattern — `plugin.model.data` is reactive and deep-watched,\n * mutations are automatically queued and sent to storage.\n *\n * @param handle - Opaque plugin handle obtained from `app.plugins`.\n * @typeParam F - The plugin factory type (inferred from the handle)\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { usePlugin, type InferPluginHandle } from '@platforma-sdk/ui-vue';\n * import type { CounterPlugin } from './plugins/counter';\n *\n * const props = defineProps<{ instance: InferPluginHandle<CounterPlugin> }>();\n * const plugin = usePlugin(props.instance);\n *\n * plugin.model.data.count += 1; // reactive, triggers storage update\n * plugin.model.outputs.displayText // computed, plugin's own outputs only\n * plugin.model.outputErrors.displayText // Error | undefined\n * </script>\n * ```\n */\nexport function usePlugin<F extends PluginFactoryLike>(handle: PluginHandle<F>) {\n const access = inject<PluginAccess>(pluginDataKey);\n\n if (!access) {\n throw new Error(\n \"usePlugin requires a V3 block (BlockModelV3). \" +\n \"Make sure the block uses apiVersion 3 and the plugin is installed.\",\n );\n }\n\n return access.getOrCreatePluginState<F>(handle);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,SAAgB,EAAuC,GAAyB;CAC9E,IAAM,IAAS,EAAqB,EAAc;AAElD,KAAI,CAAC,EACH,OAAU,MACR,mHAED;AAGH,QAAO,EAAO,uBAA0B,EAAO"}
1
+ {"version":3,"file":"usePlugin.js","names":[],"sources":["../src/usePlugin.ts"],"sourcesContent":["import { inject, type Reactive } from \"vue\";\nimport { pluginDataKey } from \"./defineApp\";\nimport type {\n PluginHandle,\n InferFactoryData,\n InferFactoryOutputs,\n InferFactoryUiServices,\n PluginFactoryLike,\n} from \"@platforma-sdk/model\";\n\n/** Per-plugin reactive model exposed to consumers via usePlugin(). */\nexport interface PluginState<\n Data = unknown,\n Outputs = unknown,\n Services = Record<string, unknown>,\n> {\n readonly model: Reactive<{\n data: Data;\n outputs: Outputs extends Record<string, unknown>\n ? { [K in keyof Outputs]: Outputs[K] | undefined }\n : Record<string, unknown>;\n outputErrors: Outputs extends Record<string, unknown>\n ? { [K in keyof Outputs]?: Error }\n : Record<string, Error | undefined>;\n }>;\n readonly services: Services;\n}\n\n/** Internal interface for plugin access — provided via Vue injection to usePlugin(). */\nexport interface PluginAccess {\n getOrCreatePluginState<F extends PluginFactoryLike>(\n handle: PluginHandle<F>,\n ): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>, InferFactoryUiServices<F>>;\n}\n\n/**\n * Composable for accessing a plugin's reactive model: data, outputs, and outputErrors.\n *\n * Mirrors the `app.model` access pattern — `plugin.model.data` is reactive and deep-watched,\n * mutations are automatically queued and sent to storage.\n *\n * @param handle - Opaque plugin handle obtained from `app.plugins`.\n * @typeParam F - The plugin factory type (inferred from the handle)\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { usePlugin, type InferPluginHandle } from '@platforma-sdk/ui-vue';\n * import type { CounterPlugin } from './plugins/counter';\n *\n * const props = defineProps<{ instance: InferPluginHandle<CounterPlugin> }>();\n * const plugin = usePlugin(props.instance);\n *\n * plugin.model.data.count += 1; // reactive, triggers storage update\n * plugin.model.outputs.displayText // computed, plugin's own outputs only\n * plugin.model.outputErrors.displayText // Error | undefined\n * </script>\n * ```\n */\nexport function usePlugin<F extends PluginFactoryLike>(handle: PluginHandle<F>) {\n const access = inject<PluginAccess>(pluginDataKey);\n\n if (!access) {\n throw new Error(\n \"usePlugin requires a V3 block (BlockModelV3). \" +\n \"Make sure the block uses apiVersion 3 and the plugin is installed.\",\n );\n }\n\n return access.getOrCreatePluginState<F>(handle);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,SAAgB,EAAuC,GAAyB;CAC9E,IAAM,IAAS,EAAqB,EAAc;AAElD,KAAI,CAAC,EACH,OAAU,MACR,mHAED;AAGH,QAAO,EAAO,uBAA0B,EAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/ui-vue",
3
- "version": "1.61.3",
3
+ "version": "1.62.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -25,8 +25,10 @@
25
25
  "lru-cache": "^11.2.2",
26
26
  "vue": "^3.5.24",
27
27
  "zod": "~3.23.8",
28
- "@milaboratories/uikit": "2.11.3",
29
- "@platforma-sdk/model": "1.61.1"
28
+ "@milaboratories/pf-spec-driver": "1.2.0",
29
+ "@milaboratories/pl-model-common": "1.30.0",
30
+ "@platforma-sdk/model": "1.62.0",
31
+ "@milaboratories/uikit": "2.11.4"
30
32
  },
31
33
  "devDependencies": {
32
34
  "@faker-js/faker": "^9.2.0",
@@ -40,10 +42,10 @@
40
42
  "typescript": "~5.9.3",
41
43
  "vite": "8.0.0-beta.15",
42
44
  "vitest": "^4.0.18",
43
- "@milaboratories/ts-configs": "1.2.2",
44
- "@milaboratories/helpers": "1.14.0",
45
45
  "@milaboratories/build-configs": "1.5.2",
46
- "@milaboratories/ts-builder": "1.3.0"
46
+ "@milaboratories/helpers": "1.14.0",
47
+ "@milaboratories/ts-builder": "1.3.0",
48
+ "@milaboratories/ts-configs": "1.2.2"
47
49
  },
48
50
  "scripts": {
49
51
  "dev": "ts-builder serve --target browser-lib",
package/src/defineApp.ts CHANGED
@@ -5,6 +5,7 @@ import type {
5
5
  PlatformaV1,
6
6
  PlatformaV2,
7
7
  BlockCodeKnownFeatureFlags,
8
+ UiServices as AllUiServices,
8
9
  } from "@platforma-sdk/model";
9
10
  import {
10
11
  getPlatformaApiVersion,
@@ -166,15 +167,16 @@ export function defineAppV3<
166
167
  Outputs extends BlockOutputsBase = BlockOutputsBase,
167
168
  Href extends `/${string}` = `/${string}`,
168
169
  Plugins extends Record<string, unknown> = Record<string, unknown>,
170
+ UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,
169
171
  Extend extends ExtendSettings<Href> = ExtendSettings<Href>,
170
172
  >(
171
- platforma: PlatformaV3<Data, Args, Outputs, Href, Plugins> & {
173
+ platforma: PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices> & {
172
174
  blockModelInfo: BlockModelInfo;
173
175
  },
174
- extendApp: (app: BaseAppV3<Data, Args, Outputs, Href, Plugins>) => Extend,
176
+ extendApp: (app: BaseAppV3<Data, Args, Outputs, Href, Plugins, UiServices>) => Extend,
175
177
  settings: AppSettings = {},
176
- ): SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend> {
177
- let app: AppV3<Data, Args, Outputs, Href, Plugins, Extend> | undefined = undefined;
178
+ ): SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices> {
179
+ let app: AppV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices> | undefined = undefined;
178
180
 
179
181
  // Captured during install() so V3 can provide plugin data access after async load
180
182
  let vueAppInstance: VueApp | undefined;
@@ -191,11 +193,14 @@ export function defineAppV3<
191
193
  await platforma.loadBlockState().then((stateOrError) => {
192
194
  const state = unwrapResult(stateOrError);
193
195
  plugin.loaded = true;
194
- const { app: baseApp, pluginAccess } = createAppV3<Data, Args, Outputs, Href, Plugins>(
195
- state,
196
- platforma,
197
- settings,
198
- );
196
+ const { app: baseApp, pluginAccess } = createAppV3<
197
+ Data,
198
+ Args,
199
+ Outputs,
200
+ Href,
201
+ Plugins,
202
+ UiServices
203
+ >(state, platforma, settings);
199
204
 
200
205
  if (!vueAppInstance) {
201
206
  throw new Error(
@@ -218,7 +223,7 @@ export function defineAppV3<
218
223
  getRoute(href: Href): Component | undefined {
219
224
  return routes[href];
220
225
  },
221
- } as AppV3<Data, Args, Outputs, Href, Plugins, Extend>);
226
+ } as AppV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices>);
222
227
  });
223
228
  };
224
229
 
@@ -234,7 +239,8 @@ export function defineAppV3<
234
239
  Outputs,
235
240
  PageHref,
236
241
  Plugins,
237
- Extend
242
+ Extend,
243
+ UiServices
238
244
  >;
239
245
  },
240
246
  install(app: VueApp) {
@@ -247,7 +253,7 @@ export function defineAppV3<
247
253
  },
248
254
  });
249
255
 
250
- return plugin as SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend>;
256
+ return plugin as SdkPluginV3<Data, Args, Outputs, Href, Plugins, Extend, UiServices>;
251
257
  }
252
258
 
253
259
  export type AppV1<
@@ -275,7 +281,8 @@ export type AppV3<
275
281
  Href extends `/${string}` = `/${string}`,
276
282
  Plugins extends Record<string, unknown> = Record<string, unknown>,
277
283
  Local extends ExtendSettings<Href> = ExtendSettings<Href>,
278
- > = BaseAppV3<Data, Args, Outputs, Href, Plugins> &
284
+ UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,
285
+ > = BaseAppV3<Data, Args, Outputs, Href, Plugins, UiServices> &
279
286
  Reactive<Omit<Local, "routes">> & { getRoute(href: Href): Component | undefined };
280
287
 
281
288
  // ---------------------------------------------------------------------------
@@ -319,12 +326,21 @@ export type SdkPluginV3<
319
326
  Href extends `/${string}` = `/${string}`,
320
327
  Plugins extends Record<string, unknown> = Record<string, unknown>,
321
328
  Local extends ExtendSettings<Href> = ExtendSettings<Href>,
329
+ UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,
322
330
  > = {
323
331
  apiVersion: 3;
324
332
  featureFlags: BlockCodeKnownFeatureFlags;
325
333
  loaded: boolean;
326
334
  error: unknown;
327
- useApp<PageHref extends Href = Href>(): AppV3<Data, Args, Outputs, PageHref, Plugins, Local>;
335
+ useApp<PageHref extends Href = Href>(): AppV3<
336
+ Data,
337
+ Args,
338
+ Outputs,
339
+ PageHref,
340
+ Plugins,
341
+ Local,
342
+ UiServices
343
+ >;
328
344
  install(app: VueApp): void;
329
345
  };
330
346
 
@@ -165,6 +165,11 @@ function createMockApiV3<
165
165
  async dispose(): Promise<ResultOrError<void>> {
166
166
  return { value: undefined };
167
167
  },
168
+ serviceDispatch: {
169
+ getServiceNames: () => [],
170
+ getServiceMethods: () => [],
171
+ callServiceMethod: () => undefined,
172
+ },
168
173
  //
169
174
  blobDriver: undefined as any,
170
175
  //
@@ -12,6 +12,7 @@ import type {
12
12
  PluginHandle,
13
13
  InferFactoryData,
14
14
  InferFactoryOutputs,
15
+ InferFactoryUiServices,
15
16
  PluginFactoryLike,
16
17
  } from "@platforma-sdk/model";
17
18
  import {
@@ -21,9 +22,13 @@ import {
21
22
  getPluginData,
22
23
  isPluginOutputKey,
23
24
  pluginOutputPrefix,
25
+ createNodeServiceProxy,
26
+ buildServices,
24
27
  } from "@platforma-sdk/model";
28
+ import { type UiServices as AllUiServices } from "@milaboratories/pl-model-common";
29
+ import { createUiServiceRegistry } from "./service_factories";
25
30
  import type { Ref } from "vue";
26
- import { reactive, computed, ref } from "vue";
31
+ import { reactive, computed, ref, markRaw } from "vue";
27
32
  import type { OutputValues, OutputErrors, AppSettings } from "../types";
28
33
  import { parseQuery } from "../urls";
29
34
  import { ensureOutputHasStableFlag, MultiError } from "../utils";
@@ -35,10 +40,11 @@ import type { PluginState, PluginAccess } from "../usePlugin";
35
40
  export const patchPoolingDelay = 150;
36
41
 
37
42
  /** Internal per-plugin state with reconciliation support. */
38
- interface InternalPluginState<Data = unknown, Outputs = unknown> extends PluginState<
39
- Data,
40
- Outputs
41
- > {
43
+ interface InternalPluginState<
44
+ Data = unknown,
45
+ Outputs = unknown,
46
+ Services = Record<string, unknown>,
47
+ > extends PluginState<Data, Outputs, Services> {
42
48
  readonly ignoreUpdates: (fn: () => void) => void;
43
49
  }
44
50
 
@@ -75,9 +81,10 @@ export function createAppV3<
75
81
  Outputs extends BlockOutputsBase = BlockOutputsBase,
76
82
  Href extends `/${string}` = `/${string}`,
77
83
  Plugins extends Record<string, unknown> = Record<string, unknown>,
84
+ UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,
78
85
  >(
79
86
  state: ValueWithUTag<BlockStateV3<Data, Outputs, Href>>,
80
- platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins>>,
87
+ platforma: PlatformaExtended<PlatformaV3<Data, Args, Outputs, Href, Plugins, UiServices>>,
81
88
  settings: AppSettings,
82
89
  ) {
83
90
  const debug = (msg: string, ...rest: unknown[]) => {
@@ -223,12 +230,11 @@ export function createAppV3<
223
230
  (async () => {
224
231
  window.addEventListener("beforeunload", () => {
225
232
  closedRef.value = true;
226
- platforma
227
- .dispose()
228
- .then(unwrapResult)
229
- .catch((err) => {
233
+ Promise.allSettled([uiRegistry.dispose(), platforma.dispose().then(unwrapResult)]).catch(
234
+ (err) => {
230
235
  error("error in dispose", err);
231
- });
236
+ },
237
+ );
232
238
  });
233
239
 
234
240
  while (!closedRef.value) {
@@ -328,6 +334,10 @@ export function createAppV3<
328
334
  },
329
335
  };
330
336
 
337
+ const proxy = createNodeServiceProxy(platforma.serviceDispatch);
338
+ const uiRegistry = createUiServiceRegistry({ proxy });
339
+ const services = buildServices<UiServices>(platforma.serviceDispatch, uiRegistry);
340
+
331
341
  /** Creates a lazily-cached per-plugin reactive state. */
332
342
  const createPluginState = <F extends PluginFactoryLike>(
333
343
  handle: PluginHandle<F>,
@@ -387,6 +397,7 @@ export function createAppV3<
387
397
 
388
398
  return {
389
399
  model: pluginModel,
400
+ services: markRaw(services),
390
401
  ignoreUpdates,
391
402
  };
392
403
  };
@@ -396,11 +407,19 @@ export function createAppV3<
396
407
  getOrCreatePluginState<F extends PluginFactoryLike>(handle: PluginHandle<F>) {
397
408
  const existing = pluginStates.get(handle);
398
409
  if (existing) {
399
- return existing as unknown as PluginState<InferFactoryData<F>, InferFactoryOutputs<F>>;
410
+ return existing as unknown as PluginState<
411
+ InferFactoryData<F>,
412
+ InferFactoryOutputs<F>,
413
+ InferFactoryUiServices<F>
414
+ >;
400
415
  }
401
416
  const state = createPluginState(handle);
402
417
  pluginStates.set(handle, state);
403
- return state;
418
+ return state as unknown as PluginState<
419
+ InferFactoryData<F>,
420
+ InferFactoryOutputs<F>,
421
+ InferFactoryUiServices<F>
422
+ >;
404
423
  },
405
424
  };
406
425
 
@@ -412,6 +431,7 @@ export function createAppV3<
412
431
  closedRef,
413
432
  snapshot,
414
433
  plugins,
434
+ services: markRaw(services),
415
435
  queryParams: computed(() => parseQuery<Href>(snapshot.value.navigationState.href as Href)),
416
436
  href: computed(() => snapshot.value.navigationState.href),
417
437
  hasErrors: computed(() =>
@@ -435,4 +455,5 @@ export type BaseAppV3<
435
455
  Outputs extends BlockOutputsBase = BlockOutputsBase,
436
456
  Href extends `/${string}` = `/${string}`,
437
457
  Plugins extends Record<string, unknown> = Record<string, unknown>,
438
- > = ReturnType<typeof createAppV3<Data, Args, Outputs, Href, Plugins>>["app"];
458
+ UiServices extends Partial<AllUiServices> = Partial<AllUiServices>,
459
+ > = ReturnType<typeof createAppV3<Data, Args, Outputs, Href, Plugins, UiServices>>["app"];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * UI service factories — add a factory for each new service here.
3
+ *
4
+ * Each entry maps a Services key to a factory function that creates the
5
+ * UI-side driver instance:
6
+ * - WASM services: instantiated directly (e.g. SpecDriver)
7
+ * - Node services: proxied via IPC using NodeServiceProxy
8
+ */
9
+
10
+ import { Services, UiServiceRegistry } from "@milaboratories/pl-model-common";
11
+ import { SpecDriver } from "@milaboratories/pf-spec-driver";
12
+ import type { NodeServiceProxy } from "@platforma-sdk/model";
13
+
14
+ export type UiServiceOptions = {
15
+ proxy: NodeServiceProxy;
16
+ };
17
+
18
+ export function createUiServiceRegistry(options: UiServiceOptions) {
19
+ return new UiServiceRegistry(Services, {
20
+ PFrameSpec: () => new SpecDriver(),
21
+ PFrame: () => options.proxy(Services.PFrame),
22
+ });
23
+ }
package/src/usePlugin.ts CHANGED
@@ -4,11 +4,16 @@ import type {
4
4
  PluginHandle,
5
5
  InferFactoryData,
6
6
  InferFactoryOutputs,
7
+ InferFactoryUiServices,
7
8
  PluginFactoryLike,
8
9
  } from "@platforma-sdk/model";
9
10
 
10
11
  /** Per-plugin reactive model exposed to consumers via usePlugin(). */
11
- export interface PluginState<Data = unknown, Outputs = unknown> {
12
+ export interface PluginState<
13
+ Data = unknown,
14
+ Outputs = unknown,
15
+ Services = Record<string, unknown>,
16
+ > {
12
17
  readonly model: Reactive<{
13
18
  data: Data;
14
19
  outputs: Outputs extends Record<string, unknown>
@@ -18,13 +23,14 @@ export interface PluginState<Data = unknown, Outputs = unknown> {
18
23
  ? { [K in keyof Outputs]?: Error }
19
24
  : Record<string, Error | undefined>;
20
25
  }>;
26
+ readonly services: Services;
21
27
  }
22
28
 
23
29
  /** Internal interface for plugin access — provided via Vue injection to usePlugin(). */
24
30
  export interface PluginAccess {
25
31
  getOrCreatePluginState<F extends PluginFactoryLike>(
26
32
  handle: PluginHandle<F>,
27
- ): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>>;
33
+ ): PluginState<InferFactoryData<F>, InferFactoryOutputs<F>, InferFactoryUiServices<F>>;
28
34
  }
29
35
 
30
36
  /**