@milaboratories/milaboratories.pool-explorer.model 1.1.2 → 1.1.4

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.
@@ -1,16 +1,16 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/milaboratories.pool-explorer.model@1.1.2 build /home/runner/_work/platforma/platforma/etc/blocks/pool-explorer/model
3
+ > @milaboratories/milaboratories.pool-explorer.model@1.1.4 build /home/runner/_work/platforma/platforma/etc/blocks/pool-explorer/model
4
4
  > ts-builder build --target block-model && block-tools build-model
5
5
 
6
6
  Building block-model project...
7
7
  ↳ rollup -c /configs/rollup.block-model.config.js
8
8
  
9
9
  ./src/index.ts → dist, dist...
10
- created dist, dist in 1.5s
10
+ created dist, dist in 2.4s
11
11
  
12
12
  ./src/index.ts → dist...
13
13
  (!) Circular dependency
14
14
  ../../../../sdk/model/dist/components/PFrameForGraphs.js -> ../../../../sdk/model/dist/pframe_utils/columns.js -> ../../../../sdk/model/dist/components/PFrameForGraphs.js
15
- created dist in 3.5s
15
+ created dist in 3.7s
16
16
  Build completed successfully
@@ -1,5 +1,5 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/milaboratories.pool-explorer.model@1.1.2 lint /home/runner/_work/platforma/platforma/etc/blocks/pool-explorer/model
3
+ > @milaboratories/milaboratories.pool-explorer.model@1.1.4 lint /home/runner/_work/platforma/platforma/etc/blocks/pool-explorer/model
4
4
  > eslint .
5
5
 
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/milaboratories.pool-explorer.model@1.1.2 type-check /home/runner/_work/platforma/platforma/etc/blocks/pool-explorer/model
3
+ > @milaboratories/milaboratories.pool-explorer.model@1.1.4 type-check /home/runner/_work/platforma/platforma/etc/blocks/pool-explorer/model
4
4
  > ts-builder types --target block-model
5
5
 
6
6
  ↳ tsc --noEmit --project ./tsconfig.json --customConditions ,
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @milaboratories/milaboratories.pool-explorer.model
2
2
 
3
+ ## 1.1.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [a748b92]
8
+ - @platforma-sdk/model@1.53.1
9
+
10
+ ## 1.1.3
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [43b4247]
15
+ - @platforma-sdk/model@1.53.0
16
+
3
17
  ## 1.1.2
4
18
 
5
19
  ### Patch Changes
package/dist/bundle.js CHANGED
@@ -27,6 +27,11 @@
27
27
  * Increment this when the storage structure itself changes (not block state migrations).
28
28
  */
29
29
  const BLOCK_STORAGE_SCHEMA_VERSION = 'v1';
30
+ /**
31
+ * Default data version for new blocks without migrations.
32
+ * Unique identifier ensures blocks are created via DataModel API.
33
+ */
34
+ const DATA_MODEL_DEFAULT_VERSION = '__pl_v1_d4e8f2a1__';
30
35
  /**
31
36
  * Type guard to check if a value is a valid BlockStorage object.
32
37
  * Checks for the discriminator key and valid schema version.
@@ -46,16 +51,32 @@
46
51
  * Creates a BlockStorage with the given initial data
47
52
  *
48
53
  * @param initialData - The initial data value (defaults to empty object)
49
- * @param version - The initial data version (defaults to 1)
54
+ * @param version - The initial data version key (defaults to DATA_MODEL_DEFAULT_VERSION)
50
55
  * @returns A new BlockStorage instance with discriminator key
51
56
  */
