@platforma-sdk/model 1.53.1 → 1.53.3

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.
@@ -6,7 +6,12 @@ import type {
6
6
  BlockCodeKnownFeatureFlags,
7
7
  BlockConfigContainer,
8
8
  } from '@milaboratories/pl-model-common';
9
- import { getPlatformaInstance, isInUI, createAndRegisterRenderLambda, createRenderLambda } from './internal';
9
+ import {
10
+ getPlatformaInstance,
11
+ isInUI,
12
+ createAndRegisterRenderLambda,
13
+ createRenderLambda,
14
+ } from './internal';
10
15
  import type { DataModel } from './block_migrations';
11
16
  import type { PlatformaV3 } from './platforma';
12
17
  import type { InferRenderFunctionReturn, RenderFunction } from './render';
@@ -20,10 +25,7 @@ import type {
20
25
  ConfigRenderLambdaFlags,
21
26
  InferOutputsFromLambdas,
22
27
  } from './bconfig';
23
- import {
24
- downgradeCfgOrLambda,
25
- isConfigLambda,
26
- } from './bconfig';
28
+ import { downgradeCfgOrLambda, isConfigLambda } from './bconfig';
27
29
  import type { PlatformaExtended } from './platforma';
28
30
 
29
31
  type SectionsExpectedType = readonly BlockSection[];
@@ -68,19 +70,27 @@ export class BlockModelV3<
68
70
  > {
69
71
  private constructor(
70
72
  private readonly config: BlockModelV3Config<Args, OutputsCfg, Data>,
71
- ) {}
73
+ ) { }
72
74
 
73
- public static readonly INITIAL_BLOCK_FEATURE_FLAGS: BlockCodeKnownFeatureFlags = {
74
- supportsLazyState: true,
75
- requiresUIAPIVersion: 3,
76
- requiresModelAPIVersion: 2,
77
- };
75
+ public static readonly INITIAL_BLOCK_FEATURE_FLAGS: BlockCodeKnownFeatureFlags
76
+ = {
77
+ supportsLazyState: true,
78
+ requiresUIAPIVersion: 3,
79
+ requiresModelAPIVersion: 2,
80
+ };
78
81
 
79
82
  /**
80
83
  * Creates a new BlockModelV3 builder with the specified data model and options.
81
84
  *
82
85
  * @example
83
- * const dataModel = DataModel.create<BlockData>(() => ({ numbers: [], labels: [] }));
86
+ * const Version = defineDataVersions({ V1: DATA_MODEL_DEFAULT_VERSION });
87
+ *
88
+ * type VersionedData = { [Version.V1]: BlockData };
89
+ *
90
+ * const dataModel = new DataModelBuilder<VersionedData>()
91
+ * .from(Version.V1)
92
+ * .init(() => ({ numbers: [], labels: [] }));
93
+ *
84
94
  * BlockModelV3.create({ dataModel })
85
95
  * .args((data) => ({ numbers: data.numbers }))
86
96
  * .sections(() => [{ type: 'link', href: '/', label: 'Main' }])
@@ -101,7 +111,10 @@ export class BlockModelV3<
101
111
  dataModel,
102
112
  outputs: {},
103
113
  // Register default sections callback (returns empty array)
104
- sections: createAndRegisterRenderLambda({ handle: 'sections', lambda: () => [] }, true),
114
+ sections: createAndRegisterRenderLambda(
115
+ { handle: 'sections', lambda: () => [] },
116
+ true,
117
+ ),
105
118
  title: undefined,
106
119
  subtitle: undefined,
107
120
  tags: undefined,
@@ -120,15 +133,22 @@ export class BlockModelV3<
120
133
  * workflows outputs and interact with platforma drivers
121
134
  * @param flags additional flags that may alter lambda rendering procedure
122
135
  * */
