@platforma-sdk/model 1.51.9 → 1.52.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.
Files changed (82) hide show
  1. package/dist/bconfig/lambdas.d.ts +26 -4
  2. package/dist/bconfig/lambdas.d.ts.map +1 -1
  3. package/dist/bconfig/v3.d.ts +4 -2
  4. package/dist/bconfig/v3.d.ts.map +1 -1
  5. package/dist/block_api_v3.d.ts +32 -0
  6. package/dist/block_api_v3.d.ts.map +1 -0
  7. package/dist/block_migrations.cjs +138 -0
  8. package/dist/block_migrations.cjs.map +1 -0
  9. package/dist/block_migrations.d.ts +79 -0
  10. package/dist/block_migrations.d.ts.map +1 -0
  11. package/dist/block_migrations.js +136 -0
  12. package/dist/block_migrations.js.map +1 -0
  13. package/dist/block_model.cjs +222 -0
  14. package/dist/block_model.cjs.map +1 -0
  15. package/dist/block_model.d.ts +132 -0
  16. package/dist/block_model.d.ts.map +1 -0
  17. package/dist/block_model.js +220 -0
  18. package/dist/block_model.js.map +1 -0
  19. package/dist/block_storage.cjs +244 -0
  20. package/dist/block_storage.cjs.map +1 -0
  21. package/dist/block_storage.d.ts +208 -0
  22. package/dist/block_storage.d.ts.map +1 -0
  23. package/dist/block_storage.js +225 -0
  24. package/dist/block_storage.js.map +1 -0
  25. package/dist/block_storage_vm.cjs +264 -0
  26. package/dist/block_storage_vm.cjs.map +1 -0
  27. package/dist/block_storage_vm.d.ts +67 -0
  28. package/dist/block_storage_vm.d.ts.map +1 -0
  29. package/dist/block_storage_vm.js +260 -0
  30. package/dist/block_storage_vm.js.map +1 -0
  31. package/dist/builder.cjs +9 -6
  32. package/dist/builder.cjs.map +1 -1
  33. package/dist/builder.d.ts +15 -30
  34. package/dist/builder.d.ts.map +1 -1
  35. package/dist/builder.js +10 -7
  36. package/dist/builder.js.map +1 -1
  37. package/dist/components/PlDataTable.cjs.map +1 -1
  38. package/dist/components/PlDataTable.d.ts +2 -2
  39. package/dist/components/PlDataTable.d.ts.map +1 -1
  40. package/dist/components/PlDataTable.js.map +1 -1
  41. package/dist/index.cjs +25 -0
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +4 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/internal.cjs +38 -0
  48. package/dist/internal.cjs.map +1 -1
  49. package/dist/internal.d.ts +21 -0
  50. package/dist/internal.d.ts.map +1 -1
  51. package/dist/internal.js +36 -1
  52. package/dist/internal.js.map +1 -1
  53. package/dist/package.json.cjs +1 -1
  54. package/dist/package.json.js +1 -1
  55. package/dist/platforma.d.ts +18 -3
  56. package/dist/platforma.d.ts.map +1 -1
  57. package/dist/render/api.cjs +43 -16
  58. package/dist/render/api.cjs.map +1 -1
  59. package/dist/render/api.d.ts +19 -7
  60. package/dist/render/api.d.ts.map +1 -1
  61. package/dist/render/api.js +42 -17
  62. package/dist/render/api.js.map +1 -1
  63. package/dist/render/internal.cjs.map +1 -1
  64. package/dist/render/internal.d.ts +3 -1
  65. package/dist/render/internal.d.ts.map +1 -1
  66. package/dist/render/internal.js.map +1 -1
  67. package/package.json +7 -7
  68. package/src/bconfig/lambdas.ts +35 -4
  69. package/src/bconfig/v3.ts +12 -2
  70. package/src/block_api_v3.ts +49 -0
  71. package/src/block_migrations.ts +173 -0
  72. package/src/block_model.ts +440 -0
  73. package/src/block_storage.test.ts +258 -0
  74. package/src/block_storage.ts +365 -0
  75. package/src/block_storage_vm.ts +349 -0
  76. package/src/builder.ts +24 -59
  77. package/src/components/PlDataTable.ts +2 -1
  78. package/src/index.ts +3 -0
  79. package/src/internal.ts +51 -0
  80. package/src/platforma.ts +31 -5
  81. package/src/render/api.ts +52 -21
  82. package/src/render/internal.ts +3 -1
@@ -1,10 +1,14 @@
1
1
  import type { ConfigResult, PlResourceEntry, TypedConfig } from '../config';