52
- function createBlockStorage(initialData = {}, version = 1) {
57
+ function createBlockStorage(initialData = {}, version = DATA_MODEL_DEFAULT_VERSION) {
53
58
  return {
54
59
  [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,
55
60
  __dataVersion: version,
56
61
  __data: initialData,
57
62
  };
58
63
  }
64
+ /**
65
+ * Normalizes raw storage data to BlockStorage format.
66
+ * If the input is already a BlockStorage, returns it as-is.
67
+ * If the input is legacy format (raw state), wraps it in BlockStorage structure.
68
+ *
69
+ * @param raw - Raw storage data (may be legacy format or BlockStorage)
70
+ * @returns Normalized BlockStorage
71
+ */
72
+ function normalizeBlockStorage(raw) {
73
+ if (isBlockStorage(raw)) {
74
+ const storage = raw;
75
+ return { ...storage, __dataVersion: String(storage.__dataVersion) };
76
+ }
77
+ // Legacy format: raw is the state directly
78
+ return createBlockStorage(raw);
79
+ }
59
80
  // =============================================================================
60
81
  // Data Access & Update Functions
61
82
  // =============================================================================
@@ -4795,6 +4816,9 @@
4795
4816
  Table: {
4796
4817
  OrderPriority: 'pl7.app/table/orderPriority'},
4797
4818
  Trace: 'pl7.app/trace',
4819
+ VDJ: {
4820
+ IsAssemblingFeature: 'pl7.app/vdj/isAssemblingFeature',
4821
+ },
4798
4822
  };
4799
4823
  const ValueTypeSchema = z.enum(['Int', 'Long', 'Float', 'Double', 'String']);
4800
4824
  const AnnotationJson = {
@@ -4824,6 +4848,7 @@
4824
4848
  [Annotation.Sequence.IsAnnotation]: z.boolean(),
4825
4849
  [Annotation.Table.OrderPriority]: z.number(),
4826
4850
  [Annotation.Trace]: z.record(z.string(), z.unknown()),
4851
+ [Annotation.VDJ.IsAssemblingFeature]: z.boolean(),
4827
4852
  };
4828
4853
  /// Helper function for reading plain annotation values
4829
4854
  function readAnnotation(spec, key) {
@@ -7498,7 +7523,7 @@
7498
7523
  }
7499
7524
  }
7500
7525
 
7501
- var version = "1.52.7";
7526
+ var version = "1.53.1";
7502
7527
 
7503
7528
  const PlatformaSDKVersion = version;
7504
7529
 
@@ -7530,7 +7555,7 @@
7530
7555
  *
7531
7556
  * Callbacks registered by DataModel.registerCallbacks():
7532
7557
  * - `__pl_data_initial`: () => initial data
7533
- * - `__pl_data_upgrade`: (versioned) => UpgradeResult
7558
+ * - `__pl_data_migrate`: (versioned) => DataMigrationResult
7534
7559
  * - `__pl_storage_initial`: () => initial BlockStorage as JSON string
7535
7560
  *
7536
7561
  * @module block_storage_vm
@@ -7566,7 +7591,8 @@
7566
7591
  }
7567
7592
  // Check for BlockStorage format (has discriminator)
7568
7593
  if (isBlockStorage(parsed)) {
7569
- return { storage: parsed, data: getStorageData(parsed) };
7594
+ const storage = normalizeBlockStorage(parsed);
7595
+ return { storage, data: getStorageData(storage) };
7570
7596
  }
7571
7597
  // Check for legacy V1/V2 format: { args, uiState }
7572
7598
  if (isLegacyModelV1ApiFormat(parsed)) {
@@ -7631,10 +7657,10 @@
7631
7657
  return getStorageDebugView(rawStorage);
7632
7658
  });