123
- public output<const Key extends string, const RF extends RenderFunction<Args, Data>>(
136
+ public output<
137
+ const Key extends string,
138
+ const RF extends RenderFunction<Args, Data>,
139
+ >(
124
140
  key: Key,
125
141
  rf: RF,
126
142
  flags: ConfigRenderLambdaFlags & { withStatus: true }
127
143
  ): BlockModelV3<
128
144
  Args,
129
- OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> & { withStatus: true } },
130
- Data,
131
- Href
145
+ OutputsCfg & {
146
+ [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> & {
147
+ withStatus: true;
148
+ };
149
+ },
150
+ Data,
151
+ Href
132
152
  >;
133
153
  /**
134
154
  * Add output cell to the configuration
@@ -138,13 +158,18 @@ export class BlockModelV3<
138
158
  * workflows outputs and interact with platforma drivers
139
159
  * @param flags additional flags that may alter lambda rendering procedure
140
160
  * */
141
- public output<const Key extends string, const RF extends RenderFunction<Args, Data>>(
161
+ public output<
162
+ const Key extends string,
163
+ const RF extends RenderFunction<Args, Data>,
164
+ >(
142
165
  key: Key,
143
166
  rf: RF,
144
167
  flags?: ConfigRenderLambdaFlags
145
168
  ): BlockModelV3<
146
169
  Args,
147
- OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> },
170
+ OutputsCfg & {
171
+ [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>>;
172
+ },
148
173
  Data,
149
174
  Href
150
175
  >;
@@ -157,29 +182,38 @@ export class BlockModelV3<
157
182
  ...this.config,
158
183
  outputs: {
159
184
  ...this.config.outputs,
160
- [key]: createAndRegisterRenderLambda({ handle: `output#${key}`, lambda: () => cfgOrRf(new RenderCtx()), ...flags }),
185
+ [key]: createAndRegisterRenderLambda({
186
+ handle: `output#${key}`,
187
+ lambda: () => cfgOrRf(new RenderCtx()),
188
+ ...flags,
189
+ }),
161
190
  },
162
191
  });
163
192
  }
164
193
 
165
194
  /** Shortcut for {@link output} with retentive flag set to true. */