2
- export type StdCtxArgsOnly<Args, UiState = undefined> = {
2
+ import type { OutputWithStatus } from '@milaboratories/pl-model-common';
3
+ import type { TypedConfigOrConfigLambda } from './types';
4
+ export type StdCtxArgsOnly<Args, Data = undefined> = {
3
5
  readonly $blockId: string;
4
6
  readonly $args: Args;
5
- readonly $ui: UiState;
7
+ /** @deprecated Use $data instead. Kept for V1/V2 block compatibility. */
8
+ readonly $ui: Data;
9
+ readonly $data: Data;
6
10
  };
7
- export type StdCtx<Args, UiState = undefined> = StdCtxArgsOnly<Args, UiState> & {
11
+ export type StdCtx<Args, Data = undefined> = StdCtxArgsOnly<Args, Data> & {
8
12
  readonly $prod: PlResourceEntry;
9
13
  readonly $staging: PlResourceEntry;
10
14
  };
@@ -13,7 +17,7 @@ export type ResolveCfgType<Cfg extends TypedConfig, Args, UiState = undefined> =
13
17
  export type ConfigRenderLambdaFlags = {
14
18
  /**
15
19
  * Tells the system that corresponding computable should be created with StableOnlyRetentive rendering mode.
16
- * This flag can be overriden by the system.
20
+ * This flag can be overridden by the system.
17
21
  * */
18
22
  retentive?: boolean;
19
23
  /**
@@ -37,4 +41,22 @@ export interface ConfigRenderLambda<Return = unknown> extends ConfigRenderLambda
37
41
  handle: string;
38
42
  }
39
43
  export type ExtractFunctionHandleReturn<Func extends ConfigRenderLambda> = Func extends ConfigRenderLambda<infer Return> ? Return : never;
44
+ /** Infers the output type from a TypedConfig or ConfigRenderLambda */
45
+ export type InferOutputType<CfgOrFH, Args, UiState> = CfgOrFH extends TypedConfig ? ResolveCfgType<CfgOrFH, Args, UiState> : CfgOrFH extends ConfigRenderLambda ? ExtractFunctionHandleReturn<CfgOrFH> : never;
46
+ /** Maps outputs configuration to inferred output types with status wrapper */
47
+ export type InferOutputsFromConfigs<Args, OutputsCfg extends Record<string, TypedConfigOrConfigLambda>, UiState> = {
48
+ [Key in keyof OutputsCfg]: OutputWithStatus<InferOutputType<OutputsCfg[Key], Args, UiState>> & {
49
+ __unwrap: (OutputsCfg[Key] extends {
50
+ withStatus: true;
51
+ } ? false : true);
52
+ };
53
+ };
54
+ /** Maps lambda-only outputs configuration to inferred output types (for V3 blocks) */
55
+ export type InferOutputsFromLambdas<OutputsCfg extends Record<string, ConfigRenderLambda>> = {
56
+ [Key in keyof OutputsCfg]: OutputWithStatus<ExtractFunctionHandleReturn<OutputsCfg[Key]>> & {
57
+ __unwrap: (OutputsCfg[Key] extends {
58
+ withStatus: true;
59
+ } ? false : true);
60
+ };
61
+ };
40
62
  //# sourceMappingURL=lambdas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lambdas.d.ts","sourceRoot":"","sources":["../../src/bconfig/lambdas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE5E,MAAM,MAAM,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,IAAI;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,IAAI,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG;IAC9E,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,cAAc,CAAC,GAAG,SAAS,WAAW,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,IAAI,YAAY,CAC3F,GAAG,EACH,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CACtB,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;SAGK;IACL,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;SAGK;IACL,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,+BAA+B;AAC/B,MAAM,WAAW,kBAAkB,CAAC,MAAM,GAAG,OAAO,CAAE,SAAQ,uBAAuB;IACnF,kBAAkB;IAClB,cAAc,EAAE,IAAI,CAAC;IAErB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,2BAA2B,CAAC,IAAI,SAAS,kBAAkB,IACrE,IAAI,SAAS,kBAAkB,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC"}
1
+ {"version":3,"file":"lambdas.d.ts","sourceRoot":"","sources":["../../src/bconfig/lambdas.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
- import type { BlockConfigV3Generic } from '@milaboratories/pl-model-common';
1
+ import type { BlockConfigV3Generic, BlockConfigV4Generic } from '@milaboratories/pl-model-common';
2
2
  import type { TypedConfigOrConfigLambda } from './types';
3
3
  import type { ConfigRenderLambda } from './lambdas';
4
4
  export type BlockConfigV3<Args = unknown, UiState = unknown, Outputs extends Record<string, TypedConfigOrConfigLambda> = Record<string, TypedConfigOrConfigLambda>> = BlockConfigV3Generic<Args, UiState, TypedConfigOrConfigLambda, ConfigRenderLambda, Outputs>;
5
- export type BlockConfig = BlockConfigV3;
5
+ export type BlockConfigV4<Args = unknown, Data extends Record<string, unknown> = Record<string, unknown>, Outputs extends Record<string, TypedConfigOrConfigLambda> = Record<string, TypedConfigOrConfigLambda>> = BlockConfigV4Generic<Args, Data, TypedConfigOrConfigLambda, ConfigRenderLambda, Outputs>;
6
+ /** Union of all block config versions with discriminator for type narrowing */
7
+ export type BlockConfig = BlockConfigV3 | BlockConfigV4;
6
8
  //# sourceMappingURL=v3.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v3.d.ts","sourceRoot":"","sources":["../../src/bconfig/v3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,MAAM,aAAa,CACvB,IAAI,GAAG,OAAO,EACd,OAAO,GAAG,OAAO,EACjB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,MAAM,CAChE,MAAM,EACN,yBAAyB,CAC1B,IACC,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;AAEhG,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC"}
1
+ {"version":3,"file":"v3.d.ts","sourceRoot":"","sources":["../../src/bconfig/v3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAClG,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,MAAM,aAAa,CACvB,IAAI,GAAG,OAAO,EACd,OAAO,GAAG,OAAO,EACjB,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,MAAM,CAChE,MAAM,EACN,yBAAyB,CAC1B,IACC,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;AAEhG,MAAM,MAAM,aAAa,CACvB,IAAI,GAAG,OAAO,EACd,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,MAAM,CAChE,MAAM,EACN,yBAAyB,CAC1B,IACC,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;AAE7F,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,aAAa,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { BlockOutputsBase, NavigationState, ValueWithUTag, ValueWithUTagAndAuthor, AuthorMarker, ResultOrError, BlockStateV3 } from '@milaboratories/pl-model-common';
2
+ import type { Operation } from 'fast-json-patch';
3
+ import type { MutateStoragePayload } from './block_storage';
4
+ /** Defines methods to read and write current block data. */
5
+ export interface BlockApiV3<_Args = unknown, Outputs extends BlockOutputsBase = BlockOutputsBase, _Data = unknown, Href extends `/${string}` = `/${string}`> {
6
+ /**
7
+ * Use this method to retrieve block state during UI initialization. Then use
8
+ * {@link onStateUpdates} method to subscribe for updates.
9
+ * */
10
+ loadBlockState(): Promise<ResultOrError<ValueWithUTag<BlockStateV3<Outputs, _Data, Href>>>>;
11
+ /**
12
+ * Get all json patches (rfc6902) that were applied to the block state.
13
+ * */
14
+ getPatches(uTag: string): Promise<ResultOrError<ValueWithUTagAndAuthor<Operation[]>>>;
15
+ /**
16
+ * Mutates block storage with the given operation.
17
+ *
18
+ * This method returns when the data is safely saved so in case the window is
19
+ * closed there will be no information losses. This function under the hood
20
+ * may delay actual persistence of the supplied values.
21
+ * */
22
+ mutateStorage(payload: MutateStoragePayload, author?: AuthorMarker): Promise<ResultOrError<void>>;
23
+ /**
24
+ * Sets block navigation state.
25
+ * */
26
+ setNavigationState(state: NavigationState<Href>): Promise<ResultOrError<void>>;
27
+ /**
28
+ * Disposes the block API.
29
+ * */
30
+ dispose(): Promise<ResultOrError<void>>;
31
+ }
32
+ //# sourceMappingURL=block_api_v3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block_api_v3.d.ts","sourceRoot":"","sources":["../src/block_api_v3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,YAAY,EACZ,aAAa,EACb,YAAY,EACb,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE5D,4DAA4D;AAC5D,MAAM,WAAW,UAAU,CACzB,KAAK,GAAG,OAAO,EACf,OAAO,SAAS,gBAAgB,GAAG,gBAAgB,EACnD,KAAK,GAAG,OAAO,EACf,IAAI,SAAS,IAAI,MAAM,EAAE,GAAG,IAAI,MAAM,EAAE;IAExC;;;SAGK;IACL,cAAc,IAAI,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5F;;SAEK;IACL,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,sBAAsB,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IAEtF;;;;;;SAMK;IACL,aAAa,CAAC,OAAO,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IAElG;;SAEK;IACL,kBAAkB,CAAC,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IAE/E;;SAEK;IACL,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;CACzC"}
@@ -0,0 +1,138 @@
1
+ 'use strict';
2
+
3
+ var internal = require('./internal.cjs');
4
+ var block_storage = require('./block_storage.cjs');
5
+
6
+ /** Internal builder for chaining migrations */
7
+ class DataModelBuilder {
8
+ migrationSteps;
9
+ constructor(steps = []) {
10
+ this.migrationSteps = steps;
11
+ }
12
+ /** Start a migration chain from an initial type */
13
+ static from() {
14
+ return new DataModelBuilder();
15
+ }
16
+ /** Add a migration step */
17
+ migrate(fn) {
18
+ return new DataModelBuilder([...this.migrationSteps, fn]);
19
+ }
20
+ /** Finalize with initial data, creating the DataModel */
21
+ create(initialData, ..._) {
22
+ return DataModel._fromBuilder(this.migrationSteps, initialData);
23
+ }
24
+ }
25
+ /**
26
+ * DataModel defines the block's data structure, initial values, and migrations.
27
+ * Used by BlockModelV3 to manage data state.
28
+ *
29
+ * @example
30
+ * // Simple data model (no migrations)
31
+ * const dataModel = DataModel.create<BlockData>(() => ({
32
+ * numbers: [],
33
+ * labels: [],
34
+ * }));
35
+ *
36
+ * // Data model with migrations
37
+ * const dataModel = DataModel
38
+ * .from<V1>()
39
+ * .migrate((data) => ({ ...data, labels: [] })) // v1 → v2
40
+ * .migrate((data) => ({ ...data, description: '' })) // v2 → v3
41
+ * .create<BlockData>(() => ({ numbers: [], labels: [], description: '' }));
42
+ */
43
+ class DataModel {
44
+ steps;
45
+ _initialData;
46
+ constructor(steps, initialData) {
47
+ this.steps = steps;
48
+ this._initialData = initialData;
49
+ }
50
+ /** Start a migration chain from an initial type */
51
+ static from() {
52
+ return DataModelBuilder.from();
53
+ }
54
+ /** Create a data model with just initial data (no migrations) */
55
+ static create(initialData) {
56
+ return new DataModel([], initialData);
57
+ }
58
+ /** Create from builder (internal use) */
59
+ static _fromBuilder(steps, initialData) {
60
+ return new DataModel(steps, initialData);
61
+ }
62
+ /**
63
+ * Latest version number.
64
+ * Version 1 = initial state, each migration adds 1.
65
+ */
66
+ get version() {
67
+ return this.steps.length + 1;
68
+ }
69
+ /** Number of migration steps */
70
+ get migrationCount() {
71
+ return this.steps.length;
72
+ }
73
+ /** Get initial data */
74
+ initialData() {
75
+ return this._initialData();
76
+ }
77
+ /** Get default data wrapped with current version */
78
+ getDefaultData() {
79
+ return { version: this.version, data: this._initialData() };
80
+ }
81
+ /**
82
+ * Upgrade versioned data from any version to the latest.
83
+ * Applies only the migrations needed (skips already-applied ones).
84
+ * If a migration fails, returns default data with a warning.
85
+ */
86
+ upgrade(versioned) {
87
+ const { version: fromVersion, data } = versioned;
88
+ if (fromVersion > this.version) {
89
+ throw new Error(`Cannot downgrade from version ${fromVersion} to ${this.version}`);
90
+ }
91
+ if (fromVersion === this.version) {
92
+ return { version: this.version, data: data };
93
+ }
94
+ // Apply migrations starting from (fromVersion - 1) index
95
+ // Version 1 -> no migrations applied yet -> start at index 0
96
+ // Version 2 -> migration[0] already applied -> start at index 1
97
+ const startIndex = fromVersion - 1;
98
+ const migrationsToApply = this.steps.slice(startIndex);
99
+ let currentData = data;
100
+ for (let i = 0; i < migrationsToApply.length; i++) {
101
+ const stepIndex = startIndex + i;
102
+ const fromVer = stepIndex + 1;
103
+ const toVer = stepIndex + 2;
104
+ try {
105
+ currentData = migrationsToApply[i](currentData);
106
+ }
107
+ catch (error) {
108
+ const errorMessage = error instanceof Error ? error.message : String(error);
109
+ return {
110
+ ...this.getDefaultData(),
111
+ warning: `Migration v${fromVer}→v${toVer} failed: ${errorMessage}`,
112
+ };
113
+ }
114
+ }
115
+ return { version: this.version, data: currentData };
116
+ }
117
+ /**
118
+ * Register callbacks for use in the VM.
119
+ * Called by BlockModelV3.create() to set up internal callbacks.
120
+ *
121
+ * All callbacks are prefixed with `__pl_` to indicate internal SDK use:
122
+ * - `__pl_data_initial`: returns initial data for new blocks
123
+ * - `__pl_data_upgrade`: upgrades versioned data from any version to latest
124
+ * - `__pl_storage_initial`: returns initial BlockStorage as JSON string
125
+ */
126
+ registerCallbacks() {
127
+ internal.tryRegisterCallback('__pl_data_initial', () => this._initialData());
128
+ internal.tryRegisterCallback('__pl_data_upgrade', (versioned) => this.upgrade(versioned));
129
+ internal.tryRegisterCallback('__pl_storage_initial', () => {
130
+ const { version, data } = this.getDefaultData();
131
+ const storage = block_storage.createBlockStorage(data, version);
132
+ return JSON.stringify(storage);
133
+ });
134
+ }
135
+ }
136
+
137
+ exports.DataModel = DataModel;
138
+ //# sourceMappingURL=block_migrations.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block_migrations.cjs","sources":["../src/block_migrations.ts"],"sourcesContent":["import { tryRegisterCallback } from './internal';\nimport { createBlockStorage } from './block_storage';\n\nexport type MigrationFn<From, To> = (prev: Readonly<From>) => To;\n\n/** Versioned data wrapper for persistence */\nexport type Versioned<T> = {\n version: number;\n data: T;\n};\n\n/** Result of upgrade operation, may include warning if migration failed */\nexport type UpgradeResult<T> = Versioned<T> & {\n warning?: string;\n};\n\n/** Internal builder for chaining migrations */\nclass DataModelBuilder<State> {\n private readonly migrationSteps: Array<(x: unknown) => unknown>;\n\n private constructor(steps: Array<(x: unknown) => unknown> = []) {\n this.migrationSteps = steps;\n }\n\n /** Start a migration chain from an initial type */\n static from<T = unknown>(): DataModelBuilder<T> {\n return new DataModelBuilder<T>();\n }\n\n /** Add a migration step */\n migrate<Next>(fn: MigrationFn<State, Next>): DataModelBuilder<Next> {\n return new DataModelBuilder<Next>([...this.migrationSteps, fn as any]);\n }\n\n /** Finalize with initial data, creating the DataModel */\n create<S>(\n initialData: () => S,\n ..._: [State] extends [S] ? [] : [never]\n ): DataModel<S> {\n return DataModel._fromBuilder<S>(this.migrationSteps, initialData);\n }\n}\n\n/**\n * DataModel defines the block's data structure, initial values, and migrations.\n * Used by BlockModelV3 to manage data state.\n *\n * @example\n * // Simple data model (no migrations)\n * const dataModel = DataModel.create<BlockData>(() => ({\n * numbers: [],\n * labels: [],\n * }));\n *\n * // Data model with migrations\n * const dataModel = DataModel\n * .from<V1>()\n * .migrate((data) => ({ ...data, labels: [] })) // v1 → v2\n * .migrate((data) => ({ ...data, description: '' })) // v2 → v3\n * .create<BlockData>(() => ({ numbers: [], labels: [], description: '' }));\n */\nexport class DataModel<State> {\n private readonly steps: Array<(x: unknown) => unknown>;\n private readonly _initialData: () => State;\n\n private constructor(steps: Array<(x: unknown) => unknown>, initialData: () => State) {\n this.steps = steps;\n this._initialData = initialData;\n }\n\n /** Start a migration chain from an initial type */\n static from<S>(): DataModelBuilder<S> {\n return DataModelBuilder.from<S>();\n }\n\n /** Create a data model with just initial data (no migrations) */\n static create<S>(initialData: () => S): DataModel<S> {\n return new DataModel<S>([], initialData);\n }\n\n /** Create from builder (internal use) */\n static _fromBuilder<S>(\n steps: Array<(x: unknown) => unknown>,\n initialData: () => S,\n ): DataModel<S> {\n return new DataModel<S>(steps, initialData);\n }\n\n /**\n * Latest version number.\n * Version 1 = initial state, each migration adds 1.\n */\n get version(): number {\n return this.steps.length + 1;\n }\n\n /** Number of migration steps */\n get migrationCount(): number {\n return this.steps.length;\n }\n\n /** Get initial data */\n initialData(): State {\n return this._initialData();\n }\n\n /** Get default data wrapped with current version */\n getDefaultData(): Versioned<State> {\n return { version: this.version, data: this._initialData() };\n }\n\n /**\n * Upgrade versioned data from any version to the latest.\n * Applies only the migrations needed (skips already-applied ones).\n * If a migration fails, returns default data with a warning.\n */\n upgrade(versioned: Versioned<unknown>): UpgradeResult<State> {\n const { version: fromVersion, data } = versioned;\n\n if (fromVersion > this.version) {\n throw new Error(\n `Cannot downgrade from version ${fromVersion} to ${this.version}`,\n );\n }\n\n if (fromVersion === this.version) {\n return { version: this.version, data: data as State };\n }\n\n // Apply migrations starting from (fromVersion - 1) index\n // Version 1 -> no migrations applied yet -> start at index 0\n // Version 2 -> migration[0] already applied -> start at index 1\n const startIndex = fromVersion - 1;\n const migrationsToApply = this.steps.slice(startIndex);\n\n let currentData: unknown = data;\n for (let i = 0; i < migrationsToApply.length; i++) {\n const stepIndex = startIndex + i;\n const fromVer = stepIndex + 1;\n const toVer = stepIndex + 2;\n try {\n currentData = migrationsToApply[i](currentData);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n ...this.getDefaultData(),\n warning: `Migration v${fromVer}→v${toVer} failed: ${errorMessage}`,\n };\n }\n }\n\n return { version: this.version, data: currentData as State };\n }\n\n /**\n * Register callbacks for use in the VM.\n * Called by BlockModelV3.create() to set up internal callbacks.\n *\n * All callbacks are prefixed with `__pl_` to indicate internal SDK use:\n * - `__pl_data_initial`: returns initial data for new blocks\n * - `__pl_data_upgrade`: upgrades versioned data from any version to latest\n * - `__pl_storage_initial`: returns initial BlockStorage as JSON string\n */\n registerCallbacks(): void {\n tryRegisterCallback('__pl_data_initial', () => this._initialData());\n tryRegisterCallback('__pl_data_upgrade', (versioned: Versioned<unknown>) => this.upgrade(versioned));\n tryRegisterCallback('__pl_storage_initial', () => {\n const { version, data } = this.getDefaultData();\n const storage = createBlockStorage(data, version);\n return JSON.stringify(storage);\n });\n }\n}\n"],"names":["tryRegisterCallback","createBlockStorage"],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ export type MigrationFn<From, To> = (prev: Readonly<From>) => To;
2
+ /** Versioned data wrapper for persistence */
3
+ export type Versioned<T> = {
4
+ version: number;
5
+ data: T;
6
+ };
7
+ /** Result of upgrade operation, may include warning if migration failed */
8
+ export type UpgradeResult<T> = Versioned<T> & {
9
+ warning?: string;
10
+ };
11
+ /** Internal builder for chaining migrations */
12
+ declare class DataModelBuilder<State> {
13
+ private readonly migrationSteps;
14
+ private constructor();
15
+ /** Start a migration chain from an initial type */
16
+ static from<T = unknown>(): DataModelBuilder<T>;
17
+ /** Add a migration step */
18
+ migrate<Next>(fn: MigrationFn<State, Next>): DataModelBuilder<Next>;
19
+ /** Finalize with initial data, creating the DataModel */
20
+ create<S>(initialData: () => S, ..._: [State] extends [S] ? [] : [never]): DataModel<S>;
21
+ }
22
+ /**
23
+ * DataModel defines the block's data structure, initial values, and migrations.
24
+ * Used by BlockModelV3 to manage data state.
25
+ *
26
+ * @example
27
+ * // Simple data model (no migrations)
28
+ * const dataModel = DataModel.create<BlockData>(() => ({
29
+ * numbers: [],
30
+ * labels: [],
31
+ * }));
32
+ *
33
+ * // Data model with migrations
34
+ * const dataModel = DataModel
35
+ * .from<V1>()
36
+ * .migrate((data) => ({ ...data, labels: [] })) // v1 → v2
37
+ * .migrate((data) => ({ ...data, description: '' })) // v2 → v3
38
+ * .create<BlockData>(() => ({ numbers: [], labels: [], description: '' }));
39
+ */
40
+ export declare class DataModel<State> {
41
+ private readonly steps;
42
+ private readonly _initialData;
43
+ private constructor();
44
+ /** Start a migration chain from an initial type */
45
+ static from<S>(): DataModelBuilder<S>;
46
+ /** Create a data model with just initial data (no migrations) */
47
+ static create<S>(initialData: () => S): DataModel<S>;
48
+ /** Create from builder (internal use) */
49
+ static _fromBuilder<S>(steps: Array<(x: unknown) => unknown>, initialData: () => S): DataModel<S>;
50
+ /**
51
+ * Latest version number.
52
+ * Version 1 = initial state, each migration adds 1.
53
+ */
54
+ get version(): number;
55
+ /** Number of migration steps */
56
+ get migrationCount(): number;
57
+ /** Get initial data */
58
+ initialData(): State;
59
+ /** Get default data wrapped with current version */
60
+ getDefaultData(): Versioned<State>;
61
+ /**
62
+ * Upgrade versioned data from any version to the latest.
63
+ * Applies only the migrations needed (skips already-applied ones).
64
+ * If a migration fails, returns default data with a warning.
65
+ */
66
+ upgrade(versioned: Versioned<unknown>): UpgradeResult<State>;
67
+ /**
68
+ * Register callbacks for use in the VM.
69
+ * Called by BlockModelV3.create() to set up internal callbacks.
70
+ *
71
+ * All callbacks are prefixed with `__pl_` to indicate internal SDK use:
72
+ * - `__pl_data_initial`: returns initial data for new blocks
73
+ * - `__pl_data_upgrade`: upgrades versioned data from any version to latest
74
+ * - `__pl_storage_initial`: returns initial BlockStorage as JSON string
75
+ */
76
+ registerCallbacks(): void;
77
+ }
78
+ export {};
79
+ //# sourceMappingURL=block_migrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block_migrations.d.ts","sourceRoot":"","sources":["../src/block_migrations.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;AAEjE,6CAA6C;AAC7C,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,CAAC,CAAC;CACT,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,GAAG;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,+CAA+C;AAC/C,cAAM,gBAAgB,CAAC,KAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiC;IAEhE,OAAO;IAIP,mDAAmD;IACnD,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,OAAO,KAAK,gBAAgB,CAAC,CAAC,CAAC;IAI/C,2BAA2B;IAC3B,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC;IAInE,yDAAyD;IACzD,MAAM,CAAC,CAAC,EACN,WAAW,EAAE,MAAM,CAAC,EACpB,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,GACvC,SAAS,CAAC,CAAC,CAAC;CAGhB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SAAS,CAAC,KAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAE3C,OAAO;IAKP,mDAAmD;IACnD,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,gBAAgB,CAAC,CAAC,CAAC;IAIrC,iEAAiE;IACjE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAIpD,yCAAyC;IACzC,MAAM,CAAC,YAAY,CAAC,CAAC,EACnB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,EACrC,WAAW,EAAE,MAAM,CAAC,GACnB,SAAS,CAAC,CAAC,CAAC;IAIf;;;OAGG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,gCAAgC;IAChC,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,uBAAuB;IACvB,WAAW,IAAI,KAAK;IAIpB,oDAAoD;IACpD,cAAc,IAAI,SAAS,CAAC,KAAK,CAAC;IAIlC;;;;OAIG;IACH,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC;IAsC5D;;;;;;;;OAQG;IACH,iBAAiB,IAAI,IAAI;CAS1B"}
@@ -0,0 +1,136 @@
1
+ import { tryRegisterCallback } from './internal.js';
2
+ import { createBlockStorage } from './block_storage.js';
3
+
4
+ /** Internal builder for chaining migrations */
5
+ class DataModelBuilder {
6
+ migrationSteps;
7
+ constructor(steps = []) {
8
+ this.migrationSteps = steps;
9
+ }
10
+ /** Start a migration chain from an initial type */
11
+ static from() {
12
+ return new DataModelBuilder();
13
+ }
14
+ /** Add a migration step */
15
+ migrate(fn) {
16
+ return new DataModelBuilder([...this.migrationSteps, fn]);
17
+ }
18
+ /** Finalize with initial data, creating the DataModel */
19
+ create(initialData, ..._) {
20
+ return DataModel._fromBuilder(this.migrationSteps, initialData);
21
+ }
22
+ }
23
+ /**
24
+ * DataModel defines the block's data structure, initial values, and migrations.
25
+ * Used by BlockModelV3 to manage data state.
26
+ *
27
+ * @example
28
+ * // Simple data model (no migrations)
29
+ * const dataModel = DataModel.create<BlockData>(() => ({
30
+ * numbers: [],
31
+ * labels: [],
32
+ * }));
33
+ *
34
+ * // Data model with migrations
35
+ * const dataModel = DataModel
36
+ * .from<V1>()
37
+ * .migrate((data) => ({ ...data, labels: [] })) // v1 → v2
38
+ * .migrate((data) => ({ ...data, description: '' })) // v2 → v3
39
+ * .create<BlockData>(() => ({ numbers: [], labels: [], description: '' }));
40
+ */
41
+ class DataModel {
42
+ steps;
43
+ _initialData;
44
+ constructor(steps, initialData) {
45
+ this.steps = steps;
46
+ this._initialData = initialData;
47
+ }
48
+ /** Start a migration chain from an initial type */
49
+ static from() {
50
+ return DataModelBuilder.from();
51
+ }
52
+ /** Create a data model with just initial data (no migrations) */
53
+ static create(initialData) {
54
+ return new DataModel([], initialData);
55
+ }
56
+ /** Create from builder (internal use) */
57
+ static _fromBuilder(steps, initialData) {
58
+ return new DataModel(steps, initialData);
59
+ }
60
+ /**
61
+ * Latest version number.
62
+ * Version 1 = initial state, each migration adds 1.
63
+ */
64
+ get version() {
65
+ return this.steps.length + 1;
66
+ }
67
+ /** Number of migration steps */
68
+ get migrationCount() {
69
+ return this.steps.length;
70
+ }
71
+ /** Get initial data */
72
+ initialData() {
73
+ return this._initialData();
74
+ }
75
+ /** Get default data wrapped with current version */
76
+ getDefaultData() {
77
+ return { version: this.version, data: this._initialData() };
78
+ }
79
+ /**
80
+ * Upgrade versioned data from any version to the latest.
81
+ * Applies only the migrations needed (skips already-applied ones).
82
+ * If a migration fails, returns default data with a warning.
83
+ */
84
+ upgrade(versioned) {
85
+ const { version: fromVersion, data } = versioned;
86
+ if (fromVersion > this.version) {
87
+ throw new Error(`Cannot downgrade from version ${fromVersion} to ${this.version}`);
88
+ }
89
+ if (fromVersion === this.version) {
90
+ return { version: this.version, data: data };
91
+ }
92
+ // Apply migrations starting from (fromVersion - 1) index
93
+ // Version 1 -> no migrations applied yet -> start at index 0
94
+ // Version 2 -> migration[0] already applied -> start at index 1
95
+ const startIndex = fromVersion - 1;
96
+ const migrationsToApply = this.steps.slice(startIndex);
97
+ let currentData = data;
98
+ for (let i = 0; i < migrationsToApply.length; i++) {
99
+ const stepIndex = startIndex + i;
100
+ const fromVer = stepIndex + 1;
101
+ const toVer = stepIndex + 2;
102
+ try {
103
+ currentData = migrationsToApply[i](currentData);
104
+ }
105
+ catch (error) {
106
+ const errorMessage = error instanceof Error ? error.message : String(error);
107
+ return {
108
+ ...this.getDefaultData(),
109
+ warning: `Migration v${fromVer}→v${toVer} failed: ${errorMessage}`,
110
+ };
111
+ }
112
+ }
113
+ return { version: this.version, data: currentData };
114
+ }
115
+ /**
116
+ * Register callbacks for use in the VM.
117
+ * Called by BlockModelV3.create() to set up internal callbacks.
118
+ *
119
+ * All callbacks are prefixed with `__pl_` to indicate internal SDK use:
120
+ * - `__pl_data_initial`: returns initial data for new blocks
121
+ * - `__pl_data_upgrade`: upgrades versioned data from any version to latest
122
+ * - `__pl_storage_initial`: returns initial BlockStorage as JSON string
123
+ */
124
+ registerCallbacks() {
125
+ tryRegisterCallback('__pl_data_initial', () => this._initialData());
126
+ tryRegisterCallback('__pl_data_upgrade', (versioned) => this.upgrade(versioned));
127
+ tryRegisterCallback('__pl_storage_initial', () => {
128
+ const { version, data } = this.getDefaultData();
129
+ const storage = createBlockStorage(data, version);
130
+ return JSON.stringify(storage);
131
+ });
132
+ }
133
+ }
134
+
135
+ export { DataModel };
136
+ //# sourceMappingURL=block_migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block_migrations.js","sources":["../src/block_migrations.ts"],"sourcesContent":["import { tryRegisterCallback } from './internal';\nimport { createBlockStorage } from './block_storage';\n\nexport type MigrationFn<From, To> = (prev: Readonly<From>) => To;\n\n/** Versioned data wrapper for persistence */\nexport type Versioned<T> = {\n version: number;\n data: T;\n};\n\n/** Result of upgrade operation, may include warning if migration failed */\nexport type UpgradeResult<T> = Versioned<T> & {\n warning?: string;\n};\n\n/** Internal builder for chaining migrations */\nclass DataModelBuilder<State> {\n private readonly migrationSteps: Array<(x: unknown) => unknown>;\n\n private constructor(steps: Array<(x: unknown) => unknown> = []) {\n this.migrationSteps = steps;\n }\n\n /** Start a migration chain from an initial type */\n static from<T = unknown>(): DataModelBuilder<T> {\n return new DataModelBuilder<T>();\n }\n\n /** Add a migration step */\n migrate<Next>(fn: MigrationFn<State, Next>): DataModelBuilder<Next> {\n return new DataModelBuilder<Next>([...this.migrationSteps, fn as any]);\n }\n\n /** Finalize with initial data, creating the DataModel */\n create<S>(\n initialData: () => S,\n ..._: [State] extends [S] ? [] : [never]\n ): DataModel<S> {\n return DataModel._fromBuilder<S>(this.migrationSteps, initialData);\n }\n}\n\n/**\n * DataModel defines the block's data structure, initial values, and migrations.\n * Used by BlockModelV3 to manage data state.\n *\n * @example\n * // Simple data model (no migrations)\n * const dataModel = DataModel.create<BlockData>(() => ({\n * numbers: [],\n * labels: [],\n * }));\n *\n * // Data model with migrations\n * const dataModel = DataModel\n * .from<V1>()\n * .migrate((data) => ({ ...data, labels: [] })) // v1 → v2\n * .migrate((data) => ({ ...data, description: '' })) // v2 → v3\n * .create<BlockData>(() => ({ numbers: [], labels: [], description: '' }));\n */\nexport class DataModel<State> {\n private readonly steps: Array<(x: unknown) => unknown>;\n private readonly _initialData: () => State;\n\n private constructor(steps: Array<(x: unknown) => unknown>, initialData: () => State) {\n this.steps = steps;\n this._initialData = initialData;\n }\n\n /** Start a migration chain from an initial type */\n static from<S>(): DataModelBuilder<S> {\n return DataModelBuilder.from<S>();\n }\n\n /** Create a data model with just initial data (no migrations) */\n static create<S>(initialData: () => S): DataModel<S> {\n return new DataModel<S>([], initialData);\n }\n\n /** Create from builder (internal use) */\n static _fromBuilder<S>(\n steps: Array<(x: unknown) => unknown>,\n initialData: () => S,\n ): DataModel<S> {\n return new DataModel<S>(steps, initialData);\n }\n\n /**\n * Latest version number.\n * Version 1 = initial state, each migration adds 1.\n */\n get version(): number {\n return this.steps.length + 1;\n }\n\n /** Number of migration steps */\n get migrationCount(): number {\n return this.steps.length;\n }\n\n /** Get initial data */\n initialData(): State {\n return this._initialData();\n }\n\n /** Get default data wrapped with current version */\n getDefaultData(): Versioned<State> {\n return { version: this.version, data: this._initialData() };\n }\n\n /**\n * Upgrade versioned data from any version to the latest.\n * Applies only the migrations needed (skips already-applied ones).\n * If a migration fails, returns default data with a warning.\n */\n upgrade(versioned: Versioned<unknown>): UpgradeResult<State> {\n const { version: fromVersion, data } = versioned;\n\n if (fromVersion > this.version) {\n throw new Error(\n `Cannot downgrade from version ${fromVersion} to ${this.version}`,\n );\n }\n\n if (fromVersion === this.version) {\n return { version: this.version, data: data as State };\n }\n\n // Apply migrations starting from (fromVersion - 1) index\n // Version 1 -> no migrations applied yet -> start at index 0\n // Version 2 -> migration[0] already applied -> start at index 1\n const startIndex = fromVersion - 1;\n const migrationsToApply = this.steps.slice(startIndex);\n\n let currentData: unknown = data;\n for (let i = 0; i < migrationsToApply.length; i++) {\n const stepIndex = startIndex + i;\n const fromVer = stepIndex + 1;\n const toVer = stepIndex + 2;\n try {\n currentData = migrationsToApply[i](currentData);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n ...this.getDefaultData(),\n warning: `Migration v${fromVer}→v${toVer} failed: ${errorMessage}`,\n };\n }\n }\n\n return { version: this.version, data: currentData as State };\n }\n\n /**\n * Register callbacks for use in the VM.\n * Called by BlockModelV3.create() to set up internal callbacks.\n *\n * All callbacks are prefixed with `__pl_` to indicate internal SDK use:\n * - `__pl_data_initial`: returns initial data for new blocks\n * - `__pl_data_upgrade`: upgrades versioned data from any version to latest\n * - `__pl_storage_initial`: returns initial BlockStorage as JSON string\n */\n registerCallbacks(): void {\n tryRegisterCallback('__pl_data_initial', () => this._initialData());\n tryRegisterCallback('__pl_data_upgrade', (versioned: Versioned<unknown>) => this.upgrade(versioned));\n tryRegisterCallback('__pl_storage_initial', () => {\n const { version, data } = this.getDefaultData();\n const storage = createBlockStorage(data, version);\n return JSON.stringify(storage);\n });\n }\n}\n"],"names":[],"mappings":"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"}