7633
7659
  /**
7634
- * Runs storage migration using the DataModel's upgrade callback.
7660
+ * Runs storage migration using the DataModel's migrate callback.
7635
7661
  * This is the main entry point for the middle layer to trigger migrations.
7636
7662
  *
7637
- * Uses the '__pl_data_upgrade' callback registered by DataModel.registerCallbacks() which:
7663
+ * Uses the '__pl_data_migrate' callback registered by DataModel.registerCallbacks() which:
7638
7664
  * - Handles all migration logic internally
7639
7665
  * - Returns { version, data, warning? } - warning present if reset to initial data
7640
7666
  *
@@ -7658,26 +7684,26 @@
7658
7684
  __data: data,
7659
7685
  });
7660
7686
  };
7661
- // Get the upgrade callback (registered by DataModel.registerCallbacks())
7662
- const upgradeCallback = ctx.callbackRegistry['__pl_data_upgrade'];
7663
- if (typeof upgradeCallback !== 'function') {
7664
- return { error: '__pl_data_upgrade callback not found (DataModel not registered)' };
7687
+ // Get the migrate callback (registered by DataModel.registerCallbacks())
7688
+ const migrateCallback = ctx.callbackRegistry['__pl_data_migrate'];
7689
+ if (typeof migrateCallback !== 'function') {
7690
+ return { error: '__pl_data_migrate callback not found (DataModel not registered)' };
7665
7691
  }
7666
- // Call the migrator's upgrade function
7692
+ // Call the migrator's migrate function
7667
7693
  let result;
7668
7694
  try {
7669
- result = upgradeCallback({ version: currentVersion, data: currentData });
7695
+ result = migrateCallback({ version: currentVersion, data: currentData });
7670
7696
  }
7671
7697
  catch (e) {
7672
7698
  const errorMsg = e instanceof Error ? e.message : String(e);
7673
- return { error: `upgrade() threw: ${errorMsg}` };
7699
+ return { error: `migrate() threw: ${errorMsg}` };
7674
7700
  }
7675
7701
  // Build info message
7676
7702
  const info = result.version === currentVersion
7677
- ? `No migration needed (v${currentVersion})`
7703
+ ? `No migration needed (${currentVersion})`
7678
7704
  : result.warning
7679
- ? `Reset to initial data (v${result.version})`
7680
- : `Migrated v${currentVersion}→v${result.version}`;
7705
+ ? `Reset to initial data (${result.version})`
7706
+ : `Migrated ${currentVersion}→${result.version}`;
7681
7707
  return {
7682
7708
  newStorageJson: createStorageJson(result.data, result.version),
7683
7709
  info,
@@ -7974,23 +8000,54 @@
7974
8000
  }
7975
8001
  }
7976
8002
 
8003
+ /** Create a DataVersioned wrapper with correct shape */
8004
+ function makeDataVersioned(version, data) {
8005
+ return { version, data };
8006
+ }
8007
+ /** Thrown by recover() to signal unrecoverable data. */
8008
+ class DataUnrecoverableError extends Error {
8009
+ name = 'DataUnrecoverableError';
8010
+ constructor(dataVersion) {
8011
+ super(`Unknown version '${dataVersion}'`);
8012
+ }
8013
+ }
8014
+ function isDataUnrecoverableError(error) {
8015
+ return error instanceof Error && error.name === 'DataUnrecoverableError';
8016
+ }
8017
+ /** Default recover function for unknown versions */
8018
+ const defaultRecover = (version, _data) => {
8019
+ throw new DataUnrecoverableError(version);
8020
+ };
7977
8021
  /** Internal builder for chaining migrations */