166
- public retentiveOutput<const Key extends string, const RF extends RenderFunction<Args, Data>>(
195
+ public retentiveOutput<
196
+ const Key extends string,
197
+ const RF extends RenderFunction<Args, Data>,
198
+ >(
167
199
  key: Key,
168
200
  rf: RF,
169
201
  ): BlockModelV3<
170
202
  Args,
171
- OutputsCfg & { [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>> },
172
- Data,
173
- Href
203
+ OutputsCfg & {
204
+ [K in Key]: ConfigRenderLambda<InferRenderFunctionReturn<RF>>;
205
+ },
206
+ Data,
207
+ Href
174
208
  > {
175
209
  return this.output(key, rf, { retentive: true });
176
210
  }
177
211
 
178
212
  /** Shortcut for {@link output} with withStatus flag set to true. */
179
- public outputWithStatus<const Key extends string, const RF extends RenderFunction<Args, Data>>(
180
- key: Key,
181
- rf: RF,
182
- ) {
213
+ public outputWithStatus<
214
+ const Key extends string,
215
+ const RF extends RenderFunction<Args, Data>,
216
+ >(key: Key, rf: RF) {
183
217
  return this.output(key, rf, { withStatus: true });
184
218
  }
185
219
 
@@ -196,7 +230,9 @@ export class BlockModelV3<
196
230
  * return { numbers: data.numbers };
197
231
  * })
198
232
  */
199
- public args<Args>(lambda: (data: Data) => Args): BlockModelV3<Args, OutputsCfg, Data, Href> {
233
+ public args<Args>(
234
+ lambda: (data: Data) => Args,
235
+ ): BlockModelV3<Args, OutputsCfg, Data, Href> {
200
236
  return new BlockModelV3<Args, OutputsCfg, Data, Href>({
201
237
  ...this.config,
202
238
  args: createAndRegisterRenderLambda<Args>({ handle: 'args', lambda }),
@@ -223,10 +259,15 @@ export class BlockModelV3<
223
259
  * return { numbers: data.numbers };
224
260
  * })
225
261
  */
226
- public prerunArgs(fn: (data: Data) => unknown): BlockModelV3<Args, OutputsCfg, Data, Href> {
262
+ public prerunArgs(
263
+ fn: (data: Data) => unknown,
264
+ ): BlockModelV3<Args, OutputsCfg, Data, Href> {
227
265
  return new BlockModelV3<Args, OutputsCfg, Data, Href>({
228
266
  ...this.config,
229
- prerunArgs: createAndRegisterRenderLambda({ handle: 'prerunArgs', lambda: fn }),
267
+ prerunArgs: createAndRegisterRenderLambda({
268
+ handle: 'prerunArgs',
269
+ lambda: fn,
270
+ }),
230
271
  });
231
272
  }
232
273
 
@@ -235,11 +276,16 @@ export class BlockModelV3<
235
276
  const Ret extends SectionsExpectedType,
236
277
  const RF extends RenderFunction<Args, Data, Ret>,
237
278
  >(rf: RF): BlockModelV3<Args, OutputsCfg, Data, DeriveHref<ReturnType<RF>>> {
238
- return new BlockModelV3<Args, OutputsCfg, Data, DeriveHref<ReturnType<RF>>>({
239
- ...this.config,
240
- // Replace the default sections callback with the user-provided one
241
- sections: createAndRegisterRenderLambda({ handle: 'sections', lambda: () => rf(new RenderCtx()) }, true),
242
- });
279
+ return new BlockModelV3<Args, OutputsCfg, Data, DeriveHref<ReturnType<RF>>>(
280
+ {
281
+ ...this.config,
282
+ // Replace the default sections callback with the user-provided one
283
+ sections: createAndRegisterRenderLambda(
284
+ { handle: 'sections', lambda: () => rf(new RenderCtx()) },
285
+ true,
286
+ ),
287
+ },
288
+ );
243
289
  }
244
290
 
245
291
  /** Sets a rendering function to derive block title, shown for the block in the left blocks-overview panel. */
@@ -248,7 +294,10 @@ export class BlockModelV3<
248
294
  ): BlockModelV3<Args, OutputsCfg, Data, Href> {
249
295
  return new BlockModelV3<Args, OutputsCfg, Data, Href>({
250
296
  ...this.config,
251
- title: createAndRegisterRenderLambda({ handle: 'title', lambda: () => rf(new RenderCtx()) }),
297
+ title: createAndRegisterRenderLambda({
298
+ handle: 'title',
299
+ lambda: () => rf(new RenderCtx()),
300
+ }),
252
301
  });
253
302
  }
254
303
 
@@ -257,7 +306,10 @@ export class BlockModelV3<
257
306
  ): BlockModelV3<Args, OutputsCfg, Data, Href> {
258
307
  return new BlockModelV3<Args, OutputsCfg, Data, Href>({
259
308
  ...this.config,
260
- subtitle: createAndRegisterRenderLambda({ handle: 'subtitle', lambda: () => rf(new RenderCtx()) }),
309
+ subtitle: createAndRegisterRenderLambda({
310
+ handle: 'subtitle',
311
+ lambda: () => rf(new RenderCtx()),
312
+ }),
261
313
  });
262
314
  }
263
315
 
@@ -266,12 +318,17 @@ export class BlockModelV3<
266
318
  ): BlockModelV3<Args, OutputsCfg, Data, Href> {
267
319
  return new BlockModelV3<Args, OutputsCfg, Data, Href>({
268
320
  ...this.config,
269
- tags: createAndRegisterRenderLambda({ handle: 'tags', lambda: () => rf(new RenderCtx()) }),
321
+ tags: createAndRegisterRenderLambda({
322
+ handle: 'tags',
323
+ lambda: () => rf(new RenderCtx()),
324
+ }),
270
325
  });
271
326
  }
272
327
 
273
328
  /** Sets or overrides feature flags for the block. */
274
- public withFeatureFlags(flags: Partial<BlockCodeKnownFeatureFlags>): BlockModelV3<Args, OutputsCfg, Data, Href> {
329
+ public withFeatureFlags(
330
+ flags: Partial<BlockCodeKnownFeatureFlags>,
331
+ ): BlockModelV3<Args, OutputsCfg, Data, Href> {
275
332
  return new BlockModelV3<Args, OutputsCfg, Data, Href>({
276
333
  ...this.config,
277
334
  featureFlags: { ...this.config.featureFlags, ...flags },
@@ -287,31 +344,29 @@ export class BlockModelV3<
287
344
  ): BlockModelV3<Args, OutputsCfg, Data, Href> {
288
345
  return new BlockModelV3<Args, OutputsCfg, Data, Href>({
289
346
  ...this.config,
290
- enrichmentTargets: createAndRegisterRenderLambda({ handle: 'enrichmentTargets', lambda: lambda }),
347
+ enrichmentTargets: createAndRegisterRenderLambda({
348
+ handle: 'enrichmentTargets',
349
+ lambda: lambda,
350
+ }),
291
351
  });
292
352
  }
293
353
 
294
354
  /** Renders all provided block settings into a pre-configured platforma API
295
355
  * instance, that can be used in frontend to interact with block data, and
296
356
  * other features provided by the platforma to the block. */
297
- public done(): PlatformaExtended<PlatformaV3<
298
- Args,
299
- InferOutputsFromLambdas<OutputsCfg>,
300
- Data,
301
- Href
302
- >> {
357
+ public done(): PlatformaExtended<
358
+ PlatformaV3<Args, InferOutputsFromLambdas<OutputsCfg>, Data, Href>
359
+ > {
303
360
  return this.withFeatureFlags({
304
361
  ...this.config.featureFlags,
305
362
  })._done();
306
363
  }
307
364
 
308
- public _done(): PlatformaExtended<PlatformaV3<
309
- Args,
310
- InferOutputsFromLambdas<OutputsCfg>,
311
- Data,
312
- Href
313
- >> {
314
- if (this.config.args === undefined) throw new Error('Args rendering function not set.');
365
+ public _done(): PlatformaExtended<
366
+ PlatformaV3<Args, InferOutputsFromLambdas<OutputsCfg>, Data, Href>
367
+ > {
368
+ if (this.config.args === undefined)
369
+ throw new Error('Args rendering function not set.');
315
370
 
316
371
  const apiVersion = 3;
317
372
 
@@ -333,9 +388,10 @@ export class BlockModelV3<
333
388
  enrichmentTargets: this.config.enrichmentTargets,
334
389
  featureFlags: this.config.featureFlags,
335
390
  // Generate migration descriptors (indices for metadata)
336
- migrations: migrationCount > 0
337
- ? Array.from({ length: migrationCount }, (_, i) => ({ index: i }))
338
- : undefined,
391
+ migrations:
392
+ migrationCount > 0
393
+ ? Array.from({ length: migrationCount }, (_, i) => ({ index: i }))
394
+ : undefined,
339
395
  },
340
396
 
341
397
  // fields below are added to allow previous desktop versions read generated configs
@@ -343,27 +399,36 @@ export class BlockModelV3<
343
399
  renderingMode: this.config.renderingMode,
344
400
  sections: this.config.sections,
345
401
  outputs: Object.fromEntries(
346
- Object.entries(this.config.outputs).map(([key, value]) => [key, downgradeCfgOrLambda(value)]),
402
+ Object.entries(this.config.outputs).map(([key, value]) => [
403
+ key,
404
+ downgradeCfgOrLambda(value),
405
+ ]),
347
406
  ),
348
407
  };
349
408
 
350
409
  globalThis.platformaApiVersion = apiVersion;
351
410
 
352
411
  if (!isInUI())
353
- // we are in the configuration rendering routine, not in actual UI
412
+ // we are in the configuration rendering routine, not in actual UI
354
413
  return { config: blockConfig } as any;
355
414
  // normal operation inside the UI
356
- else return {
357
- ...getPlatformaInstance({ sdkVersion: PlatformaSDKVersion, apiVersion }),
358
- blockModelInfo: {
359
- outputs: Object.fromEntries(
360
- Object.entries(this.config.outputs)
361
- .map(([key, value]) => [key, {
362
- withStatus: Boolean(isConfigLambda(value) && value.withStatus),
363
- }]),
364
- ),
365
- },
366
- } as any;
415
+ else
416
+ return {
417
+ ...getPlatformaInstance({
418
+ sdkVersion: PlatformaSDKVersion,
419
+ apiVersion,
420
+ }),
421
+ blockModelInfo: {
422
+ outputs: Object.fromEntries(
423
+ Object.entries(this.config.outputs).map(([key, value]) => [
424
+ key,
425
+ {
426
+ withStatus: Boolean(isConfigLambda(value) && value.withStatus),
427
+ },
428
+ ]),
429
+ ),
430
+ },
431
+ } as any;
367
432
  }
368
433
  }
369
434
 
@@ -371,70 +436,118 @@ export class BlockModelV3<
371
436
 
372
437
  export type Expect<T extends true> = T;
373
438
 
374
- export type Equal<X, Y> =
375
- (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;
439
+ export type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <
440
+ T,
441
+ >() => T extends Y ? 1 : 2
442
+ ? true
443
+ : false;
376
444
 
377
445
  export type Merge<A, B> = {
378
- [K in keyof A | keyof B]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never;
446
+ [K in keyof A | keyof B]: K extends keyof B
447
+ ? B[K]
448
+ : K extends keyof A
449
+ ? A[K]
450
+ : never;
379
451
  };
380
452
 
381
453
  // Helper types for testing
382
454
  type _TestArgs = { inputFile: string; threshold: number };
383
455
  type _TestData = { selectedTab: string };
384
- type _TestOutputs = { result: ConfigRenderLambda<string>; count: ConfigRenderLambda<number> };
456
+ type _TestOutputs = {
457
+ result: ConfigRenderLambda<string>;
458
+ count: ConfigRenderLambda<number>;
459
+ };
385
460
 
386
461
  // Test: Merge type works correctly
387
462
  type _MergeTest1 = Expect<Equal<Merge<{ a: 1 }, { b: 2 }>, { a: 1; b: 2 }>>;
388
463
  type _MergeTest2 = Expect<Equal<Merge<{ a: 1 }, { a: 2 }>, { a: 2 }>>;
389
- type _MergeTest3 = Expect<Equal<Merge<{ a: 1; b: 1 }, { b: 2; c: 3 }>, { a: 1; b: 2; c: 3 }>>;
464
+ type _MergeTest3 = Expect<
465
+ Equal<Merge<{ a: 1; b: 1 }, { b: 2; c: 3 }>, { a: 1; b: 2; c: 3 }>
466
+ >;
390
467
 
391
468
  // Test: create() returns a BlockModelV3 instance
392
469
  // Note: Due to function overloads, ReturnType uses the last overload signature.
393
470
  // We verify the structure is correct using a simpler assignability test.
394
471
  type _CreateResult = ReturnType<typeof BlockModelV3.create>;
395
- type _CreateIsBlockModelV3 = _CreateResult extends BlockModelV3<infer _A, infer _O, infer _S> ? true : false;
472
+ type _CreateIsBlockModelV3 = _CreateResult extends BlockModelV3<
473
+ infer _A,
474
+ infer _O,
475
+ infer _S
476
+ >
477
+ ? true
478
+ : false;
396
479
  type _CreateTest = Expect<_CreateIsBlockModelV3>;
397
480
 
398
481
  // Test: BlockModelV3Config interface structure
399
- type _ConfigTest = Expect<Equal<
400
- BlockModelV3Config<_TestArgs, _TestOutputs, _TestData>,
401
- {
402
- renderingMode: BlockRenderingMode;
403
- args: ConfigRenderLambda<_TestArgs> | undefined;
404
- prerunArgs: ConfigRenderLambda<unknown> | undefined;
405
- dataModel: DataModel<_TestData>;
406
- outputs: _TestOutputs;
407
- sections: ConfigRenderLambda;
408
- title: ConfigRenderLambda | undefined;
409
- subtitle: ConfigRenderLambda | undefined;
410
- tags: ConfigRenderLambda | undefined;
411
- enrichmentTargets: ConfigRenderLambda | undefined;
412
- featureFlags: BlockCodeKnownFeatureFlags;
413
- }
414
- >>;
482
+ type _ConfigTest = Expect<
483
+ Equal<
484
+ BlockModelV3Config<_TestArgs, _TestOutputs, _TestData>,
485
+ {
486
+ renderingMode: BlockRenderingMode;
487
+ args: ConfigRenderLambda<_TestArgs> | undefined;
488
+ prerunArgs: ConfigRenderLambda<unknown> | undefined;
489
+ dataModel: DataModel<_TestData>;
490
+ outputs: _TestOutputs;
491
+ sections: ConfigRenderLambda;
492
+ title: ConfigRenderLambda | undefined;
493
+ subtitle: ConfigRenderLambda | undefined;
494
+ tags: ConfigRenderLambda | undefined;
495
+ enrichmentTargets: ConfigRenderLambda | undefined;
496
+ featureFlags: BlockCodeKnownFeatureFlags;
497
+ }
498
+ >
499
+ >;
415
500
 
416
501
  // Test: Default Href is '/'
417
- type _HrefDefaultTest = BlockModelV3<_TestArgs, {}, _TestData> extends BlockModelV3<_TestArgs, {}, _TestData, '/'> ? true : false;
502
+ type _HrefDefaultTest = BlockModelV3<
503
+ _TestArgs,
504
+ {},
505
+ _TestData
506
+ > extends BlockModelV3<_TestArgs, {}, _TestData, '/'>
507
+ ? true
508
+ : false;
418
509
  type _VerifyHrefDefault = Expect<_HrefDefaultTest>;
419
510
 
420
511
  // Test: Custom Href can be specified
421
512
  type _CustomHref = '/settings' | '/main';
422
513
  type _HrefCustomBuilder = BlockModelV3<_TestArgs, {}, _TestData, _CustomHref>;
423
- type _HrefCustomTest = _HrefCustomBuilder extends BlockModelV3<_TestArgs, {}, _TestData, _CustomHref> ? true : false;
514
+ type _HrefCustomTest = _HrefCustomBuilder extends BlockModelV3<
515
+ _TestArgs,
516
+ {},
517
+ _TestData,
518
+ _CustomHref
519
+ >
520
+ ? true
521
+ : false;
424
522
  type _VerifyHrefCustom = Expect<_HrefCustomTest>;
425
523
 
426
524
  // Test: Output type accumulation with & intersection
427
- type _OutputsAccumulation = { a: ConfigRenderLambda<string> } & { b: ConfigRenderLambda<number> };
428
- type _VerifyOutputsHaveKeys = Expect<Equal<keyof _OutputsAccumulation, 'a' | 'b'>>;
525
+ type _OutputsAccumulation = { a: ConfigRenderLambda<string> } & {
526
+ b: ConfigRenderLambda<number>;
527
+ };
528
+ type _VerifyOutputsHaveKeys = Expect<
529
+ Equal<keyof _OutputsAccumulation, 'a' | 'b'>
530
+ >;
429
531
 
430
532
  // Test: Builder with all type parameters specified compiles
431
533
  type _FullBuilder = BlockModelV3<_TestArgs, _TestOutputs, _TestData, '/main'>;
432
- type _FullBuilderTest = _FullBuilder extends BlockModelV3<_TestArgs, _TestOutputs, _TestData, '/main'> ? true : false;
534
+ type _FullBuilderTest = _FullBuilder extends BlockModelV3<
535
+ _TestArgs,
536
+ _TestOutputs,
537
+ _TestData,
538
+ '/main'
539
+ >
540
+ ? true
541
+ : false;
433
542
  type _VerifyFullBuilder = Expect<_FullBuilderTest>;
434
543
 
435
544
  // Test: InferOutputsFromLambdas maps outputs correctly
436
- type _InferOutputsTest = InferOutputsFromLambdas<{ myOutput: ConfigRenderLambda<number> }>;
437
- type _VerifyInferOutputs = Expect<Equal<
438
- _InferOutputsTest,
439
- { myOutput: OutputWithStatus<number> & { __unwrap: true } }
440
- >>;
545
+ type _InferOutputsTest = InferOutputsFromLambdas<{
546
+ myOutput: ConfigRenderLambda<number>;
547
+ }>;
548
+ type _VerifyInferOutputs = Expect<
549
+ Equal<
550
+ _InferOutputsTest,
551
+ { myOutput: OutputWithStatus<number> & { __unwrap: true } }
552
+ >
553
+ >;
@@ -105,7 +105,13 @@ export function createBlockStorage<TState = unknown>(
105
105
  export function normalizeBlockStorage<TState = unknown>(raw: unknown): BlockStorage<TState> {
106
106
  if (isBlockStorage(raw)) {
107
107
  const storage = raw as BlockStorage<TState>;
108
- return { ...storage, __dataVersion: String(storage.__dataVersion) };
108
+ return {
109
+ ...storage,
110
+ // Fix for early released version where __dataVersion was a number
111
+ __dataVersion: typeof storage.__dataVersion === 'number'
112
+ ? DATA_MODEL_DEFAULT_VERSION
113
+ : storage.__dataVersion,
114
+ };
109
115
  }
110
116
  // Legacy format: raw is the state directly
111
117
  return createBlockStorage(raw as TState);
@@ -14,7 +14,7 @@
14
14
  *
15
15
  * Callbacks registered by DataModel.registerCallbacks():
16
16
  * - `__pl_data_initial`: () => initial data
17
- * - `__pl_data_migrate`: (versioned) => DataMigrationResult
17
+ * - `__pl_data_upgrade`: (versioned) => DataMigrationResult
18
18
  * - `__pl_storage_initial`: () => initial BlockStorage as JSON string
19
19
  *
20
20
  * @module block_storage_vm
@@ -178,7 +178,7 @@ interface DataMigrationResult {
178
178
  * Runs storage migration using the DataModel's migrate callback.
179
179
  * This is the main entry point for the middle layer to trigger migrations.
180
180
  *
181
- * Uses the '__pl_data_migrate' callback registered by DataModel.registerCallbacks() which:
181
+ * Uses the '__pl_data_upgrade' callback registered by DataModel.registerCallbacks() which:
182
182
  * - Handles all migration logic internally
183
183
  * - Returns { version, data, warning? } - warning present if reset to initial data
184
184
  *
@@ -206,9 +206,9 @@ function migrateStorage(currentStorageJson: string | undefined): MigrationResult
206
206
  };
207
207
 
208
208
  // Get the migrate callback (registered by DataModel.registerCallbacks())
209
- const migrateCallback = ctx.callbackRegistry['__pl_data_migrate'] as ((v: { version: string; data: unknown }) => DataMigrationResult) | undefined;
209
+ const migrateCallback = ctx.callbackRegistry['__pl_data_upgrade'] as ((v: { version: string; data: unknown }) => DataMigrationResult) | undefined;
210
210
  if (typeof migrateCallback !== 'function') {
211
- return { error: '__pl_data_migrate callback not found (DataModel not registered)' };
211
+ return { error: '__pl_data_upgrade callback not found (DataModel not registered)' };
212
212
  }
213
213
 
214
214
  // Call the migrator's migrate function
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ export * from './builder';
5
5
  export { BlockModelV3 } from './block_model';
6
6
  export {
7
7
  DataModel,
8
+ DataModelBuilder,
8
9
  DataUnrecoverableError,
9
10
  isDataUnrecoverableError,
10
11
  defineDataVersions,