@milaboratories/milaboratories.ui-examples.model 1.3.21 → 1.4.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.
@@ -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.ui-examples.model@1.3.21 build /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/model
3
+ > @milaboratories/milaboratories.ui-examples.model@1.4.0 build /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/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 3.9s
10
+ created dist, dist in 2.8s
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 5.1s
15
+ created dist in 5.6s
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.ui-examples.model@1.3.21 lint /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/model
3
+ > @milaboratories/milaboratories.ui-examples.model@1.4.0 lint /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/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.ui-examples.model@1.3.21 type-check /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/model
3
+ > @milaboratories/milaboratories.ui-examples.model@1.4.0 type-check /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/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,23 @@
1
1
  # @milaboratories/milaboratories.ui-examples.model
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1694d1a: Platforma API v3
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [1694d1a]
12
+ - @platforma-sdk/model@1.52.0
13
+
14
+ ## 1.3.22
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [38534c5]
19
+ - @platforma-sdk/model@1.51.9
20
+
3
21
  ## 1.3.21
4
22
 
5
23
  ### Patch Changes
package/dist/bundle.js CHANGED
@@ -4,6 +4,86 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["block-model"] = {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
+ /**
8
+ * BlockStorage - Typed storage abstraction for block persistent data.
9
+ *
10
+ * This module provides:
11
+ * - A typed structure for block storage with versioning and plugin support
12
+ * - Utility functions for manipulating storage
13
+ * - Handler interfaces for model-level customization
14
+ *
15
+ * @module block_storage
16
+ */
17
+ // =============================================================================
18
+ // Core Types
19
+ // =============================================================================
20
+ /**
21
+ * Discriminator key for BlockStorage format detection.
22
+ * This unique hash-based key identifies data as BlockStorage vs legacy formats.
23
+ */
24
+ const BLOCK_STORAGE_KEY = '__pl_a7f3e2b9__';
25
+ /**
26
+ * Current BlockStorage schema version.
27
+ * Increment this when the storage structure itself changes (not block state migrations).
28
+ */
29
+ const BLOCK_STORAGE_SCHEMA_VERSION = 'v1';
30
+ /**
31
+ * Type guard to check if a value is a valid BlockStorage object.
32
+ * Checks for the discriminator key and valid schema version.
33
+ */
34
+ function isBlockStorage(value) {
35
+ if (value === null || typeof value !== 'object')
36
+ return false;
37
+ const obj = value;
38
+ const schemaVersion = obj[BLOCK_STORAGE_KEY];
39
+ // Currently only 'v1' is valid, but this allows future versions
40
+ return schemaVersion === 'v1'; // Add more versions as schema evolves
41
+ }
42
+ // =============================================================================
43
+ // Factory Functions
44
+ // =============================================================================
45
+ /**
46
+ * Creates a BlockStorage with the given initial data
47
+ *
48
+ * @param initialData - The initial data value (defaults to empty object)
49
+ * @param version - The initial data version (defaults to 1)
50
+ * @returns A new BlockStorage instance with discriminator key
51
+ */
52
+ function createBlockStorage(initialData = {}, version = 1) {
53
+ return {
54
+ [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,
55
+ __dataVersion: version,
56
+ __data: initialData,
57
+ };
58
+ }
59
+ // =============================================================================
60
+ // Data Access & Update Functions
61
+ // =============================================================================
62
+ /**
63
+ * Gets the data from BlockStorage
64
+ *
65
+ * @param storage - The BlockStorage instance
66
+ * @returns The data value
67
+ */
68
+ function getStorageData(storage) {
69
+ return storage.__data;
70
+ }
71
+ /**
72
+ * Updates the data in BlockStorage (immutable)
73
+ *
74
+ * @param storage - The current BlockStorage
75
+ * @param payload - The update payload with operation and value
76
+ * @returns A new BlockStorage with updated data
77
+ */
78
+ function updateStorageData(storage, payload) {
79
+ switch (payload.operation) {
80
+ case 'update-data':
81
+ return { ...storage, __data: payload.value };
82
+ default:
83
+ throw new Error(`Unknown storage operation: ${payload.operation}`);
84
+ }
85
+ }
86
+
7
87
  //
8
88
  // Helpers
9
89
  //
@@ -6108,10 +6188,15 @@
6108
6188
  }
6109
6189
  return result;
6110
6190
  };