7978
8022
  class DataModelBuilder {
8023
+ versionChain;
7979
8024
  migrationSteps;
7980
- constructor(steps = []) {
8025
+ recoverFn;
8026
+ constructor(versionChain, steps = [], recoverFn) {
8027
+ this.versionChain = versionChain;
7981
8028
  this.migrationSteps = steps;
8029
+ this.recoverFn = recoverFn;
7982
8030
  }
7983
- /** Start a migration chain from an initial type */
7984
- static from() {
7985
- return new DataModelBuilder();
8031
+ /** Start a migration chain from an initial version */
8032
+ static from(initialVersion) {
8033
+ return new DataModelBuilder([initialVersion]);
7986
8034
  }
7987
- /** Add a migration step */
7988
- migrate(fn) {
7989
- return new DataModelBuilder([...this.migrationSteps, fn]);
8035
+ /** Add a migration step to the target version */
8036
+ migrate(nextVersion, fn) {
8037
+ if (this.versionChain.includes(nextVersion)) {
8038
+ throw new Error(`Duplicate version '${nextVersion}' in migration chain`);
8039
+ }
8040
+ const fromVersion = this.versionChain[this.versionChain.length - 1];
8041
+ const step = { fromVersion, toVersion: nextVersion, migrate: fn };
8042
+ return new DataModelBuilder([...this.versionChain, nextVersion], [...this.migrationSteps, step]);
8043
+ }
8044
+ /** Set recovery handler for unknown or unsupported versions */
8045
+ recover(fn) {
8046
+ return new DataModelBuilder([...this.versionChain], [...this.migrationSteps], fn);
7990
8047
  }
7991
8048
  /** Finalize with initial data, creating the DataModel */
7992
8049
  create(initialData, ..._) {
7993
- return DataModel._fromBuilder(this.migrationSteps, initialData);
8050
+ return DataModel._fromBuilder(this.versionChain, this.migrationSteps, initialData, this.recoverFn);
7994
8051
  }
7995
8052
  }
7996
8053
  /**
@@ -8005,37 +8062,61 @@
8005
8062
  * }));
8006
8063
  *
8007
8064
  * // Data model with migrations
8065
+ * const Version = defineDataVersions({
8066
+ * V1: 'v1',
8067
+ * V2: 'v2',
8068
+ * V3: 'v3',
8069
+ * });
8070
+ *
8071
+ * type VersionedData = {
8072
+ * [Version.V1]: { numbers: number[] };
8073
+ * [Version.V2]: { numbers: number[]; labels: string[] };
8074
+ * [Version.V3]: { numbers: number[]; labels: string[]; description: string };
8075
+ * };
8076
+ *
8008
8077
  * const dataModel = DataModel
8009
- * .from<V1>()
8010
- * .migrate((data) => ({ ...data, labels: [] })) // v1 → v2
8011
- * .migrate((data) => ({ ...data, description: '' })) // v2 → v3
8012
- * .create<BlockData>(() => ({ numbers: [], labels: [], description: '' }));
8078
+ * .from<VersionedData>(Version.V1)
8079
+ * .migrate(Version.V2, (data) => ({ ...data, labels: [] }))
8080
+ * .migrate(Version.V3, (data) => ({ ...data, description: '' }))
8081
+ * .recover((version, data) => {
8082
+ * if (version === 'legacy' && typeof data === 'object' && data !== null && 'numbers' in data) {
8083
+ * return { numbers: (data as { numbers: number[] }).numbers, labels: [], description: '' };
8084
+ * }
8085
+ * return defaultRecover(version, data);
8086
+ * })
8087
+ * .create(() => ({ numbers: [], labels: [], description: '' }));
8013
8088
  */
8014
8089
  class DataModel {
8090
+ versionChain;
8015
8091
  steps;
8016
- _initialData;
8017
- constructor(steps, initialData) {
8092
+ initialDataFn;
8093
+ recoverFn;
8094
+ constructor(versionChain, steps, initialData, recover = defaultRecover) {
8095
+ if (versionChain.length === 0) {
8096
+ throw new Error('DataModel requires at least one version key');
8097
+ }
8098
+ this.versionChain = versionChain;
8018
8099
  this.steps = steps;
8019
- this._initialData = initialData;
8100
+ this.initialDataFn = initialData;
8101
+ this.recoverFn = recover;
8020
8102
  }
8021
8103
  /** Start a migration chain from an initial type */
8022
- static from() {
8023
- return DataModelBuilder.from();
8104
+ static from(initialVersion) {
8105
+ return DataModelBuilder.from(initialVersion);
8024
8106
  }
8025
8107
  /** Create a data model with just initial data (no migrations) */
8026
- static create(initialData) {
8027
- return new DataModel([], initialData);
8108
+ static create(initialData, version = DATA_MODEL_DEFAULT_VERSION) {
8109
+ return new DataModel([version], [], initialData);
8028
8110
  }
8029
8111
  /** Create from builder (internal use) */
8030
- static _fromBuilder(steps, initialData) {
8031
- return new DataModel(steps, initialData);
8112
+ static _fromBuilder(versionChain, steps, initialData, recover) {
8113
+ return new DataModel(versionChain, steps, initialData, recover);
8032
8114
  }
8033
8115
  /**
8034
- * Latest version number.
8035
- * Version 1 = initial state, each migration adds 1.
8116
+ * Latest version key.
8036
8117
  */
8037
8118
  get version() {
8038
- return this.steps.length + 1;
8119
+ return this.versionChain[this.versionChain.length - 1];
8039
8120
  }
8040
8121
  /** Number of migration steps */
8041
8122
  get migrationCount() {
@@ -8043,43 +8124,52 @@
8043
8124
  }
8044
8125
  /** Get initial data */
8045
8126
  initialData() {
8046
- return this._initialData();
8127
+ return this.initialDataFn();
8047
8128
  }
8048
8129
  /** Get default data wrapped with current version */
8049
8130
  getDefaultData() {
8050
- return { version: this.version, data: this._initialData() };
8131
+ return makeDataVersioned(this.version, this.initialDataFn());
8132
+ }
8133
+ recoverFrom(data, version) {
8134
+ try {
8135
+ return { version: this.version, data: this.recoverFn(version, data) };
8136
+ }
8137
+ catch (error) {
8138
+ if (isDataUnrecoverableError(error)) {
8139
+ return { ...this.getDefaultData(), warning: error.message };
8140
+ }
8141
+ const errorMessage = error instanceof Error ? error.message : String(error);
8142
+ return {
8143
+ ...this.getDefaultData(),
8144
+ warning: `Recover failed for version '${version}': ${errorMessage}`,
8145
+ };
8146
+ }
8051
8147
  }
8052
8148
  /**
8053
- * Upgrade versioned data from any version to the latest.
8149
+ * Migrate versioned data from any version to the latest.
8054
8150
  * Applies only the migrations needed (skips already-applied ones).
8055
8151
  * If a migration fails, returns default data with a warning.
8056
8152
  */
8057
- upgrade(versioned) {
8153
+ migrate(versioned) {
8058
8154
  const { version: fromVersion, data } = versioned;
8059
- if (fromVersion > this.version) {
8060
- throw new Error(`Cannot downgrade from version ${fromVersion} to ${this.version}`);
8061
- }
8062
8155
  if (fromVersion === this.version) {
8063
8156
  return { version: this.version, data: data };
8064
8157
  }
8065
- // Apply migrations starting from (fromVersion - 1) index
8066
- // Version 1 -> no migrations applied yet -> start at index 0
8067
- // Version 2 -> migration[0] already applied -> start at index 1
8068
- const startIndex = fromVersion - 1;
8069
- const migrationsToApply = this.steps.slice(startIndex);
8158
+ const startIndex = this.versionChain.indexOf(fromVersion);
8159
+ if (startIndex < 0) {
8160
+ return this.recoverFrom(data, fromVersion);
8161
+ }
8070
8162
  let currentData = data;
8071
- for (let i = 0; i < migrationsToApply.length; i++) {
8072
- const stepIndex = startIndex + i;
8073
- const fromVer = stepIndex + 1;
8074
- const toVer = stepIndex + 2;
8163
+ for (let i = startIndex; i < this.steps.length; i++) {
8164
+ const step = this.steps[i];
8075
8165
  try {
8076
- currentData = migrationsToApply[i](currentData);
8166
+ currentData = step.migrate(currentData);
8077
8167
  }
8078
8168
  catch (error) {
8079
8169
  const errorMessage = error instanceof Error ? error.message : String(error);
8080
8170
  return {
8081
8171
  ...this.getDefaultData(),
8082
- warning: `Migration v${fromVer}→v${toVer} failed: ${errorMessage}`,
8172
+ warning: `Migration ${step.fromVersion}→${step.toVersion} failed: ${errorMessage}`,
8083
8173
  };
8084
8174
  }
8085
8175
  }
@@ -8091,12 +8181,12 @@
8091
8181
  *
8092
8182
  * All callbacks are prefixed with `__pl_` to indicate internal SDK use:
8093
8183
  * - `__pl_data_initial`: returns initial data for new blocks
8094
- * - `__pl_data_upgrade`: upgrades versioned data from any version to latest
8184
+ * - `__pl_data_migrate`: migrates versioned data from any version to latest
8095
8185
  * - `__pl_storage_initial`: returns initial BlockStorage as JSON string
8096
8186
  */
8097
8187
  registerCallbacks() {
8098
- tryRegisterCallback('__pl_data_initial', () => this._initialData());
8099
- tryRegisterCallback('__pl_data_upgrade', (versioned) => this.upgrade(versioned));
8188
+ tryRegisterCallback('__pl_data_initial', () => this.initialDataFn());
8189
+ tryRegisterCallback('__pl_data_migrate', (versioned) => this.migrate(versioned));
8100
8190
  tryRegisterCallback('__pl_storage_initial', () => {
8101
8191
  const { version, data } = this.getDefaultData();
8102
8192
  const storage = createBlockStorage(data, version);