@platforma-sdk/model 1.58.5 → 1.58.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.cjs +43 -0
- package/dist/_virtual/_rolldown/runtime.js +18 -0
- package/dist/annotations/converter.cjs +15 -20
- package/dist/annotations/converter.cjs.map +1 -1
- package/dist/annotations/converter.d.ts +6 -2
- package/dist/annotations/converter.js +14 -18
- package/dist/annotations/converter.js.map +1 -1
- package/dist/annotations/index.cjs +1 -0
- package/dist/annotations/index.d.ts +2 -3
- package/dist/annotations/index.js +1 -0
- package/dist/annotations/types.d.ts +21 -16
- package/dist/bconfig/index.cjs +2 -0
- package/dist/bconfig/index.d.ts +5 -6
- package/dist/bconfig/index.js +2 -0
- package/dist/bconfig/lambdas.d.ts +52 -52
- package/dist/bconfig/normalization.cjs +13 -18
- package/dist/bconfig/normalization.cjs.map +1 -1
- package/dist/bconfig/normalization.d.ts +10 -6
- package/dist/bconfig/normalization.js +12 -16
- package/dist/bconfig/normalization.js.map +1 -1
- package/dist/bconfig/types.cjs +4 -3
- package/dist/bconfig/types.cjs.map +1 -1
- package/dist/bconfig/types.d.ts +10 -5
- package/dist/bconfig/types.js +4 -2
- package/dist/bconfig/types.js.map +1 -1
- package/dist/bconfig/util.d.ts +7 -4
- package/dist/bconfig/v3.d.ts +10 -6
- package/dist/block_api_v1.d.ts +62 -58
- package/dist/block_api_v2.d.ts +51 -47
- package/dist/block_api_v3.d.ts +33 -29
- package/dist/block_migrations.cjs +481 -413
- package/dist/block_migrations.cjs.map +1 -1
- package/dist/block_migrations.d.ts +258 -204
- package/dist/block_migrations.js +482 -408
- package/dist/block_migrations.js.map +1 -1
- package/dist/block_model.cjs +312 -343
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts +143 -147
- package/dist/block_model.js +312 -341
- package/dist/block_model.js.map +1 -1
- package/dist/block_model_legacy.cjs +231 -255
- package/dist/block_model_legacy.cjs.map +1 -1
- package/dist/block_model_legacy.d.ts +108 -106
- package/dist/block_model_legacy.js +231 -253
- package/dist/block_model_legacy.js.map +1 -1
- package/dist/block_state_patch.d.ts +10 -10
- package/dist/block_state_util.cjs +15 -19
- package/dist/block_state_util.cjs.map +1 -1
- package/dist/block_state_util.d.ts +14 -13
- package/dist/block_state_util.js +15 -18
- package/dist/block_state_util.js.map +1 -1
- package/dist/block_storage.cjs +233 -238
- package/dist/block_storage.cjs.map +1 -1
- package/dist/block_storage.d.ts +62 -78
- package/dist/block_storage.js +234 -237
- package/dist/block_storage.js.map +1 -1
- package/dist/block_storage_callbacks.cjs +156 -195
- package/dist/block_storage_callbacks.cjs.map +1 -1
- package/dist/block_storage_callbacks.js +156 -192
- package/dist/block_storage_callbacks.js.map +1 -1
- package/dist/block_storage_facade.cjs +29 -85
- package/dist/block_storage_facade.cjs.map +1 -1
- package/dist/block_storage_facade.d.ts +83 -126
- package/dist/block_storage_facade.js +29 -83
- package/dist/block_storage_facade.js.map +1 -1
- package/dist/components/PFrameForGraphs.cjs +26 -24
- package/dist/components/PFrameForGraphs.cjs.map +1 -1
- package/dist/components/PFrameForGraphs.d.ts +12 -7
- package/dist/components/PFrameForGraphs.js +25 -22
- package/dist/components/PFrameForGraphs.js.map +1 -1
- package/dist/components/PlAnnotations/filter.d.ts +62 -79
- package/dist/components/PlAnnotations/filters_ui.cjs +135 -171
- package/dist/components/PlAnnotations/filters_ui.cjs.map +1 -1
- package/dist/components/PlAnnotations/filters_ui.d.ts +48 -46
- package/dist/components/PlAnnotations/filters_ui.js +135 -170
- package/dist/components/PlAnnotations/filters_ui.js.map +1 -1
- package/dist/components/PlAnnotations/index.d.ts +2 -3
- package/dist/components/PlDataTable/index.cjs +2 -0
- package/dist/components/PlDataTable/index.d.ts +3 -5
- package/dist/components/PlDataTable/index.js +2 -0
- package/dist/components/PlDataTable/labels.cjs +59 -81
- package/dist/components/PlDataTable/labels.cjs.map +1 -1
- package/dist/components/PlDataTable/labels.js +58 -79
- package/dist/components/PlDataTable/labels.js.map +1 -1
- package/dist/components/PlDataTable/state-migration.cjs +186 -144
- package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
- package/dist/components/PlDataTable/state-migration.d.ts +85 -82
- package/dist/components/PlDataTable/state-migration.js +185 -142
- package/dist/components/PlDataTable/state-migration.js.map +1 -1
- package/dist/components/PlDataTable/table.cjs +172 -194
- package/dist/components/PlDataTable/table.cjs.map +1 -1
- package/dist/components/PlDataTable/table.d.ts +16 -12
- package/dist/components/PlDataTable/table.js +171 -192
- package/dist/components/PlDataTable/table.js.map +1 -1
- package/dist/components/PlDataTable/v4.d.ts +84 -119
- package/dist/components/PlDataTable/v5.d.ts +80 -103
- package/dist/components/PlMultiSequenceAlignment.cjs +27 -29
- package/dist/components/PlMultiSequenceAlignment.cjs.map +1 -1
- package/dist/components/PlMultiSequenceAlignment.d.ts +36 -27
- package/dist/components/PlMultiSequenceAlignment.js +26 -27
- package/dist/components/PlMultiSequenceAlignment.js.map +1 -1
- package/dist/components/PlSelectionModel.cjs +7 -6
- package/dist/components/PlSelectionModel.cjs.map +1 -1
- package/dist/components/PlSelectionModel.d.ts +10 -8
- package/dist/components/PlSelectionModel.js +7 -5
- package/dist/components/PlSelectionModel.js.map +1 -1
- package/dist/components/index.cjs +8 -0
- package/dist/components/index.d.ts +11 -6
- package/dist/components/index.js +8 -0
- package/dist/config/actions.cjs +138 -171
- package/dist/config/actions.cjs.map +1 -1
- package/dist/config/actions.d.ts +47 -47
- package/dist/config/actions.js +146 -178
- package/dist/config/actions.js.map +1 -1
- package/dist/config/actions_kinds.d.ts +114 -121
- package/dist/config/index.cjs +1 -0
- package/dist/config/index.d.ts +6 -7
- package/dist/config/index.js +1 -0
- package/dist/config/model.d.ts +131 -127
- package/dist/config/model_meta.d.ts +4 -1
- package/dist/config/type_engine.d.ts +22 -21
- package/dist/config/type_util.d.ts +12 -10
- package/dist/env_value.cjs +5 -6
- package/dist/env_value.cjs.map +1 -1
- package/dist/env_value.d.ts +4 -1
- package/dist/env_value.js +5 -5
- package/dist/env_value.js.map +1 -1
- package/dist/filters/converters/filterToQuery.cjs +273 -239
- package/dist/filters/converters/filterToQuery.cjs.map +1 -1
- package/dist/filters/converters/filterToQuery.d.ts +6 -2
- package/dist/filters/converters/filterToQuery.js +272 -237
- package/dist/filters/converters/filterToQuery.js.map +1 -1
- package/dist/filters/converters/filterUiToExpressionImpl.cjs +56 -85
- package/dist/filters/converters/filterUiToExpressionImpl.cjs.map +1 -1
- package/dist/filters/converters/filterUiToExpressionImpl.d.ts +8 -4
- package/dist/filters/converters/filterUiToExpressionImpl.js +55 -83
- package/dist/filters/converters/filterUiToExpressionImpl.js.map +1 -1
- package/dist/filters/converters/index.cjs +2 -0
- package/dist/filters/converters/index.d.ts +2 -3
- package/dist/filters/converters/index.js +2 -0
- package/dist/filters/distill.cjs +59 -60
- package/dist/filters/distill.cjs.map +1 -1
- package/dist/filters/distill.d.ts +6 -3
- package/dist/filters/distill.js +58 -58
- package/dist/filters/distill.js.map +1 -1
- package/dist/filters/index.cjs +4 -0
- package/dist/filters/index.d.ts +5 -4
- package/dist/filters/index.js +4 -0
- package/dist/filters/traverse.cjs +31 -40
- package/dist/filters/traverse.cjs.map +1 -1
- package/dist/filters/traverse.js +31 -39
- package/dist/filters/traverse.js.map +1 -1
- package/dist/filters/types.d.ts +10 -7
- package/dist/index.cjs +193 -187
- package/dist/index.d.ts +61 -28
- package/dist/index.js +49 -41
- package/dist/internal.cjs +48 -62
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.js +49 -60
- package/dist/internal.js.map +1 -1
- package/dist/package.cjs +12 -0
- package/dist/package.cjs.map +1 -0
- package/dist/package.js +6 -0
- package/dist/package.js.map +1 -0
- package/dist/pframe.cjs +32 -37
- package/dist/pframe.cjs.map +1 -1
- package/dist/pframe.d.ts +14 -10
- package/dist/pframe.js +32 -35
- package/dist/pframe.js.map +1 -1
- package/dist/pframe_utils/axes.cjs +81 -114
- package/dist/pframe_utils/axes.cjs.map +1 -1
- package/dist/pframe_utils/axes.d.ts +10 -13
- package/dist/pframe_utils/axes.js +80 -112
- package/dist/pframe_utils/axes.js.map +1 -1
- package/dist/pframe_utils/columns.cjs +61 -81
- package/dist/pframe_utils/columns.cjs.map +1 -1
- package/dist/pframe_utils/columns.d.ts +15 -6
- package/dist/pframe_utils/columns.js +60 -79
- package/dist/pframe_utils/columns.js.map +1 -1
- package/dist/pframe_utils/index.cjs +232 -253
- package/dist/pframe_utils/index.cjs.map +1 -1
- package/dist/pframe_utils/index.d.ts +39 -35
- package/dist/pframe_utils/index.js +231 -251
- package/dist/pframe_utils/index.js.map +1 -1
- package/dist/platforma.d.ts +48 -46
- package/dist/plugin_handle.cjs +6 -14
- package/dist/plugin_handle.cjs.map +1 -1
- package/dist/plugin_handle.d.ts +20 -25
- package/dist/plugin_handle.js +6 -13
- package/dist/plugin_handle.js.map +1 -1
- package/dist/plugin_model.cjs +364 -163
- package/dist/plugin_model.cjs.map +1 -1
- package/dist/plugin_model.d.ts +280 -129
- package/dist/plugin_model.js +362 -163
- package/dist/plugin_model.js.map +1 -1
- package/dist/raw_globals.cjs +10 -22
- package/dist/raw_globals.cjs.map +1 -1
- package/dist/raw_globals.d.ts +8 -5
- package/dist/raw_globals.js +10 -20
- package/dist/raw_globals.js.map +1 -1
- package/dist/ref_util.cjs +14 -13
- package/dist/ref_util.cjs.map +1 -1
- package/dist/ref_util.d.ts +18 -12
- package/dist/ref_util.js +14 -11
- package/dist/ref_util.js.map +1 -1
- package/dist/render/accessor.cjs +213 -226
- package/dist/render/accessor.cjs.map +1 -1
- package/dist/render/accessor.d.ts +115 -120
- package/dist/render/accessor.js +212 -224
- package/dist/render/accessor.js.map +1 -1
- package/dist/render/api.cjs +478 -580
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +207 -209
- package/dist/render/api.js +476 -578
- package/dist/render/api.js.map +1 -1
- package/dist/render/future.cjs +28 -32
- package/dist/render/future.cjs.map +1 -1
- package/dist/render/future.d.ts +15 -11
- package/dist/render/future.js +28 -30
- package/dist/render/future.js.map +1 -1
- package/dist/render/index.cjs +8 -0
- package/dist/render/index.d.ts +10 -8
- package/dist/render/index.js +8 -0
- package/dist/render/internal.cjs +33 -29
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts +78 -72
- package/dist/render/internal.js +29 -26
- package/dist/render/internal.js.map +1 -1
- package/dist/render/traversal_ops.d.ts +42 -43
- package/dist/render/util/axis_filtering.cjs +63 -86
- package/dist/render/util/axis_filtering.cjs.map +1 -1
- package/dist/render/util/axis_filtering.d.ts +10 -7
- package/dist/render/util/axis_filtering.js +63 -85
- package/dist/render/util/axis_filtering.js.map +1 -1
- package/dist/render/util/column_collection.cjs +266 -321
- package/dist/render/util/column_collection.cjs.map +1 -1
- package/dist/render/util/column_collection.d.ts +47 -47
- package/dist/render/util/column_collection.js +264 -319
- package/dist/render/util/column_collection.js.map +1 -1
- package/dist/render/util/index.cjs +4 -0
- package/dist/render/util/index.d.ts +4 -5
- package/dist/render/util/index.js +4 -0
- package/dist/render/util/label.cjs +129 -163
- package/dist/render/util/label.cjs.map +1 -1
- package/dist/render/util/label.d.ts +45 -46
- package/dist/render/util/label.js +128 -161
- package/dist/render/util/label.js.map +1 -1
- package/dist/render/util/pcolumn_data.cjs +315 -375
- package/dist/render/util/pcolumn_data.cjs.map +1 -1
- package/dist/render/util/pcolumn_data.d.ts +33 -32
- package/dist/render/util/pcolumn_data.js +314 -373
- package/dist/render/util/pcolumn_data.js.map +1 -1
- package/dist/render/util/pframe_upgraders.cjs +37 -42
- package/dist/render/util/pframe_upgraders.cjs.map +1 -1
- package/dist/render/util/pframe_upgraders.js +37 -41
- package/dist/render/util/pframe_upgraders.js.map +1 -1
- package/dist/render/util/split_selectors.d.ts +13 -9
- package/dist/version.cjs +6 -8
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.ts +7 -4
- package/dist/version.js +5 -5
- package/dist/version.js.map +1 -1
- package/package.json +10 -4
- package/src/block_migrations.test.ts +184 -14
- package/src/block_migrations.ts +185 -30
- package/src/block_model.ts +111 -66
- package/src/block_storage.test.ts +147 -3
- package/src/block_storage.ts +43 -8
- package/src/block_storage_callbacks.ts +9 -4
- package/src/env_value.ts +0 -2
- package/src/index.ts +12 -11
- package/src/internal.ts +0 -1
- package/src/platforma.ts +4 -4
- package/src/plugin_handle.ts +1 -1
- package/src/plugin_model.test.ts +217 -21
- package/src/plugin_model.ts +450 -55
- package/src/raw_globals.ts +0 -1
- package/dist/annotations/converter.d.ts.map +0 -1
- package/dist/annotations/index.d.ts.map +0 -1
- package/dist/annotations/types.d.ts.map +0 -1
- package/dist/bconfig/index.d.ts.map +0 -1
- package/dist/bconfig/lambdas.d.ts.map +0 -1
- package/dist/bconfig/normalization.d.ts.map +0 -1
- package/dist/bconfig/types.d.ts.map +0 -1
- package/dist/bconfig/util.d.ts.map +0 -1
- package/dist/bconfig/v3.d.ts.map +0 -1
- package/dist/block_api_v1.d.ts.map +0 -1
- package/dist/block_api_v2.d.ts.map +0 -1
- package/dist/block_api_v3.d.ts.map +0 -1
- package/dist/block_migrations.d.ts.map +0 -1
- package/dist/block_model.d.ts.map +0 -1
- package/dist/block_model_legacy.d.ts.map +0 -1
- package/dist/block_state_patch.d.ts.map +0 -1
- package/dist/block_state_util.d.ts.map +0 -1
- package/dist/block_storage.d.ts.map +0 -1
- package/dist/block_storage_callbacks.d.ts +0 -115
- package/dist/block_storage_callbacks.d.ts.map +0 -1
- package/dist/block_storage_facade.d.ts.map +0 -1
- package/dist/components/PFrameForGraphs.d.ts.map +0 -1
- package/dist/components/PlAnnotations/filter.d.ts.map +0 -1
- package/dist/components/PlAnnotations/filters_ui.d.ts.map +0 -1
- package/dist/components/PlAnnotations/index.d.ts.map +0 -1
- package/dist/components/PlAnnotations/types.d.ts +0 -3
- package/dist/components/PlAnnotations/types.d.ts.map +0 -1
- package/dist/components/PlDataTable/index.d.ts.map +0 -1
- package/dist/components/PlDataTable/labels.d.ts +0 -7
- package/dist/components/PlDataTable/labels.d.ts.map +0 -1
- package/dist/components/PlDataTable/state-migration.d.ts.map +0 -1
- package/dist/components/PlDataTable/table.d.ts.map +0 -1
- package/dist/components/PlDataTable/v4.d.ts.map +0 -1
- package/dist/components/PlDataTable/v5.d.ts.map +0 -1
- package/dist/components/PlMultiSequenceAlignment.d.ts.map +0 -1
- package/dist/components/PlSelectionModel.d.ts.map +0 -1
- package/dist/components/index.d.ts.map +0 -1
- package/dist/config/actions.d.ts.map +0 -1
- package/dist/config/actions_kinds.d.ts.map +0 -1
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/model.d.ts.map +0 -1
- package/dist/config/model_meta.d.ts.map +0 -1
- package/dist/config/type_engine.d.ts.map +0 -1
- package/dist/config/type_util.d.ts.map +0 -1
- package/dist/env_value.d.ts.map +0 -1
- package/dist/filters/converters/filterToQuery.d.ts.map +0 -1
- package/dist/filters/converters/filterUiToExpressionImpl.d.ts.map +0 -1
- package/dist/filters/converters/index.d.ts.map +0 -1
- package/dist/filters/distill.d.ts.map +0 -1
- package/dist/filters/index.d.ts.map +0 -1
- package/dist/filters/traverse.d.ts +0 -27
- package/dist/filters/traverse.d.ts.map +0 -1
- package/dist/filters/types.d.ts.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal.d.ts +0 -36
- package/dist/internal.d.ts.map +0 -1
- package/dist/package.json.cjs +0 -6
- package/dist/package.json.cjs.map +0 -1
- package/dist/package.json.js +0 -4
- package/dist/package.json.js.map +0 -1
- package/dist/pframe.d.ts.map +0 -1
- package/dist/pframe_utils/axes.d.ts.map +0 -1
- package/dist/pframe_utils/columns.d.ts.map +0 -1
- package/dist/pframe_utils/index.d.ts.map +0 -1
- package/dist/pframe_utils/querySpec.d.ts +0 -2
- package/dist/pframe_utils/querySpec.d.ts.map +0 -1
- package/dist/platforma.d.ts.map +0 -1
- package/dist/plugin_handle.d.ts.map +0 -1
- package/dist/plugin_model.d.ts.map +0 -1
- package/dist/raw_globals.d.ts.map +0 -1
- package/dist/ref_util.d.ts.map +0 -1
- package/dist/render/accessor.d.ts.map +0 -1
- package/dist/render/api.d.ts.map +0 -1
- package/dist/render/future.d.ts.map +0 -1
- package/dist/render/index.d.ts.map +0 -1
- package/dist/render/internal.d.ts.map +0 -1
- package/dist/render/traversal_ops.d.ts.map +0 -1
- package/dist/render/util/axis_filtering.d.ts.map +0 -1
- package/dist/render/util/column_collection.d.ts.map +0 -1
- package/dist/render/util/index.d.ts.map +0 -1
- package/dist/render/util/label.d.ts.map +0 -1
- package/dist/render/util/pcolumn_data.d.ts.map +0 -1
- package/dist/render/util/pframe_upgraders.d.ts +0 -3
- package/dist/render/util/pframe_upgraders.d.ts.map +0 -1
- package/dist/render/util/split_selectors.d.ts.map +0 -1
- package/dist/version.d.ts.map +0 -1
package/src/block_migrations.ts
CHANGED
|
@@ -5,6 +5,31 @@ export type DataMigrateFn<From, To> = (prev: Readonly<From>) => To;
|
|
|
5
5
|
export type DataCreateFn<T> = () => T;
|
|
6
6
|
export type DataRecoverFn<T> = (version: DataVersionKey, data: unknown) => T;
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Minimal interface that .transfer() accepts. PluginInstance implements this.
|
|
10
|
+
* Defined here to avoid circular dependency with plugin_model.ts.
|
|
11
|
+
*/
|
|
12
|
+
export interface TransferTarget<Id extends string = string, TransferData = never> {
|
|
13
|
+
readonly id: Id;
|
|
14
|
+
/** Version key in the plugin's data model chain where transferred data enters. */
|
|
15
|
+
readonly transferVersion: string;
|
|
16
|
+
/** @internal Phantom field for TransferData type extraction */
|
|
17
|
+
readonly __transferBrand?: TransferData;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Internal record of a single transfer step in the migration chain. */
|
|
21
|
+
export type TransferStep = {
|
|
22
|
+
pluginId: string;
|
|
23
|
+
/** Capture data before this step index executes. */
|
|
24
|
+
beforeStepIndex: number;
|
|
25
|
+
extract: (data: unknown) => unknown;
|
|
26
|
+
/** Version key in the plugin's data model chain where the transferred data enters. */
|
|
27
|
+
targetVersion: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Map of plugin ID → versioned data extracted during migration. */
|
|
31
|
+
export type TransferRecord = Record<string, DataVersioned<unknown>>;
|
|
32
|
+
|
|
8
33
|
/** Versioned data wrapper for persistence */
|
|
9
34
|
export type DataVersioned<T> = {
|
|
10
35
|
version: DataVersionKey;
|
|
@@ -12,7 +37,7 @@ export type DataVersioned<T> = {
|
|
|
12
37
|
};
|
|
13
38
|
|
|
14
39
|
/** Create a DataVersioned wrapper with correct shape */
|
|
15
|
-
export function
|
|
40
|
+
export function makeVersionedData<T>(version: DataVersionKey, data: T): DataVersioned<T> {
|
|
16
41
|
return { version, data };
|
|
17
42
|
}
|
|
18
43
|
|
|
@@ -68,6 +93,7 @@ export type LegacyV1State<Args, UiState> = { args: Args; uiState: UiState };
|
|
|
68
93
|
type BuilderState<S> = {
|
|
69
94
|
versionChain: DataVersionKey[];
|
|
70
95
|
steps: MigrationStep[];
|
|
96
|
+
transferSteps: TransferStep[];
|
|
71
97
|
initialDataFn: () => S;
|
|
72
98
|
recoverFn?: (version: DataVersionKey, data: unknown) => unknown;
|
|
73
99
|
/** Index of the first step to run after recovery. Equals the number of steps
|
|
@@ -89,13 +115,19 @@ type RecoverState = {
|
|
|
89
115
|
*
|
|
90
116
|
* @internal
|
|
91
117
|
*/
|
|
92
|
-
abstract class MigrationChainBase<Current> {
|
|
118
|
+
abstract class MigrationChainBase<Current, Transfers extends Record<string, unknown> = {}> {
|
|
93
119
|
protected readonly versionChain: DataVersionKey[];
|
|
94
120
|
protected readonly migrationSteps: MigrationStep[];
|
|
121
|
+
protected readonly transferSteps: TransferStep[];
|
|
95
122
|
|
|
96
|
-
protected constructor(state: {
|
|
123
|
+
protected constructor(state: {
|
|
124
|
+
versionChain: DataVersionKey[];
|
|
125
|
+
steps: MigrationStep[];
|
|
126
|
+
transferSteps?: TransferStep[];
|
|
127
|
+
}) {
|
|
97
128
|
this.versionChain = state.versionChain;
|
|
98
129
|
this.migrationSteps = state.steps;
|
|
130
|
+
this.transferSteps = state.transferSteps ?? [];
|
|
99
131
|
}
|
|
100
132
|
|
|
101
133
|
/** Appends a migration step and returns the new versionChain and steps arrays. */
|
|
@@ -118,6 +150,23 @@ abstract class MigrationChainBase<Current> {
|
|
|
118
150
|
};
|
|
119
151
|
}
|
|
120
152
|
|
|
153
|
+
/** Validates uniqueness and records a TransferStep. */
|
|
154
|
+
protected buildTransfer<Id extends string, L>(
|
|
155
|
+
target: TransferTarget<Id, L>,
|
|
156
|
+
extract: (data: Current) => L,
|
|
157
|
+
): { transferSteps: TransferStep[] } {
|
|
158
|
+
if (this.transferSteps.some((t) => t.pluginId === target.id)) {
|
|
159
|
+
throw new Error(`Duplicate transfer for plugin '${target.id}'`);
|
|
160
|
+
}
|
|
161
|
+
const entry: TransferStep = {
|
|
162
|
+
pluginId: target.id,
|
|
163
|
+
beforeStepIndex: this.migrationSteps.length,
|
|
164
|
+
extract: extract as (data: unknown) => unknown,
|
|
165
|
+
targetVersion: target.transferVersion,
|
|
166
|
+
};
|
|
167
|
+
return { transferSteps: [...this.transferSteps, entry] };
|
|
168
|
+
}
|
|
169
|
+
|
|
121
170
|
/** Returns recover-specific fields for DataModel construction. Overridden by WithRecover. */
|
|
122
171
|
protected recoverState(): RecoverState {
|
|
123
172
|
return {};
|
|
@@ -129,10 +178,11 @@ abstract class MigrationChainBase<Current> {
|
|
|
129
178
|
* @param initialData - Factory function returning the initial state
|
|
130
179
|
* @returns Finalized DataModel instance
|
|
131
180
|
*/
|
|
132
|
-
init(initialData: DataCreateFn<Current>): DataModel<Current> {
|
|
133
|
-
return DataModel[FROM_BUILDER]<Current>({
|
|
181
|
+
init(initialData: DataCreateFn<Current>): DataModel<Current, Transfers> {
|
|
182
|
+
return DataModel[FROM_BUILDER]<Current, Transfers>({
|
|
134
183
|
versionChain: this.versionChain,
|
|
135
184
|
steps: this.migrationSteps,
|
|
185
|
+
transferSteps: this.transferSteps,
|
|
136
186
|
initialDataFn: initialData,
|
|
137
187
|
...this.recoverState(),
|
|
138
188
|
});
|
|
@@ -141,13 +191,17 @@ abstract class MigrationChainBase<Current> {
|
|
|
141
191
|
|
|
142
192
|
/**
|
|
143
193
|
* Migration chain after recover() or upgradeLegacy() has been called.
|
|
144
|
-
* Further migrate() calls are allowed; recover() and upgradeLegacy() are not
|
|
194
|
+
* Further migrate() and transfer() calls are allowed; recover() and upgradeLegacy() are not
|
|
145
195
|
* (enforced by type — no such methods on this class).
|
|
146
196
|
*
|
|
147
197
|
* @typeParam Current - Data type at the current point in the chain
|
|
198
|
+
* @typeParam Transfers - Accumulated transfer types keyed by plugin ID
|
|
148
199
|
* @internal
|
|
149
200
|
*/
|
|
150
|
-
class DataModelMigrationChainWithRecover<
|
|
201
|
+
class DataModelMigrationChainWithRecover<
|
|
202
|
+
Current,
|
|
203
|
+
Transfers extends Record<string, unknown> = {},
|
|
204
|
+
> extends MigrationChainBase<Current, Transfers> {
|
|
151
205
|
private readonly recoverFn?: (version: DataVersionKey, data: unknown) => unknown;
|
|
152
206
|
private readonly recoverFromIndex?: number;
|
|
153
207
|
|
|
@@ -155,6 +209,7 @@ class DataModelMigrationChainWithRecover<Current> extends MigrationChainBase<Cur
|
|
|
155
209
|
constructor(state: {
|
|
156
210
|
versionChain: DataVersionKey[];
|
|
157
211
|
steps: MigrationStep[];
|
|
212
|
+
transferSteps?: TransferStep[];
|
|
158
213
|
recoverFn?: (version: DataVersionKey, data: unknown) => unknown;
|
|
159
214
|
recoverFromIndex?: number;
|
|
160
215
|
}) {
|
|
@@ -177,11 +232,31 @@ class DataModelMigrationChainWithRecover<Current> extends MigrationChainBase<Cur
|
|
|
177
232
|
migrate<Next>(
|
|
178
233
|
nextVersion: string,
|
|
179
234
|
fn: DataMigrateFn<Current, Next>,
|
|
180
|
-
): DataModelMigrationChainWithRecover<Next> {
|
|
235
|
+
): DataModelMigrationChainWithRecover<Next, Transfers> {
|
|
181
236
|
const { versionChain, steps } = this.buildStep(nextVersion, fn);
|
|
182
|
-
return new DataModelMigrationChainWithRecover<Next>({
|
|
237
|
+
return new DataModelMigrationChainWithRecover<Next, Transfers>({
|
|
183
238
|
versionChain,
|
|
184
239
|
steps,
|
|
240
|
+
transferSteps: this.transferSteps,
|
|
241
|
+
recoverFn: this.recoverFn,
|
|
242
|
+
recoverFromIndex: this.recoverFromIndex,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Extract data at the current chain position for seeding a new plugin.
|
|
248
|
+
* The extract function's return type must match the plugin's transfer data type.
|
|
249
|
+
* Duplicate plugin IDs are rejected at both type and runtime level.
|
|
250
|
+
*/
|
|
251
|
+
transfer<Id extends string, L>(
|
|
252
|
+
target: TransferTarget<Id & (Id extends keyof Transfers ? never : string), L>,
|
|
253
|
+
extract: (data: Current) => L,
|
|
254
|
+
): DataModelMigrationChainWithRecover<Current, Transfers & Record<Id, L>> {
|
|
255
|
+
const { transferSteps } = this.buildTransfer(target, extract);
|
|
256
|
+
return new DataModelMigrationChainWithRecover<Current, Transfers & Record<Id, L>>({
|
|
257
|
+
versionChain: this.versionChain,
|
|
258
|
+
steps: this.migrationSteps,
|
|
259
|
+
transferSteps,
|
|
185
260
|
recoverFn: this.recoverFn,
|
|
186
261
|
recoverFromIndex: this.recoverFromIndex,
|
|
187
262
|
});
|
|
@@ -195,18 +270,24 @@ class DataModelMigrationChainWithRecover<Current> extends MigrationChainBase<Cur
|
|
|
195
270
|
* Duplicate version keys throw at runtime.
|
|
196
271
|
*
|
|
197
272
|
* @typeParam Current - Data type at the current point in the migration chain
|
|
273
|
+
* @typeParam Transfers - Accumulated transfer types keyed by plugin ID
|
|
198
274
|
* @internal
|
|
199
275
|
*/
|
|
200
|
-
class DataModelMigrationChain<
|
|
276
|
+
class DataModelMigrationChain<
|
|
277
|
+
Current,
|
|
278
|
+
Transfers extends Record<string, unknown> = {},
|
|
279
|
+
> extends MigrationChainBase<Current, Transfers> {
|
|
201
280
|
/** @internal */
|
|
202
281
|
constructor({
|
|
203
282
|
versionChain,
|
|
204
283
|
steps = [],
|
|
284
|
+
transferSteps = [],
|
|
205
285
|
}: {
|
|
206
286
|
versionChain: DataVersionKey[];
|
|
207
287
|
steps?: MigrationStep[];
|
|
288
|
+
transferSteps?: TransferStep[];
|
|
208
289
|
}) {
|
|
209
|
-
super({ versionChain, steps });
|
|
290
|
+
super({ versionChain, steps, transferSteps });
|
|
210
291
|
}
|
|
211
292
|
|
|
212
293
|
/**
|
|
@@ -223,9 +304,38 @@ class DataModelMigrationChain<Current> extends MigrationChainBase<Current> {
|
|
|
223
304
|
migrate<Next>(
|
|
224
305
|
nextVersion: string,
|
|
225
306
|
fn: DataMigrateFn<Current, Next>,
|
|
226
|
-
): DataModelMigrationChain<Next> {
|
|
307
|
+
): DataModelMigrationChain<Next, Transfers> {
|
|
227
308
|
const { versionChain, steps } = this.buildStep(nextVersion, fn);
|
|
228
|
-
return new DataModelMigrationChain<Next>({
|
|
309
|
+
return new DataModelMigrationChain<Next, Transfers>({
|
|
310
|
+
versionChain,
|
|
311
|
+
steps,
|
|
312
|
+
transferSteps: this.transferSteps,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Extract data at the current chain position for seeding a new plugin.
|
|
318
|
+
* The extract function's return type must match the plugin's transfer data type.
|
|
319
|
+
* Duplicate plugin IDs are rejected at both type and runtime level.
|
|
320
|
+
*
|
|
321
|
+
* Calling .transfer() on DataModelInitialChain returns DataModelMigrationChain,
|
|
322
|
+
* which removes .upgradeLegacy() from the chain (preventing a problematic combination).
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* .from<V1>("v1")
|
|
326
|
+
* .transfer(tablePlugin, (v1) => ({ state: v1.tableState }))
|
|
327
|
+
* .migrate<V2>("v2", ({ tableState: _, ...rest }) => rest)
|
|
328
|
+
*/
|
|
329
|
+
transfer<Id extends string, L>(
|
|
330
|
+
target: TransferTarget<Id & (Id extends keyof Transfers ? never : string), L>,
|
|
331
|
+
extract: (data: Current) => L,
|
|
332
|
+
): DataModelMigrationChain<Current, Transfers & Record<Id, L>> {
|
|
333
|
+
const { transferSteps } = this.buildTransfer(target, extract);
|
|
334
|
+
return new DataModelMigrationChain<Current, Transfers & Record<Id, L>>({
|
|
335
|
+
versionChain: this.versionChain,
|
|
336
|
+
steps: this.migrationSteps,
|
|
337
|
+
transferSteps,
|
|
338
|
+
});
|
|
229
339
|
}
|
|
230
340
|
|
|
231
341
|
/**
|
|
@@ -251,10 +361,11 @@ class DataModelMigrationChain<Current> extends MigrationChainBase<Current> {
|
|
|
251
361
|
* .migrate<V3>("v3", (v2) => ({ ...v2, description: "" }))
|
|
252
362
|
* .init(() => ({ count: 0, label: "", description: "" }));
|
|
253
363
|
*/
|
|
254
|
-
recover(fn: DataRecoverFn<Current>): DataModelMigrationChainWithRecover<Current> {
|
|
255
|
-
return new DataModelMigrationChainWithRecover<Current>({
|
|
364
|
+
recover(fn: DataRecoverFn<Current>): DataModelMigrationChainWithRecover<Current, Transfers> {
|
|
365
|
+
return new DataModelMigrationChainWithRecover<Current, Transfers>({
|
|
256
366
|
versionChain: this.versionChain,
|
|
257
367
|
steps: this.migrationSteps,
|
|
368
|
+
transferSteps: this.transferSteps,
|
|
258
369
|
recoverFn: fn as (version: DataVersionKey, data: unknown) => unknown,
|
|
259
370
|
recoverFromIndex: this.migrationSteps.length,
|
|
260
371
|
});
|
|
@@ -267,9 +378,13 @@ class DataModelMigrationChain<Current> extends MigrationChainBase<Current> {
|
|
|
267
378
|
* any `.migrate()` calls, since legacy data always arrives at the initial version.
|
|
268
379
|
*
|
|
269
380
|
* @typeParam Current - Data type at the initial version
|
|
381
|
+
* @typeParam Transfers - Accumulated transfer types keyed by plugin ID
|
|
270
382
|
* @internal
|
|
271
383
|
*/
|
|
272
|
-
class DataModelInitialChain<
|
|
384
|
+
class DataModelInitialChain<
|
|
385
|
+
Current,
|
|
386
|
+
Transfers extends Record<string, unknown> = {},
|
|
387
|
+
> extends DataModelMigrationChain<Current, Transfers> {
|
|
273
388
|
/**
|
|
274
389
|
* Handle legacy V1 model state ({ args, uiState }) when upgrading a block from
|
|
275
390
|
* BlockModel V1 to BlockModelV3.
|
|
@@ -306,7 +421,7 @@ class DataModelInitialChain<Current> extends DataModelMigrationChain<Current> {
|
|
|
306
421
|
*/
|
|
307
422
|
upgradeLegacy<Args, UiState = unknown>(
|
|
308
423
|
fn: (legacy: LegacyV1State<Args, UiState>) => Current,
|
|
309
|
-
): DataModelMigrationChainWithRecover<Current> {
|
|
424
|
+
): DataModelMigrationChainWithRecover<Current, Transfers> {
|
|
310
425
|
const wrappedFn = (data: unknown): unknown => {
|
|
311
426
|
if (data !== null && typeof data === "object" && "args" in data) {
|
|
312
427
|
return fn(data as LegacyV1State<Args, UiState>);
|
|
@@ -322,9 +437,14 @@ class DataModelInitialChain<Current> extends DataModelMigrationChain<Current> {
|
|
|
322
437
|
toVersion: initialVersion,
|
|
323
438
|
migrate: wrappedFn,
|
|
324
439
|
};
|
|
325
|
-
return new DataModelMigrationChainWithRecover<Current>({
|
|
440
|
+
return new DataModelMigrationChainWithRecover<Current, Transfers>({
|
|
326
441
|
versionChain: [DATA_MODEL_LEGACY_VERSION, ...this.versionChain],
|
|
327
442
|
steps: [step, ...this.migrationSteps],
|
|
443
|
+
// Shift transfer indices to account for the prepended legacy step
|
|
444
|
+
transferSteps: this.transferSteps.map((t) => ({
|
|
445
|
+
...t,
|
|
446
|
+
beforeStepIndex: t.beforeStepIndex + 1,
|
|
447
|
+
})),
|
|
328
448
|
});
|
|
329
449
|
}
|
|
330
450
|
}
|
|
@@ -407,12 +527,16 @@ export class DataModelBuilder {
|
|
|
407
527
|
* .migrate<V3>("v3", (v2) => ({ ...v2, description: "" }))
|
|
408
528
|
* .init(() => ({ count: 0, label: "", description: "" }));
|
|
409
529
|
*/
|
|
410
|
-
export class DataModel<State> {
|
|
530
|
+
export class DataModel<State, Transfers extends Record<string, unknown> = {}> {
|
|
531
|
+
/** @internal Phantom field to anchor the Transfers type parameter. */
|
|
532
|
+
declare readonly __transfers?: Transfers;
|
|
533
|
+
|
|
411
534
|
/** Latest version key — O(1) access for the common "already current" check. */
|
|
412
535
|
private readonly latestVersion: DataVersionKey;
|
|
413
536
|
/** Maps each known version key to the index of the first step to run from it. O(1) lookup. */
|
|
414
537
|
private readonly stepsByFromVersion: ReadonlyMap<DataVersionKey, number>;
|
|
415
538
|
private readonly steps: MigrationStep[];
|
|
539
|
+
private readonly transferSteps: TransferStep[];
|
|
416
540
|
private readonly initialDataFn: () => State;
|
|
417
541
|
private readonly recoverFn: (version: DataVersionKey, data: unknown) => unknown;
|
|
418
542
|
private readonly recoverFromIndex: number;
|
|
@@ -420,6 +544,7 @@ export class DataModel<State> {
|
|
|
420
544
|
private constructor({
|
|
421
545
|
versionChain,
|
|
422
546
|
steps,
|
|
547
|
+
transferSteps = [],
|
|
423
548
|
initialDataFn,
|
|
424
549
|
recoverFn = defaultRecover,
|
|
425
550
|
recoverFromIndex,
|
|
@@ -430,6 +555,7 @@ export class DataModel<State> {
|
|
|
430
555
|
this.latestVersion = versionChain[versionChain.length - 1];
|
|
431
556
|
this.stepsByFromVersion = new Map(versionChain.map((v, i) => [v, i]));
|
|
432
557
|
this.steps = steps;
|
|
558
|
+
this.transferSteps = transferSteps;
|
|
433
559
|
this.initialDataFn = initialDataFn;
|
|
434
560
|
this.recoverFn = recoverFn;
|
|
435
561
|
this.recoverFromIndex = recoverFromIndex ?? steps.length;
|
|
@@ -440,8 +566,10 @@ export class DataModel<State> {
|
|
|
440
566
|
* Uses Symbol key to prevent external access.
|
|
441
567
|
* @internal
|
|
442
568
|
*/
|
|
443
|
-
static [FROM_BUILDER]<S
|
|
444
|
-
|
|
569
|
+
static [FROM_BUILDER]<S, T extends Record<string, unknown> = {}>(
|
|
570
|
+
state: BuilderState<S>,
|
|
571
|
+
): DataModel<S, T> {
|
|
572
|
+
return new DataModel<S, T>(state);
|
|
445
573
|
}
|
|
446
574
|
|
|
447
575
|
/**
|
|
@@ -463,7 +591,7 @@ export class DataModel<State> {
|
|
|
463
591
|
* Used when creating new blocks or resetting to defaults.
|
|
464
592
|
*/
|
|
465
593
|
getDefaultData(): DataVersioned<State> {
|
|
466
|
-
return
|
|
594
|
+
return makeVersionedData(this.latestVersion, this.initialDataFn());
|
|
467
595
|
}
|
|
468
596
|
|
|
469
597
|
private recoverFrom(data: unknown, version: DataVersionKey): DataVersioned<State> {
|
|
@@ -482,40 +610,67 @@ export class DataModel<State> {
|
|
|
482
610
|
|
|
483
611
|
/**
|
|
484
612
|
* Migrate versioned data from any version to the latest.
|
|
613
|
+
* Collects transfer extractions at their designated chain positions.
|
|
485
614
|
*
|
|
486
615
|
* - If version is in chain, applies needed migrations (O(1) lookup)
|
|
487
616
|
* - If version is unknown, attempts recovery; falls back to initial data
|
|
488
617
|
* - If a migration step fails, throws so the caller can preserve original data
|
|
489
618
|
*
|
|
619
|
+
* Transfers only fire during normal step-by-step migration:
|
|
620
|
+
* - Recovery path: returns empty transfers
|
|
621
|
+
* - Fast-path (already at latest): returns empty transfers
|
|
622
|
+
*
|
|
490
623
|
* @param versioned - Data with version tag
|
|
491
|
-
* @returns Migrated data at the latest version
|
|
624
|
+
* @returns Migrated data at the latest version with transfer record
|
|
492
625
|
* @throws If a migration step from a known version fails
|
|
493
626
|
*/
|
|
494
|
-
migrate(versioned: DataVersioned<unknown>): DataVersioned<State> {
|
|
627
|
+
migrate(versioned: DataVersioned<unknown>): DataVersioned<State> & { transfers: TransferRecord } {
|
|
495
628
|
const { version: fromVersion, data } = versioned;
|
|
496
629
|
|
|
630
|
+
// Fast path: already at latest version
|
|
497
631
|
if (fromVersion === this.latestVersion) {
|
|
498
|
-
return { version: this.latestVersion, data: data as State };
|
|
632
|
+
return { version: this.latestVersion, data: data as State, transfers: {} };
|
|
499
633
|
}
|
|
500
634
|
|
|
635
|
+
// Unknown version: recovery path — empty transfers
|
|
501
636
|
const startIndex = this.stepsByFromVersion.get(fromVersion);
|
|
502
637
|
if (startIndex === undefined) {
|
|
503
638
|
try {
|
|
504
|
-
return this.recoverFrom(data, fromVersion);
|
|
639
|
+
return { ...this.recoverFrom(data, fromVersion), transfers: {} };
|
|
505
640
|
} catch {
|
|
506
641
|
// Recovery failed (unknown version, recover fn threw, or post-recover
|
|
507
642
|
// migration failed) — reset to initial data rather than blocking the update.
|
|
508
|
-
return this.getDefaultData();
|
|
643
|
+
return { ...this.getDefaultData(), transfers: {} };
|
|
509
644
|
}
|
|
510
645
|
}
|
|
511
646
|
|
|
512
647
|
let currentData: unknown = data;
|
|
648
|
+
const transfers: TransferRecord = {};
|
|
513
649
|
|
|
650
|
+
// Run steps and check transfer entries before each step
|
|
514
651
|
for (let i = startIndex; i < this.steps.length; i++) {
|
|
515
|
-
const
|
|
516
|
-
|
|
652
|
+
for (const t of this.transferSteps) {
|
|
653
|
+
if (t.beforeStepIndex === i) {
|
|
654
|
+
transfers[t.pluginId] = {
|
|
655
|
+
version: t.targetVersion,
|
|
656
|
+
data: t.extract(currentData),
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
currentData = this.steps[i].migrate(currentData);
|
|
517
661
|
}
|
|
518
662
|
|
|
519
|
-
|
|
663
|
+
// Check for transfers positioned at or past the end of the steps array
|
|
664
|
+
// (e.g., .transfer() was the last call before .init(), after all .migrate() calls)
|
|
665
|
+
for (const t of this.transferSteps) {
|
|
666
|
+
if (t.beforeStepIndex >= this.steps.length && t.beforeStepIndex >= startIndex) {
|
|
667
|
+
transfers[t.pluginId] = {
|
|
668
|
+
version: t.targetVersion,
|
|
669
|
+
data: t.extract(currentData),
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return { version: this.latestVersion, data: currentData as State, transfers };
|
|
520
675
|
}
|
|
521
676
|
}
|