6111
- // Checks if a result has all unique labels
6112
- const hasUniqueLabels = (result) => result !== undefined && new Set(result.map((c) => c.label)).size === values.length;
6191
+ const countUniqueLabels = (result) => result === undefined ? 0 : new Set(result.map((c) => c.label)).size;
6113
6192
  // Post-processing: try removing types one by one (lowest importance first) to minimize the label set
6193
+ // Accepts removal if it doesn't decrease the number of unique labels (cardinality)
6114
6194
  const minimizeTypeSet = (typeSet) => {
6195
+ const initialResult = calculate(typeSet);
6196
+ if (initialResult === undefined) {
6197
+ return typeSet;
6198
+ }
6199
+ const currentCardinality = countUniqueLabels(initialResult);
6115
6200
  // Get types sorted by importance ascending (lowest first), excluding forced elements
6116
6201
  const removableSorted = [...typeSet]
6117
6202
  .filter((t) => !forceTraceElements?.has(t.split('@')[0])
@@ -6121,7 +6206,7 @@
6121
6206
  const reducedSet = new Set(typeSet);
6122
6207
  reducedSet.delete(typeToRemove);
6123
6208
  const candidateResult = calculate(reducedSet);
6124
- if (hasUniqueLabels(candidateResult)) {
6209
+ if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= currentCardinality) {
6125
6210
  typeSet.delete(typeToRemove);
6126
6211
  }
6127
6212
  }
@@ -6152,7 +6237,7 @@
6152
6237
  if (additionalType >= 0)
6153
6238
  currentSet.add(mainTypes[additionalType]);
6154
6239
  const candidateResult = calculate(currentSet);
6155
- if (hasUniqueLabels(candidateResult)) {
6240
+ if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {
6156
6241
  minimizeTypeSet(currentSet);
6157
6242
  return calculate(currentSet);
6158
6243
  }
@@ -7268,28 +7353,19 @@
7268
7353
  }
7269
7354
  }
7270
7355
  /** Main entry point to the API available within model lambdas (like outputs, sections, etc..) */
7271
- class RenderCtx {
7356
+ class RenderCtxBase {
7272
7357
  ctx;
7273
7358
  constructor() {
7274
7359
  this.ctx = getCfgRenderCtx();
7275
7360
  }
7276
- _argsCache;
7277
- get args() {
7278
- if (this._argsCache === undefined) {
7279
- const raw = this.ctx.args;
7361
+ _dataCache;
7362
+ get data() {
7363
+ if (this._dataCache === undefined) {
7364
+ const raw = this.ctx.data;
7280
7365
  const value = typeof raw === 'function' ? raw() : raw;
7281
- this._argsCache = { v: JSON.parse(value) };
7366
+ this._dataCache = { v: value ? JSON.parse(value) : {} };
7282
7367
  }
7283
- return this._argsCache.v;
7284
- }
7285
- _uiStateCache;
7286
- get uiState() {
7287
- if (this._uiStateCache === undefined) {
7288
- const raw = this.ctx.uiState;
7289
- const value = typeof raw === 'function' ? raw() : raw;
7290
- this._uiStateCache = { v: value ? JSON.parse(value) : {} };
7291
- }
7292
- return this._uiStateCache.v;
7368
+ return this._dataCache.v;
7293
7369
  }
7294
7370
  // lazy rendering because this feature is rarely used
7295
7371
  _activeArgsCache;
@@ -7400,8 +7476,29 @@
7400
7476
  this.ctx.logError(msg);
7401
7477
  }
7402
7478
  }
7479
+ /** Render context for legacy v1/v2 blocks - provides backward compatibility */
7480
+ class RenderCtxLegacy extends RenderCtxBase {
7481
+ _argsCache;
7482
+ get args() {
7483
+ if (this._argsCache === undefined) {
7484
+ const raw = this.ctx.args;
7485
+ const value = typeof raw === 'function' ? raw() : raw;
7486
+ this._argsCache = { v: JSON.parse(value) };
7487
+ }
7488
+ return this._argsCache.v;
7489
+ }
7490
+ _uiStateCache;
7491
+ get uiState() {
7492
+ if (this._uiStateCache === undefined) {
7493
+ const raw = this.ctx.uiState;
7494
+ const value = typeof raw === 'function' ? raw() : raw;
7495
+ this._uiStateCache = { v: value ? JSON.parse(value) : {} };
7496
+ }
7497
+ return this._uiStateCache.v;
7498
+ }
7499
+ }
7403
7500
 
7404
- var version = "1.51.6";
7501
+ var version = "1.52.0";
7405
7502
 
7406
7503
  const PlatformaSDKVersion = version;
7407
7504
 
@@ -7445,7 +7542,7 @@
7445
7542
  output(key, cfgOrRf, flags = {}) {
7446
7543
  if (typeof cfgOrRf === 'function') {
7447
7544
  const handle = `output#${key}`;
7448
- tryRegisterCallback(handle, () => cfgOrRf(new RenderCtx()));
7545
+ tryRegisterCallback(handle, () => cfgOrRf(new RenderCtxLegacy()));
7449
7546
  return new BlockModel({
7450
7547
  ...this.config,
7451
7548
  outputs: {
@@ -7482,7 +7579,7 @@
7482
7579
  }
7483
7580
  argsValid(cfgOrRf) {
7484
7581
  if (typeof cfgOrRf === 'function') {
7485
- tryRegisterCallback('inputsValid', () => cfgOrRf(new RenderCtx()));
7582
+ tryRegisterCallback('inputsValid', () => cfgOrRf(new RenderCtxLegacy()));
7486
7583
  return new BlockModel({
7487
7584
  ...this.config,
7488
7585
  inputsValid: {
@@ -7503,7 +7600,7 @@
7503
7600
  return this.sections(getImmediate(arrOrCfgOrRf));
7504
7601
  }
7505
7602
  else if (typeof arrOrCfgOrRf === 'function') {
7506
- tryRegisterCallback('sections', () => arrOrCfgOrRf(new RenderCtx()));
7603
+ tryRegisterCallback('sections', () => arrOrCfgOrRf(new RenderCtxLegacy()));
7507
7604
  return new BlockModel({
7508
7605
  ...this.config,
7509
7606
  sections: {
@@ -7521,7 +7618,7 @@
7521
7618
  }
7522
7619
  /** Sets a rendering function to derive block title, shown for the block in the left blocks-overview panel. */
7523
7620
  title(rf) {
7524
- tryRegisterCallback('title', () => rf(new RenderCtx()));
7621
+ tryRegisterCallback('title', () => rf(new RenderCtxLegacy()));
7525
7622
  return new BlockModel({
7526
7623
  ...this.config,
7527
7624
  title: {
@@ -7531,7 +7628,7 @@
7531
7628
  });
7532
7629
  }
7533
7630
  subtitle(rf) {
7534
- tryRegisterCallback('subtitle', () => rf(new RenderCtx()));
7631
+ tryRegisterCallback('subtitle', () => rf(new RenderCtxLegacy()));
7535
7632
  return new BlockModel({
7536
7633
  ...this.config,
7537
7634
  subtitle: {
@@ -7541,7 +7638,7 @@
7541
7638
  });
7542
7639
  }
7543
7640
  tags(rf) {
7544
- tryRegisterCallback('tags', () => rf(new RenderCtx()));
7641
+ tryRegisterCallback('tags', () => rf(new RenderCtxLegacy()));
7545
7642
  return new BlockModel({
7546
7643
  ...this.config,
7547
7644
  tags: {
@@ -7608,7 +7705,10 @@
7608
7705
  if (this.config.initialArgs === undefined)
7609
7706
  throw new Error('Initial arguments not set.');
7610
7707
  const config = {
7708
+ v4: undefined,
7611
7709
  v3: {
7710
+ configVersion: 3,
7711
+ modelAPIVersion: 1,
7612
7712
  sdkVersion: PlatformaSDKVersion,
7613
7713
  renderingMode: this.config.renderingMode,
7614
7714
  initialArgs: this.config.initialArgs,
@@ -7648,6 +7748,262 @@
7648
7748
  }
7649
7749
  }
7650
7750
 
7751
+ /**
7752
+ * BlockStorage VM Integration - Internal module for VM-based storage operations.
7753
+ *
7754
+ * This module auto-registers internal callbacks that the middle layer can invoke
7755
+ * to perform storage transformations. Block developers never interact with these
7756
+ * directly - they only see `state`.
7757
+ *
7758
+ * Registered callbacks (all prefixed with `__pl_` for internal SDK use):
7759
+ * - `__pl_storage_normalize`: (rawStorage) => { storage, data }
7760
+ * - `__pl_storage_applyUpdate`: (currentStorageJson, payload) => updatedStorageJson
7761
+ * - `__pl_storage_getInfo`: (rawStorage) => JSON string with storage info
7762
+ * - `__pl_storage_migrate`: (currentStorageJson) => MigrationResult
7763
+ * - `__pl_args_derive`: (storageJson) => ArgsDeriveResult
7764
+ * - `__pl_prerunArgs_derive`: (storageJson) => ArgsDeriveResult
7765
+ *
7766
+ * Callbacks registered by DataModel.registerCallbacks():
7767
+ * - `__pl_data_initial`: () => initial data
7768
+ * - `__pl_data_upgrade`: (versioned) => UpgradeResult
7769
+ * - `__pl_storage_initial`: () => initial BlockStorage as JSON string
7770
+ *
7771
+ * @module block_storage_vm
7772
+ * @internal
7773
+ */
7774
+ /**
7775
+ * Normalizes raw storage data and extracts state.
7776
+ * Handles all formats:
7777
+ * - New BlockStorage format (has discriminator)
7778
+ * - Legacy V1/V2 format ({ args, uiState })
7779
+ * - Raw V3 state (any other format)
7780
+ *
7781
+ * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)
7782
+ * @returns Object with normalized storage and extracted state
7783
+ */
7784
+ function normalizeStorage(rawStorage) {
7785
+ // Handle undefined/null
7786
+ if (rawStorage === undefined || rawStorage === null) {
7787
+ const storage = createBlockStorage({});
7788
+ return { storage, data: {} };
7789
+ }
7790
+ // Parse JSON string if needed
7791
+ let parsed = rawStorage;
7792
+ if (typeof rawStorage === 'string') {
7793
+ try {
7794
+ parsed = JSON.parse(rawStorage);
7795
+ }
7796
+ catch {
7797
+ // If parsing fails, treat string as the data
7798
+ const storage = createBlockStorage(rawStorage);
7799
+ return { storage, data: rawStorage };
7800
+ }
7801
+ }
7802
+ // Check for BlockStorage format (has discriminator)
7803
+ if (isBlockStorage(parsed)) {
7804
+ return { storage: parsed, data: getStorageData(parsed) };
7805
+ }
7806
+ // Check for legacy V1/V2 format: { args, uiState }
7807
+ if (isLegacyModelV1ApiFormat(parsed)) {
7808
+ // For legacy format, the whole object IS the data
7809
+ const storage = createBlockStorage(parsed);
7810
+ return { storage, data: parsed };
7811
+ }
7812
+ // Raw V3 data - wrap it
7813
+ const storage = createBlockStorage(parsed);
7814
+ return { storage, data: parsed };
7815
+ }
7816
+ /**
7817
+ * Applies a state update to existing storage.
7818
+ * Used when setData is called from the frontend.
7819
+ *
7820
+ * @param currentStorageJson - Current storage as JSON string (must be defined)
7821
+ * @param newData - New data from application
7822
+ * @returns Updated storage as JSON string
7823
+ */
7824
+ function applyStorageUpdate(currentStorageJson, payload) {
7825
+ const { storage: currentStorage } = normalizeStorage(currentStorageJson);
7826
+ // Update data while preserving other storage fields (version, plugins)
7827
+ const updatedStorage = updateStorageData(currentStorage, payload);
7828
+ return JSON.stringify(updatedStorage);
7829
+ }
7830
+ /**
7831
+ * Checks if data is in legacy Model API v1 format.
7832
+ * Legacy format has { args, uiState? } at top level without the BlockStorage discriminator.
7833
+ */
7834
+ function isLegacyModelV1ApiFormat(data) {
7835
+ if (data === null || typeof data !== 'object')
7836
+ return false;
7837
+ if (isBlockStorage(data))
7838
+ return false;
7839
+ const obj = data;
7840
+ return 'args' in obj;
7841
+ }
7842
+ // =============================================================================
7843
+ // Auto-register internal callbacks when module is loaded in VM
7844
+ // =============================================================================
7845
+ // Register normalize callback
7846
+ tryRegisterCallback('__pl_storage_normalize', (rawStorage) => {
7847
+ return normalizeStorage(rawStorage);
7848
+ });
7849
+ // Register apply update callback (requires existing storage)
7850
+ tryRegisterCallback('__pl_storage_applyUpdate', (currentStorageJson, payload) => {
7851
+ return applyStorageUpdate(currentStorageJson, payload);
7852
+ });
7853
+ /**
7854
+ * Gets storage info from raw storage data.
7855
+ * Returns structured info about the storage state.
7856
+ *
7857
+ * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)
7858
+ * @returns JSON string with storage info
7859
+ */
7860
+ function getStorageInfo(rawStorage) {
7861
+ const { storage } = normalizeStorage(rawStorage);
7862
+ const info = {
7863
+ dataVersion: storage.__dataVersion,
7864
+ };
7865
+ return JSON.stringify(info);
7866
+ }
7867
+ // Register get info callback
7868
+ tryRegisterCallback('__pl_storage_getInfo', (rawStorage) => {
7869
+ return getStorageInfo(rawStorage);
7870
+ });
7871
+ /**
7872
+ * Runs storage migration using the DataModel's upgrade callback.
7873
+ * This is the main entry point for the middle layer to trigger migrations.
7874
+ *
7875
+ * Uses the '__pl_data_upgrade' callback registered by DataModel.registerCallbacks() which:
7876
+ * - Handles all migration logic internally
7877
+ * - Returns { version, data, warning? } - warning present if reset to initial data
7878
+ *
7879
+ * @param currentStorageJson - Current storage as JSON string (or undefined)
7880
+ * @returns MigrationResult
7881
+ */
7882
+ function migrateStorage(currentStorageJson) {
7883
+ // Get the callback registry context
7884
+ const ctx = tryGetCfgRenderCtx();
7885
+ if (ctx === undefined) {
7886
+ return { error: 'Not in config rendering context' };
7887
+ }
7888
+ // Normalize storage to get current data and version
7889
+ const { storage: currentStorage, data: currentData } = normalizeStorage(currentStorageJson);
7890
+ const currentVersion = currentStorage.__dataVersion;
7891
+ // Helper to create storage with given data and version
7892
+ const createStorageJson = (data, version) => {
7893
+ return JSON.stringify({
7894
+ ...currentStorage,
7895
+ __dataVersion: version,
7896
+ __data: data,
7897
+ });
7898
+ };
7899
+ // Get the upgrade callback (registered by DataModel.registerCallbacks())
7900
+ const upgradeCallback = ctx.callbackRegistry['__pl_data_upgrade'];
7901
+ if (typeof upgradeCallback !== 'function') {
7902
+ return { error: '__pl_data_upgrade callback not found (DataModel not registered)' };
7903
+ }
7904
+ // Call the migrator's upgrade function
7905
+ let result;
7906
+ try {
7907
+ result = upgradeCallback({ version: currentVersion, data: currentData });
7908
+ }
7909
+ catch (e) {
7910
+ const errorMsg = e instanceof Error ? e.message : String(e);
7911
+ return { error: `upgrade() threw: ${errorMsg}` };
7912
+ }
7913
+ // Build info message
7914
+ const info = result.version === currentVersion
7915
+ ? `No migration needed (v${currentVersion})`
7916
+ : result.warning
7917
+ ? `Reset to initial data (v${result.version})`
7918
+ : `Migrated v${currentVersion}→v${result.version}`;
7919
+ return {
7920
+ newStorageJson: createStorageJson(result.data, result.version),
7921
+ info,
7922
+ warn: result.warning,
7923
+ };
7924
+ }
7925
+ // Register migrate callback
7926
+ tryRegisterCallback('__pl_storage_migrate', (currentStorageJson) => {
7927
+ return migrateStorage(currentStorageJson);
7928
+ });
7929
+ /**
7930
+ * Derives args from storage using the registered 'args' callback.
7931
+ * This extracts data from storage and passes it to the block's args() function.
7932
+ *
7933
+ * @param storageJson - Storage as JSON string
7934
+ * @returns ArgsDeriveResult with derived args or error
7935
+ */
7936
+ function deriveArgsFromStorage(storageJson) {
7937
+ const ctx = tryGetCfgRenderCtx();
7938
+ if (ctx === undefined) {
7939
+ return { error: 'Not in config rendering context' };
7940
+ }
7941
+ // Extract data from storage
7942
+ const { data } = normalizeStorage(storageJson);
7943
+ // Get the args callback (registered by BlockModelV3.args())
7944
+ const argsCallback = ctx.callbackRegistry['args'];
7945
+ if (typeof argsCallback !== 'function') {
7946
+ return { error: 'args callback not found' };
7947
+ }
7948
+ // Call the args callback with extracted data
7949
+ try {
7950
+ const result = argsCallback(data);
7951
+ return { value: result };
7952
+ }
7953
+ catch (e) {
7954
+ const errorMsg = e instanceof Error ? e.message : String(e);
7955
+ return { error: `args() threw: ${errorMsg}` };
7956
+ }
7957
+ }
7958
+ // Register args derivation callback
7959
+ tryRegisterCallback('__pl_args_derive', (storageJson) => {
7960
+ return deriveArgsFromStorage(storageJson);
7961
+ });
7962
+ /**
7963
+ * Derives prerunArgs from storage using the registered 'prerunArgs' callback.
7964
+ * Falls back to 'args' callback if 'prerunArgs' is not defined.
7965
+ *
7966
+ * @param storageJson - Storage as JSON string
7967
+ * @returns ArgsDeriveResult with derived prerunArgs or error
7968
+ */
7969
+ function derivePrerunArgsFromStorage(storageJson) {
7970
+ const ctx = tryGetCfgRenderCtx();
7971
+ if (ctx === undefined) {
7972
+ return { error: 'Not in config rendering context' };
7973
+ }
7974
+ // Extract data from storage
7975
+ const { data } = normalizeStorage(storageJson);
7976
+ // Try prerunArgs callback first
7977
+ const prerunArgsCallback = ctx.callbackRegistry['prerunArgs'];
7978
+ if (typeof prerunArgsCallback === 'function') {
7979
+ try {
7980
+ const result = prerunArgsCallback(data);
7981
+ return { value: result };
7982
+ }
7983
+ catch (e) {
7984
+ const errorMsg = e instanceof Error ? e.message : String(e);
7985
+ return { error: `prerunArgs() threw: ${errorMsg}` };
7986
+ }
7987
+ }
7988
+ // Fall back to args callback
7989
+ const argsCallback = ctx.callbackRegistry['args'];
7990
+ if (typeof argsCallback !== 'function') {
7991
+ return { error: 'args callback not found (fallback from missing prerunArgs)' };
7992
+ }
7993
+ try {
7994
+ const result = argsCallback(data);
7995
+ return { value: result };
7996
+ }
7997
+ catch (e) {
7998
+ const errorMsg = e instanceof Error ? e.message : String(e);
7999
+ return { error: `args() threw (fallback): ${errorMsg}` };
8000
+ }
8001
+ }
8002
+ // Register prerunArgs derivation callback
8003
+ tryRegisterCallback('__pl_prerunArgs_derive', (storageJson) => {
8004
+ return derivePrerunArgsFromStorage(storageJson);
8005
+ });
8006
+
7651
8007
  function identity(x) {
7652
8008
  return x;
7653
8009
  }
@@ -8307,7 +8663,7 @@
8307
8663
  },
8308
8664
  ];
8309
8665
  })
8310
- .done(); // api version 2
8666
+ .done(2); // api version 2
8311
8667
 
8312
8668
  exports.$BlockArgs = $BlockArgs;
8313
8669
  exports.ImportFileHandleSchema = ImportFileHandleSchema;