@platforma-sdk/model 1.63.0 → 1.63.12

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 (334) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +12 -22
  2. package/dist/_virtual/_rolldown/runtime.js +6 -11
  3. package/dist/annotations/converter.cjs +4 -5
  4. package/dist/annotations/converter.cjs.map +1 -1
  5. package/dist/annotations/converter.d.ts.map +1 -0
  6. package/dist/annotations/converter.js +1 -2
  7. package/dist/annotations/converter.js.map +1 -1
  8. package/dist/annotations/index.cjs +1 -1
  9. package/dist/annotations/index.js +1 -1
  10. package/dist/annotations/types.d.ts +0 -1
  11. package/dist/annotations/types.d.ts.map +1 -0
  12. package/dist/bconfig/index.cjs +2 -2
  13. package/dist/bconfig/index.js +2 -2
  14. package/dist/bconfig/lambdas.d.ts +0 -1
  15. package/dist/bconfig/lambdas.d.ts.map +1 -0
  16. package/dist/bconfig/normalization.cjs +4 -5
  17. package/dist/bconfig/normalization.cjs.map +1 -1
  18. package/dist/bconfig/normalization.d.ts.map +1 -0
  19. package/dist/bconfig/normalization.js +1 -2
  20. package/dist/bconfig/normalization.js.map +1 -1
  21. package/dist/bconfig/types.cjs +1 -2
  22. package/dist/bconfig/types.cjs.map +1 -1
  23. package/dist/bconfig/types.d.ts +0 -1
  24. package/dist/bconfig/types.d.ts.map +1 -0
  25. package/dist/bconfig/types.js +1 -1
  26. package/dist/bconfig/util.d.ts.map +1 -0
  27. package/dist/bconfig/v3.d.ts.map +1 -0
  28. package/dist/block_api_v1.d.ts.map +1 -0
  29. package/dist/block_api_v2.d.ts.map +1 -0
  30. package/dist/block_api_v3.d.ts.map +1 -0
  31. package/dist/block_migrations.cjs +2 -3
  32. package/dist/block_migrations.cjs.map +1 -1
  33. package/dist/block_migrations.d.ts.map +1 -0
  34. package/dist/block_migrations.js +1 -2
  35. package/dist/block_migrations.js.map +1 -1
  36. package/dist/block_model.cjs +16 -17
  37. package/dist/block_model.cjs.map +1 -1
  38. package/dist/block_model.d.ts +0 -2
  39. package/dist/block_model.d.ts.map +1 -0
  40. package/dist/block_model.js +4 -5
  41. package/dist/block_model.js.map +1 -1
  42. package/dist/block_model_legacy.cjs +10 -11
  43. package/dist/block_model_legacy.cjs.map +1 -1
  44. package/dist/block_model_legacy.d.ts +0 -3
  45. package/dist/block_model_legacy.d.ts.map +1 -0
  46. package/dist/block_model_legacy.js +1 -2
  47. package/dist/block_model_legacy.js.map +1 -1
  48. package/dist/block_state_patch.d.ts.map +1 -0
  49. package/dist/block_state_util.cjs +1 -2
  50. package/dist/block_state_util.cjs.map +1 -1
  51. package/dist/block_state_util.d.ts.map +1 -0
  52. package/dist/block_state_util.js +1 -1
  53. package/dist/block_state_util.js.map +1 -1
  54. package/dist/block_storage.cjs +5 -12
  55. package/dist/block_storage.cjs.map +1 -1
  56. package/dist/block_storage.d.ts.map +1 -0
  57. package/dist/block_storage.js +5 -11
  58. package/dist/block_storage.js.map +1 -1
  59. package/dist/block_storage_callbacks.cjs +4 -5
  60. package/dist/block_storage_callbacks.cjs.map +1 -1
  61. package/dist/block_storage_callbacks.js +3 -4
  62. package/dist/block_storage_callbacks.js.map +1 -1
  63. package/dist/block_storage_facade.cjs +2 -3
  64. package/dist/block_storage_facade.cjs.map +1 -1
  65. package/dist/block_storage_facade.d.ts +0 -1
  66. package/dist/block_storage_facade.d.ts.map +1 -0
  67. package/dist/block_storage_facade.js +1 -2
  68. package/dist/block_storage_facade.js.map +1 -1
  69. package/dist/columns/column_collection_builder.cjs +6 -7
  70. package/dist/columns/column_collection_builder.cjs.map +1 -1
  71. package/dist/columns/column_collection_builder.d.ts.map +1 -0
  72. package/dist/columns/column_collection_builder.js +1 -2
  73. package/dist/columns/column_collection_builder.js.map +1 -1
  74. package/dist/columns/column_selector.cjs +1 -2
  75. package/dist/columns/column_selector.cjs.map +1 -1
  76. package/dist/columns/column_selector.d.ts.map +1 -0
  77. package/dist/columns/column_selector.js +1 -1
  78. package/dist/columns/column_selector.js.map +1 -1
  79. package/dist/columns/column_snapshot.cjs +1 -2
  80. package/dist/columns/column_snapshot.cjs.map +1 -1
  81. package/dist/columns/column_snapshot.d.ts.map +1 -0
  82. package/dist/columns/column_snapshot.js +1 -1
  83. package/dist/columns/column_snapshot_provider.cjs +1 -2
  84. package/dist/columns/column_snapshot_provider.cjs.map +1 -1
  85. package/dist/columns/column_snapshot_provider.d.ts.map +1 -0
  86. package/dist/columns/column_snapshot_provider.js +1 -1
  87. package/dist/columns/column_snapshot_provider.js.map +1 -1
  88. package/dist/columns/ctx_column_sources.cjs +3 -4
  89. package/dist/columns/ctx_column_sources.cjs.map +1 -1
  90. package/dist/columns/ctx_column_sources.d.ts +0 -1
  91. package/dist/columns/ctx_column_sources.d.ts.map +1 -0
  92. package/dist/columns/ctx_column_sources.js +1 -2
  93. package/dist/columns/ctx_column_sources.js.map +1 -1
  94. package/dist/columns/index.cjs +5 -5
  95. package/dist/columns/index.js +5 -5
  96. package/dist/components/PFrameForGraphs.cjs +4 -5
  97. package/dist/components/PFrameForGraphs.cjs.map +1 -1
  98. package/dist/components/PFrameForGraphs.d.ts +0 -1
  99. package/dist/components/PFrameForGraphs.d.ts.map +1 -0
  100. package/dist/components/PFrameForGraphs.js +2 -3
  101. package/dist/components/PFrameForGraphs.js.map +1 -1
  102. package/dist/components/PlAnnotations/filter.d.ts.map +1 -0
  103. package/dist/components/PlAnnotations/filters_ui.cjs +1 -2
  104. package/dist/components/PlAnnotations/filters_ui.cjs.map +1 -1
  105. package/dist/components/PlAnnotations/filters_ui.d.ts +0 -2
  106. package/dist/components/PlAnnotations/filters_ui.d.ts.map +1 -0
  107. package/dist/components/PlAnnotations/filters_ui.js +1 -1
  108. package/dist/components/PlAnnotations/filters_ui.js.map +1 -1
  109. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +9 -10
  110. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
  111. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +0 -1
  112. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts.map +1 -0
  113. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +1 -2
  114. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
  115. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +14 -15
  116. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  117. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +0 -2
  118. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -0
  119. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +1 -2
  120. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  121. package/dist/components/PlDataTable/createPlDataTable/index.cjs +3 -4
  122. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
  123. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +0 -1
  124. package/dist/components/PlDataTable/createPlDataTable/index.d.ts.map +1 -0
  125. package/dist/components/PlDataTable/createPlDataTable/index.js +1 -2
  126. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
  127. package/dist/components/PlDataTable/createPlDataTableSheet.cjs +1 -2
  128. package/dist/components/PlDataTable/createPlDataTableSheet.cjs.map +1 -1
  129. package/dist/components/PlDataTable/createPlDataTableSheet.d.ts +0 -1
  130. package/dist/components/PlDataTable/createPlDataTableSheet.d.ts.map +1 -0
  131. package/dist/components/PlDataTable/createPlDataTableSheet.js +1 -1
  132. package/dist/components/PlDataTable/index.cjs +5 -5
  133. package/dist/components/PlDataTable/index.js +5 -5
  134. package/dist/components/PlDataTable/labels.cjs +4 -5
  135. package/dist/components/PlDataTable/labels.cjs.map +1 -1
  136. package/dist/components/PlDataTable/labels.js +1 -2
  137. package/dist/components/PlDataTable/labels.js.map +1 -1
  138. package/dist/components/PlDataTable/state-migration.cjs +4 -5
  139. package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
  140. package/dist/components/PlDataTable/state-migration.d.ts.map +1 -0
  141. package/dist/components/PlDataTable/state-migration.js +1 -2
  142. package/dist/components/PlDataTable/state-migration.js.map +1 -1
  143. package/dist/components/PlDataTable/typesV4.d.ts.map +1 -0
  144. package/dist/components/PlDataTable/typesV5.d.ts +0 -1
  145. package/dist/components/PlDataTable/typesV5.d.ts.map +1 -0
  146. package/dist/components/PlMultiSequenceAlignment.cjs +2 -3
  147. package/dist/components/PlMultiSequenceAlignment.cjs.map +1 -1
  148. package/dist/components/PlMultiSequenceAlignment.d.ts.map +1 -0
  149. package/dist/components/PlMultiSequenceAlignment.js +1 -2
  150. package/dist/components/PlMultiSequenceAlignment.js.map +1 -1
  151. package/dist/components/PlSelectionModel.cjs +1 -2
  152. package/dist/components/PlSelectionModel.cjs.map +1 -1
  153. package/dist/components/PlSelectionModel.d.ts.map +1 -0
  154. package/dist/components/PlSelectionModel.js +1 -1
  155. package/dist/components/index.cjs +11 -11
  156. package/dist/components/index.d.ts +0 -2
  157. package/dist/components/index.js +10 -10
  158. package/dist/config/actions.cjs +1 -2
  159. package/dist/config/actions.cjs.map +1 -1
  160. package/dist/config/actions.d.ts.map +1 -0
  161. package/dist/config/actions.js +1 -1
  162. package/dist/config/actions_kinds.d.ts.map +1 -0
  163. package/dist/config/index.cjs +1 -1
  164. package/dist/config/index.js +1 -1
  165. package/dist/config/model.d.ts.map +1 -0
  166. package/dist/config/model_meta.d.ts.map +1 -0
  167. package/dist/config/type_engine.d.ts.map +1 -0
  168. package/dist/config/type_util.d.ts.map +1 -0
  169. package/dist/env_value.cjs +1 -2
  170. package/dist/env_value.cjs.map +1 -1
  171. package/dist/env_value.d.ts.map +1 -0
  172. package/dist/env_value.js +1 -1
  173. package/dist/env_value.js.map +1 -1
  174. package/dist/filters/converters/filterToQuery.cjs +3 -4
  175. package/dist/filters/converters/filterToQuery.cjs.map +1 -1
  176. package/dist/filters/converters/filterToQuery.d.ts.map +1 -0
  177. package/dist/filters/converters/filterToQuery.js +1 -2
  178. package/dist/filters/converters/filterToQuery.js.map +1 -1
  179. package/dist/filters/converters/filterUiToExpressionImpl.cjs +3 -4
  180. package/dist/filters/converters/filterUiToExpressionImpl.cjs.map +1 -1
  181. package/dist/filters/converters/filterUiToExpressionImpl.d.ts.map +1 -0
  182. package/dist/filters/converters/filterUiToExpressionImpl.js +1 -2
  183. package/dist/filters/converters/filterUiToExpressionImpl.js.map +1 -1
  184. package/dist/filters/converters/index.cjs +2 -2
  185. package/dist/filters/converters/index.js +2 -2
  186. package/dist/filters/distill.cjs +3 -4
  187. package/dist/filters/distill.cjs.map +1 -1
  188. package/dist/filters/distill.d.ts.map +1 -0
  189. package/dist/filters/distill.js +1 -2
  190. package/dist/filters/distill.js.map +1 -1
  191. package/dist/filters/index.cjs +4 -4
  192. package/dist/filters/index.d.ts +0 -1
  193. package/dist/filters/index.js +3 -3
  194. package/dist/filters/traverse.cjs +1 -2
  195. package/dist/filters/traverse.cjs.map +1 -1
  196. package/dist/filters/traverse.js +1 -1
  197. package/dist/filters/traverse.js.map +1 -1
  198. package/dist/filters/types.d.ts.map +1 -0
  199. package/dist/index.cjs +78 -76
  200. package/dist/index.d.ts +0 -9
  201. package/dist/index.js +3 -6
  202. package/dist/internal.cjs +1 -2
  203. package/dist/internal.cjs.map +1 -1
  204. package/dist/internal.js +1 -1
  205. package/dist/internal.js.map +1 -1
  206. package/dist/labels/derive_distinct_labels.cjs +2 -3
  207. package/dist/labels/derive_distinct_labels.cjs.map +1 -1
  208. package/dist/labels/derive_distinct_labels.d.ts.map +1 -0
  209. package/dist/labels/derive_distinct_labels.js +1 -2
  210. package/dist/labels/derive_distinct_labels.js.map +1 -1
  211. package/dist/labels/index.cjs +2 -2
  212. package/dist/labels/index.js +2 -2
  213. package/dist/labels/write_labels_to_specs.cjs +2 -3
  214. package/dist/labels/write_labels_to_specs.cjs.map +1 -1
  215. package/dist/labels/write_labels_to_specs.d.ts +0 -2
  216. package/dist/labels/write_labels_to_specs.d.ts.map +1 -0
  217. package/dist/labels/write_labels_to_specs.js +1 -2
  218. package/dist/labels/write_labels_to_specs.js.map +1 -1
  219. package/dist/package.cjs +7 -8
  220. package/dist/package.js +2 -2
  221. package/dist/pframe.cjs +2 -3
  222. package/dist/pframe.cjs.map +1 -1
  223. package/dist/pframe.d.ts.map +1 -0
  224. package/dist/pframe.js +1 -2
  225. package/dist/pframe.js.map +1 -1
  226. package/dist/pframe_utils/axes.cjs +2 -3
  227. package/dist/pframe_utils/axes.cjs.map +1 -1
  228. package/dist/pframe_utils/axes.d.ts +0 -1
  229. package/dist/pframe_utils/axes.d.ts.map +1 -0
  230. package/dist/pframe_utils/axes.js +1 -2
  231. package/dist/pframe_utils/axes.js.map +1 -1
  232. package/dist/pframe_utils/columns.cjs +5 -6
  233. package/dist/pframe_utils/columns.cjs.map +1 -1
  234. package/dist/pframe_utils/columns.d.ts +0 -1
  235. package/dist/pframe_utils/columns.d.ts.map +1 -0
  236. package/dist/pframe_utils/columns.js +1 -2
  237. package/dist/pframe_utils/columns.js.map +1 -1
  238. package/dist/pframe_utils/index.cjs +3 -4
  239. package/dist/pframe_utils/index.cjs.map +1 -1
  240. package/dist/pframe_utils/index.d.ts.map +1 -0
  241. package/dist/pframe_utils/index.js +2 -3
  242. package/dist/pframe_utils/index.js.map +1 -1
  243. package/dist/platforma.d.ts.map +1 -0
  244. package/dist/plugin_handle.cjs +1 -2
  245. package/dist/plugin_handle.cjs.map +1 -1
  246. package/dist/plugin_handle.d.ts.map +1 -0
  247. package/dist/plugin_handle.js +1 -1
  248. package/dist/plugin_model.cjs +3 -4
  249. package/dist/plugin_model.cjs.map +1 -1
  250. package/dist/plugin_model.d.ts +0 -1
  251. package/dist/plugin_model.d.ts.map +1 -0
  252. package/dist/plugin_model.js +1 -2
  253. package/dist/plugin_model.js.map +1 -1
  254. package/dist/raw_globals.cjs +3 -4
  255. package/dist/raw_globals.cjs.map +1 -1
  256. package/dist/raw_globals.d.ts.map +1 -0
  257. package/dist/raw_globals.js +1 -2
  258. package/dist/raw_globals.js.map +1 -1
  259. package/dist/ref_util.cjs +3 -4
  260. package/dist/ref_util.cjs.map +1 -1
  261. package/dist/ref_util.d.ts +0 -2
  262. package/dist/ref_util.d.ts.map +1 -0
  263. package/dist/ref_util.js +1 -2
  264. package/dist/ref_util.js.map +1 -1
  265. package/dist/render/accessor.cjs +4 -5
  266. package/dist/render/accessor.cjs.map +1 -1
  267. package/dist/render/accessor.d.ts.map +1 -0
  268. package/dist/render/accessor.js +1 -2
  269. package/dist/render/accessor.js.map +1 -1
  270. package/dist/render/api.cjs +10 -11
  271. package/dist/render/api.cjs.map +1 -1
  272. package/dist/render/api.d.ts +0 -1
  273. package/dist/render/api.d.ts.map +1 -0
  274. package/dist/render/api.js +1 -2
  275. package/dist/render/api.js.map +1 -1
  276. package/dist/render/future.cjs +2 -3
  277. package/dist/render/future.cjs.map +1 -1
  278. package/dist/render/future.d.ts.map +1 -0
  279. package/dist/render/future.js +1 -2
  280. package/dist/render/future.js.map +1 -1
  281. package/dist/render/index.cjs +8 -8
  282. package/dist/render/index.d.ts +1 -2
  283. package/dist/render/index.js +7 -7
  284. package/dist/render/internal.cjs +7 -9
  285. package/dist/render/internal.cjs.map +1 -1
  286. package/dist/render/internal.d.ts.map +1 -0
  287. package/dist/render/internal.js +1 -2
  288. package/dist/render/internal.js.map +1 -1
  289. package/dist/render/traversal_ops.d.ts.map +1 -0
  290. package/dist/render/util/axis_filtering.cjs +1 -2
  291. package/dist/render/util/axis_filtering.cjs.map +1 -1
  292. package/dist/render/util/axis_filtering.d.ts.map +1 -0
  293. package/dist/render/util/axis_filtering.js +1 -1
  294. package/dist/render/util/column_collection.cjs +5 -6
  295. package/dist/render/util/column_collection.cjs.map +1 -1
  296. package/dist/render/util/column_collection.d.ts +0 -1
  297. package/dist/render/util/column_collection.d.ts.map +1 -0
  298. package/dist/render/util/column_collection.js +1 -2
  299. package/dist/render/util/column_collection.js.map +1 -1
  300. package/dist/render/util/index.cjs +4 -4
  301. package/dist/render/util/index.js +4 -4
  302. package/dist/render/util/label.cjs +2 -3
  303. package/dist/render/util/label.cjs.map +1 -1
  304. package/dist/render/util/label.d.ts.map +1 -0
  305. package/dist/render/util/label.js +1 -2
  306. package/dist/render/util/label.js.map +1 -1
  307. package/dist/render/util/pcolumn_data.cjs +9 -10
  308. package/dist/render/util/pcolumn_data.cjs.map +1 -1
  309. package/dist/render/util/pcolumn_data.d.ts.map +1 -0
  310. package/dist/render/util/pcolumn_data.js +7 -8
  311. package/dist/render/util/pcolumn_data.js.map +1 -1
  312. package/dist/render/util/pframe_upgraders.cjs +1 -2
  313. package/dist/render/util/pframe_upgraders.cjs.map +1 -1
  314. package/dist/render/util/pframe_upgraders.js +1 -1
  315. package/dist/render/util/split_selectors.d.ts.map +1 -0
  316. package/dist/services/block_services.cjs +2 -3
  317. package/dist/services/block_services.cjs.map +1 -1
  318. package/dist/services/block_services.d.ts +2 -2
  319. package/dist/services/block_services.d.ts.map +1 -0
  320. package/dist/services/block_services.js +1 -2
  321. package/dist/services/block_services.js.map +1 -1
  322. package/dist/services/index.cjs +2 -2
  323. package/dist/services/index.js +2 -2
  324. package/dist/services/service_bridge.cjs +1 -2
  325. package/dist/services/service_bridge.cjs.map +1 -1
  326. package/dist/services/service_bridge.d.ts.map +1 -0
  327. package/dist/services/service_bridge.js +1 -1
  328. package/dist/services/service_resolve.d.ts.map +1 -0
  329. package/dist/version.cjs +2 -4
  330. package/dist/version.cjs.map +1 -1
  331. package/dist/version.d.ts.map +1 -0
  332. package/dist/version.js +1 -2
  333. package/dist/version.js.map +1 -1
  334. package/package.json +13 -13
@@ -1 +1 @@
1
- {"version":3,"file":"block_storage.js","names":[],"sources":["../src/block_storage.ts"],"sourcesContent":["/**\n * BlockStorage - Typed storage abstraction for block persistent data.\n *\n * This module provides:\n * - A typed structure for block storage with versioning and plugin support\n * - Utility functions for manipulating storage\n * - Handler interfaces for model-level customization\n *\n * @module block_storage\n */\n\nimport type { Branded } from \"@milaboratories/pl-model-common\";\nimport {\n type DataVersioned,\n type TransferRecord,\n isDataUnrecoverableError,\n} from \"./block_migrations\";\nimport type { PluginHandle, PluginFactoryLike, InferFactoryData } from \"./plugin_handle\";\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Discriminator key for BlockStorage format detection.\n * This unique hash-based key identifies data as BlockStorage vs legacy formats.\n */\nexport const BLOCK_STORAGE_KEY = \"__pl_a7f3e2b9__\";\n\n/**\n * Current BlockStorage schema version.\n * Increment this when the storage structure itself changes (not block state migrations).\n */\nexport const BLOCK_STORAGE_SCHEMA_VERSION = \"v1\";\n\n/**\n * Default data version for new blocks without migrations.\n * Unique identifier ensures blocks are created via DataModel API.\n */\nexport const DATA_MODEL_LEGACY_VERSION = \"__pl_v1_d4e8f2a1__\";\n\n/**\n * Type for valid schema versions\n */\nexport type BlockStorageSchemaVersion = \"v1\"; // Add 'v2', 'v3', etc. as schema evolves\n\n/**\n * Branded type for plugin names - globally unique plugin type identifiers.\n * Using a branded type enforces explicit casting (`as PluginName`) which makes\n * it easy to find all plugin name definitions in the codebase and verify uniqueness.\n */\nexport type PluginName = Branded<string, \"PluginName\">;\n\n/**\n * Plugin registry - maps pluginId (unique within a block) to pluginName (globally unique plugin type).\n * Using a Record highlights that pluginIds must be unique within a block.\n */\nexport type PluginRegistry = Record<PluginHandle, PluginName>;\n\n/**\n * Versioned data - used for both block data and plugin data\n */\nexport interface VersionedData<TData = unknown> {\n /** Version of the data, used for migrations */\n __dataVersion: string;\n /** The persistent data */\n __data: TData;\n}\n\n/**\n * Core BlockStorage type that holds:\n * - __pl_a7f3e2b9__: Schema version (discriminator key identifies BlockStorage format)\n * - __dataVersion: Version key for block data migrations\n * - __data: The block's user-facing data (state)\n * - __pluginRegistry: Map from pluginId to pluginName (optional)\n * - __plugins: Plugin-specific data keyed by pluginId (optional)\n */\nexport type BlockStorage<TState = unknown> = {\n /** Schema version - the key itself is the discriminator */\n readonly [BLOCK_STORAGE_KEY]: BlockStorageSchemaVersion;\n /** Registry of plugins: pluginId -> pluginName */\n __pluginRegistry?: PluginRegistry;\n /** Plugin-specific data, keyed by plugin handle */\n __plugins?: Record<PluginHandle, VersionedData<unknown>>;\n} & VersionedData<TState>;\n\n/**\n * Type guard to check if a value is a valid BlockStorage object.\n * Checks for the discriminator key and valid schema version.\n */\nexport function isBlockStorage(value: unknown): value is BlockStorage {\n if (value === null || typeof value !== \"object\") return false;\n const obj = value as Record<string, unknown>;\n const schemaVersion = obj[BLOCK_STORAGE_KEY];\n // Currently only 'v1' is valid, but this allows future versions\n return schemaVersion === \"v1\"; // Add more versions as schema evolves\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Creates a BlockStorage with the given initial data\n *\n * @param initialData - The initial data value (defaults to empty object)\n * @param version - The initial data version key (defaults to DATA_MODEL_LEGACY_VERSION)\n * @returns A new BlockStorage instance with discriminator key\n */\nexport function createBlockStorage<TState = unknown>(\n initialData: TState = {} as TState,\n version: string = DATA_MODEL_LEGACY_VERSION,\n): BlockStorage<TState> {\n return {\n [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,\n __dataVersion: version,\n __data: initialData,\n __pluginRegistry: {},\n __plugins: {},\n };\n}\n\n/**\n * Normalizes raw storage data to BlockStorage format.\n * If the input is already a BlockStorage, returns it as-is (with defaults for missing fields).\n * If the input is legacy format (raw state), wraps it in BlockStorage structure.\n *\n * @param raw - Raw storage data (may be legacy format or BlockStorage)\n * @returns Normalized BlockStorage\n */\nexport function normalizeBlockStorage<TState = unknown>(raw: unknown): BlockStorage<TState> {\n if (isBlockStorage(raw)) {\n const storage = raw as BlockStorage<TState>;\n return {\n ...storage,\n // Fix for early released version where __dataVersion was a number\n __dataVersion:\n typeof storage.__dataVersion === \"number\"\n ? DATA_MODEL_LEGACY_VERSION\n : storage.__dataVersion,\n // Ensure plugin fields have defaults\n __pluginRegistry: storage.__pluginRegistry ?? {},\n __plugins: storage.__plugins ?? {},\n };\n }\n // Legacy format: raw is the state directly\n return createBlockStorage(raw as TState);\n}\n\n// =============================================================================\n// Data Access & Update Functions\n// =============================================================================\n\n/**\n * Gets the data from BlockStorage\n *\n * @param storage - The BlockStorage instance\n * @returns The data value\n */\nexport function getStorageData<TState>(storage: BlockStorage<TState>): TState {\n return storage.__data;\n}\n\n/**\n * Derives data from raw block storage.\n * This function is meant to be called from sdk/ui-vue to extract\n * user-facing data from the raw storage returned by the middle layer.\n *\n * The middle layer returns raw storage (opaque to it), and the UI\n * uses this function to derive the actual data value.\n *\n * @param rawStorage - Raw storage data from middle layer (may be any format)\n * @returns The extracted data value, or undefined if storage is undefined/null\n */\nexport function deriveDataFromStorage<TData = unknown>(rawStorage: unknown): TData {\n // Normalize to BlockStorage format (handles legacy formats too)\n const storage = normalizeBlockStorage<TData>(rawStorage);\n return getStorageData(storage);\n}\n\n/** Payload for storage mutation operations. SDK defines specific operations. */\nexport type MutateStoragePayload<T = unknown> =\n | { operation: \"update-block-data\"; value: T }\n | { operation: \"update-plugin-data\"; pluginId: PluginHandle; value: unknown };\n\n/**\n * Updates the data in BlockStorage (immutable)\n *\n * @param storage - The current BlockStorage\n * @param payload - The update payload with operation and value\n * @returns A new BlockStorage with updated data\n */\nexport function updateStorageData<TValue = unknown>(\n storage: BlockStorage<TValue>,\n payload: MutateStoragePayload<TValue>,\n): BlockStorage<TValue> {\n switch (payload.operation) {\n case \"update-block-data\":\n return { ...storage, __data: payload.value };\n case \"update-plugin-data\": {\n const { pluginId, value } = payload;\n const currentPlugins = storage.__plugins ?? {};\n const existingEntry = currentPlugins[pluginId];\n const version = existingEntry?.__dataVersion ?? DATA_MODEL_LEGACY_VERSION;\n return {\n ...storage,\n __plugins: {\n ...currentPlugins,\n [pluginId]: {\n __dataVersion: version,\n __data: value,\n },\n },\n };\n }\n default:\n throw new Error(`Unknown storage operation: ${(payload as { operation: string }).operation}`);\n }\n}\n\n// =============================================================================\n// Atomic Migration\n// =============================================================================\n\n/**\n * Result of a successful atomic migration.\n */\nexport interface MigrationSuccess<TState> {\n success: true;\n /** The fully migrated storage - commit this to persist */\n storage: BlockStorage<TState>;\n}\n\n/**\n * Result of a failed atomic migration.\n * The original storage is untouched - user must choose to abort or reset.\n */\nexport interface MigrationFailure {\n success: false;\n /** Description of what failed */\n error: string;\n /** Which step failed: 'block' or pluginId */\n failedAt: string;\n}\n\nexport type MigrationResult<TState> = MigrationSuccess<TState> | MigrationFailure;\n\n/**\n * Configuration for atomic block storage migration.\n * Callbacks use DataVersioned format (the DataModel API format).\n * Conversion to internal VersionedData format is handled by migrateBlockStorage().\n */\nexport interface MigrateBlockStorageConfig {\n /** Migrate block data from any version to latest. Returns migrated data and transfers. */\n migrateBlockData: (versioned: DataVersioned<unknown>) => DataVersioned<unknown> & {\n transfers: TransferRecord;\n };\n /** Migrate each plugin's data. Return undefined to remove the plugin. Throws on failure. */\n migratePluginData: (\n handle: PluginHandle,\n versioned: DataVersioned<unknown>,\n ) => DataVersioned<unknown> | undefined;\n /** The new plugin registry after migration (pluginId -> pluginName) */\n newPluginRegistry: PluginRegistry;\n /** Factory to create initial data for new plugins. Transfer is provided when a\n * .transfer() was defined for this plugin in the block's migration chain. */\n createPluginData: (\n handle: PluginHandle,\n transfer?: DataVersioned<unknown>,\n ) => DataVersioned<unknown>;\n}\n\n/**\n * Performs atomic migration of block storage including block data and all plugins.\n *\n * Migration is atomic: either everything succeeds and a new storage is returned,\n * or an error is returned and the original storage is completely untouched.\n *\n * Migration steps:\n * 1. Migrate block data\n * 2. For each plugin in newPluginRegistry:\n * - If plugin exists with same name: migrate its data\n * - Otherwise (new or type changed): create with initial data\n * Plugins not in newPluginRegistry are dropped.\n *\n * If any step throws, migration fails and original storage is preserved.\n * User can then choose to:\n * - Abort: keep original storage, don't update block\n * - Reset: call createBlockStorage() to start fresh\n *\n * @param storage - The original storage (will not be modified)\n * @param config - Migration configuration\n * @returns Migration result - either success with new storage, or failure with error info\n *\n * @example\n * const result = migrateBlockStorage(storage, {\n * migrateBlockData: (versioned) => blockDataModel.migrate(versioned),\n * migratePluginData: (pluginId, versioned) => getPluginModel(pluginId).migrate(versioned),\n * newPluginRegistry: { table1: 'dataTable' as PluginName },\n * createPluginData: (pluginId) => getPluginModel(pluginId).getDefaultData(),\n * });\n *\n * if (result.success) {\n * commitStorage(result.storage);\n * } else {\n * const userChoice = await askUser(`Migration failed: ${result.error}. Reset data?`);\n * if (userChoice === 'reset') {\n * commitStorage(createBlockStorage(initialData, currentVersion));\n * }\n * // else: abort, keep original\n * }\n */\nexport function migrateBlockStorage(\n storage: BlockStorage<unknown>,\n config: MigrateBlockStorageConfig,\n): MigrationResult<unknown> {\n const { migrateBlockData, migratePluginData, newPluginRegistry, createPluginData } = config;\n\n // Step 1: Migrate block data and collect transfers\n let migratedData: unknown;\n let newVersion: string;\n let transfers: TransferRecord;\n try {\n const result = migrateBlockData({ version: storage.__dataVersion, data: storage.__data });\n migratedData = result.data;\n newVersion = result.version;\n transfers = result.transfers;\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n failedAt: \"block\",\n };\n }\n\n // Step 2: Migrate plugins\n const oldPlugins = storage.__plugins ?? {};\n const oldRegistry = storage.__pluginRegistry ?? {};\n const newPlugins: Record<PluginHandle, VersionedData<unknown>> = {};\n\n for (const [key, pluginName] of Object.entries(newPluginRegistry)) {\n const handle = key as PluginHandle;\n const existingEntry = oldPlugins[handle];\n const existingName = oldRegistry[handle];\n\n try {\n if (existingEntry && existingName === pluginName) {\n // Plugin exists with same type - migrate its data\n const migrated = migratePluginData(handle, {\n version: existingEntry.__dataVersion,\n data: existingEntry.__data,\n });\n if (migrated) {\n newPlugins[handle] = { __dataVersion: migrated.version, __data: migrated.data };\n }\n // If undefined returned, plugin is intentionally removed\n } else if (existingEntry) {\n // Plugin type changed — pass old data with DATA_MODEL_LEGACY_VERSION.\n // If the new plugin has upgradeLegacy(), it migrates the old data.\n // If not, defaultRecover throws DataUnrecoverableError → fall back to init.\n let recovered = false;\n try {\n const migrated = migratePluginData(handle, {\n version: DATA_MODEL_LEGACY_VERSION,\n data: existingEntry.__data,\n });\n if (migrated) {\n newPlugins[handle] = { __dataVersion: migrated.version, __data: migrated.data };\n recovered = true;\n }\n } catch (recoverError) {\n if (!isDataUnrecoverableError(recoverError)) throw recoverError;\n }\n if (!recovered) {\n const transfer = transfers[handle];\n const initial = createPluginData(handle, transfer);\n newPlugins[handle] = { __dataVersion: initial.version, __data: initial.data };\n }\n } else {\n // New plugin - create with initial data, passing transfer if available\n const transfer = transfers[handle];\n const initial = createPluginData(handle, transfer);\n newPlugins[handle] = { __dataVersion: initial.version, __data: initial.data };\n }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n failedAt: handle,\n };\n }\n }\n\n // Step 3: Build final storage atomically\n const migratedStorage: BlockStorage = {\n [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,\n __dataVersion: newVersion,\n __data: migratedData,\n __pluginRegistry: newPluginRegistry,\n __plugins: newPlugins,\n };\n\n return {\n success: true,\n storage: migratedStorage,\n };\n}\n\n/**\n * Gets plugin-specific data from block storage.\n * Accepts raw storage (any format) and normalizes internally.\n *\n * When called with a typed PluginHandle<F>, the return type is automatically\n * inferred from the factory's phantom `__types.data` field.\n *\n * @param rawStorage - Raw block storage (may be legacy format or BlockStorage)\n * @param handle - The plugin handle (branded plugin instance id)\n * @returns The plugin data, typed via factory inference\n * @throws If plugin is not found in storage\n */\nexport function getPluginData<F extends PluginFactoryLike>(\n rawStorage: unknown,\n handle: PluginHandle<F>,\n): InferFactoryData<F> {\n const storage = normalizeBlockStorage(rawStorage);\n const pluginEntry = storage.__plugins?.[handle];\n if (!pluginEntry) throw new Error(`Plugin '${handle}' not found in block storage`);\n return pluginEntry.__data as InferFactoryData<F>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"block_storage.js","names":[],"sources":["../src/block_storage.ts"],"sourcesContent":["/**\n * BlockStorage - Typed storage abstraction for block persistent data.\n *\n * This module provides:\n * - A typed structure for block storage with versioning and plugin support\n * - Utility functions for manipulating storage\n * - Handler interfaces for model-level customization\n *\n * @module block_storage\n */\n\nimport type { Branded } from \"@milaboratories/pl-model-common\";\nimport {\n type DataVersioned,\n type TransferRecord,\n isDataUnrecoverableError,\n} from \"./block_migrations\";\nimport type { PluginHandle, PluginFactoryLike, InferFactoryData } from \"./plugin_handle\";\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Discriminator key for BlockStorage format detection.\n * This unique hash-based key identifies data as BlockStorage vs legacy formats.\n */\nexport const BLOCK_STORAGE_KEY = \"__pl_a7f3e2b9__\";\n\n/**\n * Current BlockStorage schema version.\n * Increment this when the storage structure itself changes (not block state migrations).\n */\nexport const BLOCK_STORAGE_SCHEMA_VERSION = \"v1\";\n\n/**\n * Default data version for new blocks without migrations.\n * Unique identifier ensures blocks are created via DataModel API.\n */\nexport const DATA_MODEL_LEGACY_VERSION = \"__pl_v1_d4e8f2a1__\";\n\n/**\n * Type for valid schema versions\n */\nexport type BlockStorageSchemaVersion = \"v1\"; // Add 'v2', 'v3', etc. as schema evolves\n\n/**\n * Branded type for plugin names - globally unique plugin type identifiers.\n * Using a branded type enforces explicit casting (`as PluginName`) which makes\n * it easy to find all plugin name definitions in the codebase and verify uniqueness.\n */\nexport type PluginName = Branded<string, \"PluginName\">;\n\n/**\n * Plugin registry - maps pluginId (unique within a block) to pluginName (globally unique plugin type).\n * Using a Record highlights that pluginIds must be unique within a block.\n */\nexport type PluginRegistry = Record<PluginHandle, PluginName>;\n\n/**\n * Versioned data - used for both block data and plugin data\n */\nexport interface VersionedData<TData = unknown> {\n /** Version of the data, used for migrations */\n __dataVersion: string;\n /** The persistent data */\n __data: TData;\n}\n\n/**\n * Core BlockStorage type that holds:\n * - __pl_a7f3e2b9__: Schema version (discriminator key identifies BlockStorage format)\n * - __dataVersion: Version key for block data migrations\n * - __data: The block's user-facing data (state)\n * - __pluginRegistry: Map from pluginId to pluginName (optional)\n * - __plugins: Plugin-specific data keyed by pluginId (optional)\n */\nexport type BlockStorage<TState = unknown> = {\n /** Schema version - the key itself is the discriminator */\n readonly [BLOCK_STORAGE_KEY]: BlockStorageSchemaVersion;\n /** Registry of plugins: pluginId -> pluginName */\n __pluginRegistry?: PluginRegistry;\n /** Plugin-specific data, keyed by plugin handle */\n __plugins?: Record<PluginHandle, VersionedData<unknown>>;\n} & VersionedData<TState>;\n\n/**\n * Type guard to check if a value is a valid BlockStorage object.\n * Checks for the discriminator key and valid schema version.\n */\nexport function isBlockStorage(value: unknown): value is BlockStorage {\n if (value === null || typeof value !== \"object\") return false;\n const obj = value as Record<string, unknown>;\n const schemaVersion = obj[BLOCK_STORAGE_KEY];\n // Currently only 'v1' is valid, but this allows future versions\n return schemaVersion === \"v1\"; // Add more versions as schema evolves\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Creates a BlockStorage with the given initial data\n *\n * @param initialData - The initial data value (defaults to empty object)\n * @param version - The initial data version key (defaults to DATA_MODEL_LEGACY_VERSION)\n * @returns A new BlockStorage instance with discriminator key\n */\nexport function createBlockStorage<TState = unknown>(\n initialData: TState = {} as TState,\n version: string = DATA_MODEL_LEGACY_VERSION,\n): BlockStorage<TState> {\n return {\n [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,\n __dataVersion: version,\n __data: initialData,\n __pluginRegistry: {},\n __plugins: {},\n };\n}\n\n/**\n * Normalizes raw storage data to BlockStorage format.\n * If the input is already a BlockStorage, returns it as-is (with defaults for missing fields).\n * If the input is legacy format (raw state), wraps it in BlockStorage structure.\n *\n * @param raw - Raw storage data (may be legacy format or BlockStorage)\n * @returns Normalized BlockStorage\n */\nexport function normalizeBlockStorage<TState = unknown>(raw: unknown): BlockStorage<TState> {\n if (isBlockStorage(raw)) {\n const storage = raw as BlockStorage<TState>;\n return {\n ...storage,\n // Fix for early released version where __dataVersion was a number\n __dataVersion:\n typeof storage.__dataVersion === \"number\"\n ? DATA_MODEL_LEGACY_VERSION\n : storage.__dataVersion,\n // Ensure plugin fields have defaults\n __pluginRegistry: storage.__pluginRegistry ?? {},\n __plugins: storage.__plugins ?? {},\n };\n }\n // Legacy format: raw is the state directly\n return createBlockStorage(raw as TState);\n}\n\n// =============================================================================\n// Data Access & Update Functions\n// =============================================================================\n\n/**\n * Gets the data from BlockStorage\n *\n * @param storage - The BlockStorage instance\n * @returns The data value\n */\nexport function getStorageData<TState>(storage: BlockStorage<TState>): TState {\n return storage.__data;\n}\n\n/**\n * Derives data from raw block storage.\n * This function is meant to be called from sdk/ui-vue to extract\n * user-facing data from the raw storage returned by the middle layer.\n *\n * The middle layer returns raw storage (opaque to it), and the UI\n * uses this function to derive the actual data value.\n *\n * @param rawStorage - Raw storage data from middle layer (may be any format)\n * @returns The extracted data value, or undefined if storage is undefined/null\n */\nexport function deriveDataFromStorage<TData = unknown>(rawStorage: unknown): TData {\n // Normalize to BlockStorage format (handles legacy formats too)\n const storage = normalizeBlockStorage<TData>(rawStorage);\n return getStorageData(storage);\n}\n\n/** Payload for storage mutation operations. SDK defines specific operations. */\nexport type MutateStoragePayload<T = unknown> =\n | { operation: \"update-block-data\"; value: T }\n | { operation: \"update-plugin-data\"; pluginId: PluginHandle; value: unknown };\n\n/**\n * Updates the data in BlockStorage (immutable)\n *\n * @param storage - The current BlockStorage\n * @param payload - The update payload with operation and value\n * @returns A new BlockStorage with updated data\n */\nexport function updateStorageData<TValue = unknown>(\n storage: BlockStorage<TValue>,\n payload: MutateStoragePayload<TValue>,\n): BlockStorage<TValue> {\n switch (payload.operation) {\n case \"update-block-data\":\n return { ...storage, __data: payload.value };\n case \"update-plugin-data\": {\n const { pluginId, value } = payload;\n const currentPlugins = storage.__plugins ?? {};\n const existingEntry = currentPlugins[pluginId];\n const version = existingEntry?.__dataVersion ?? DATA_MODEL_LEGACY_VERSION;\n return {\n ...storage,\n __plugins: {\n ...currentPlugins,\n [pluginId]: {\n __dataVersion: version,\n __data: value,\n },\n },\n };\n }\n default:\n throw new Error(`Unknown storage operation: ${(payload as { operation: string }).operation}`);\n }\n}\n\n// =============================================================================\n// Atomic Migration\n// =============================================================================\n\n/**\n * Result of a successful atomic migration.\n */\nexport interface MigrationSuccess<TState> {\n success: true;\n /** The fully migrated storage - commit this to persist */\n storage: BlockStorage<TState>;\n}\n\n/**\n * Result of a failed atomic migration.\n * The original storage is untouched - user must choose to abort or reset.\n */\nexport interface MigrationFailure {\n success: false;\n /** Description of what failed */\n error: string;\n /** Which step failed: 'block' or pluginId */\n failedAt: string;\n}\n\nexport type MigrationResult<TState> = MigrationSuccess<TState> | MigrationFailure;\n\n/**\n * Configuration for atomic block storage migration.\n * Callbacks use DataVersioned format (the DataModel API format).\n * Conversion to internal VersionedData format is handled by migrateBlockStorage().\n */\nexport interface MigrateBlockStorageConfig {\n /** Migrate block data from any version to latest. Returns migrated data and transfers. */\n migrateBlockData: (versioned: DataVersioned<unknown>) => DataVersioned<unknown> & {\n transfers: TransferRecord;\n };\n /** Migrate each plugin's data. Return undefined to remove the plugin. Throws on failure. */\n migratePluginData: (\n handle: PluginHandle,\n versioned: DataVersioned<unknown>,\n ) => DataVersioned<unknown> | undefined;\n /** The new plugin registry after migration (pluginId -> pluginName) */\n newPluginRegistry: PluginRegistry;\n /** Factory to create initial data for new plugins. Transfer is provided when a\n * .transfer() was defined for this plugin in the block's migration chain. */\n createPluginData: (\n handle: PluginHandle,\n transfer?: DataVersioned<unknown>,\n ) => DataVersioned<unknown>;\n}\n\n/**\n * Performs atomic migration of block storage including block data and all plugins.\n *\n * Migration is atomic: either everything succeeds and a new storage is returned,\n * or an error is returned and the original storage is completely untouched.\n *\n * Migration steps:\n * 1. Migrate block data\n * 2. For each plugin in newPluginRegistry:\n * - If plugin exists with same name: migrate its data\n * - Otherwise (new or type changed): create with initial data\n * Plugins not in newPluginRegistry are dropped.\n *\n * If any step throws, migration fails and original storage is preserved.\n * User can then choose to:\n * - Abort: keep original storage, don't update block\n * - Reset: call createBlockStorage() to start fresh\n *\n * @param storage - The original storage (will not be modified)\n * @param config - Migration configuration\n * @returns Migration result - either success with new storage, or failure with error info\n *\n * @example\n * const result = migrateBlockStorage(storage, {\n * migrateBlockData: (versioned) => blockDataModel.migrate(versioned),\n * migratePluginData: (pluginId, versioned) => getPluginModel(pluginId).migrate(versioned),\n * newPluginRegistry: { table1: 'dataTable' as PluginName },\n * createPluginData: (pluginId) => getPluginModel(pluginId).getDefaultData(),\n * });\n *\n * if (result.success) {\n * commitStorage(result.storage);\n * } else {\n * const userChoice = await askUser(`Migration failed: ${result.error}. Reset data?`);\n * if (userChoice === 'reset') {\n * commitStorage(createBlockStorage(initialData, currentVersion));\n * }\n * // else: abort, keep original\n * }\n */\nexport function migrateBlockStorage(\n storage: BlockStorage<unknown>,\n config: MigrateBlockStorageConfig,\n): MigrationResult<unknown> {\n const { migrateBlockData, migratePluginData, newPluginRegistry, createPluginData } = config;\n\n // Step 1: Migrate block data and collect transfers\n let migratedData: unknown;\n let newVersion: string;\n let transfers: TransferRecord;\n try {\n const result = migrateBlockData({ version: storage.__dataVersion, data: storage.__data });\n migratedData = result.data;\n newVersion = result.version;\n transfers = result.transfers;\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n failedAt: \"block\",\n };\n }\n\n // Step 2: Migrate plugins\n const oldPlugins = storage.__plugins ?? {};\n const oldRegistry = storage.__pluginRegistry ?? {};\n const newPlugins: Record<PluginHandle, VersionedData<unknown>> = {};\n\n for (const [key, pluginName] of Object.entries(newPluginRegistry)) {\n const handle = key as PluginHandle;\n const existingEntry = oldPlugins[handle];\n const existingName = oldRegistry[handle];\n\n try {\n if (existingEntry && existingName === pluginName) {\n // Plugin exists with same type - migrate its data\n const migrated = migratePluginData(handle, {\n version: existingEntry.__dataVersion,\n data: existingEntry.__data,\n });\n if (migrated) {\n newPlugins[handle] = { __dataVersion: migrated.version, __data: migrated.data };\n }\n // If undefined returned, plugin is intentionally removed\n } else if (existingEntry) {\n // Plugin type changed — pass old data with DATA_MODEL_LEGACY_VERSION.\n // If the new plugin has upgradeLegacy(), it migrates the old data.\n // If not, defaultRecover throws DataUnrecoverableError → fall back to init.\n let recovered = false;\n try {\n const migrated = migratePluginData(handle, {\n version: DATA_MODEL_LEGACY_VERSION,\n data: existingEntry.__data,\n });\n if (migrated) {\n newPlugins[handle] = { __dataVersion: migrated.version, __data: migrated.data };\n recovered = true;\n }\n } catch (recoverError) {\n if (!isDataUnrecoverableError(recoverError)) throw recoverError;\n }\n if (!recovered) {\n const transfer = transfers[handle];\n const initial = createPluginData(handle, transfer);\n newPlugins[handle] = { __dataVersion: initial.version, __data: initial.data };\n }\n } else {\n // New plugin - create with initial data, passing transfer if available\n const transfer = transfers[handle];\n const initial = createPluginData(handle, transfer);\n newPlugins[handle] = { __dataVersion: initial.version, __data: initial.data };\n }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n failedAt: handle,\n };\n }\n }\n\n // Step 3: Build final storage atomically\n const migratedStorage: BlockStorage = {\n [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,\n __dataVersion: newVersion,\n __data: migratedData,\n __pluginRegistry: newPluginRegistry,\n __plugins: newPlugins,\n };\n\n return {\n success: true,\n storage: migratedStorage,\n };\n}\n\n/**\n * Gets plugin-specific data from block storage.\n * Accepts raw storage (any format) and normalizes internally.\n *\n * When called with a typed PluginHandle<F>, the return type is automatically\n * inferred from the factory's phantom `__types.data` field.\n *\n * @param rawStorage - Raw block storage (may be legacy format or BlockStorage)\n * @param handle - The plugin handle (branded plugin instance id)\n * @returns The plugin data, typed via factory inference\n * @throws If plugin is not found in storage\n */\nexport function getPluginData<F extends PluginFactoryLike>(\n rawStorage: unknown,\n handle: PluginHandle<F>,\n): InferFactoryData<F> {\n const storage = normalizeBlockStorage(rawStorage);\n const pluginEntry = storage.__plugins?.[handle];\n if (!pluginEntry) throw new Error(`Plugin '${handle}' not found in block storage`);\n return pluginEntry.__data as InferFactoryData<F>;\n}\n"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
2
- const require_block_storage = require('./block_storage.cjs');
1
+ require("./_virtual/_rolldown/runtime.cjs");
2
+ const require_block_storage = require("./block_storage.cjs");
3
3
  let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
4
-
5
4
  //#region src/block_storage_callbacks.ts
6
5
  /**
7
6
  * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().
@@ -133,7 +132,7 @@ function createInitialStorage(hooks) {
133
132
  };
134
133
  }
135
134
  return (0, _milaboratories_pl_model_common.stringifyJson)({
136
- [require_block_storage.BLOCK_STORAGE_KEY]: require_block_storage.BLOCK_STORAGE_SCHEMA_VERSION,
135
+ [require_block_storage.BLOCK_STORAGE_KEY]: "v1",
137
136
  __dataVersion: blockDefault.version,
138
137
  __data: blockDefault.data,
139
138
  __pluginRegistry: pluginRegistry,
@@ -178,7 +177,6 @@ function derivePrerunArgsFromStorage(storageJson, argsFunction, prerunArgsFuncti
178
177
  return { error: `args() threw (fallback): ${e instanceof Error ? e.message : String(e)}` };
179
178
  }
180
179
  }
181
-
182
180
  //#endregion
183
181
  exports.applyStorageUpdate = applyStorageUpdate;
184
182
  exports.createInitialStorage = createInitialStorage;
@@ -186,4 +184,5 @@ exports.deriveArgsFromStorage = deriveArgsFromStorage;
186
184
  exports.derivePrerunArgsFromStorage = derivePrerunArgsFromStorage;
187
185
  exports.getStorageDebugView = getStorageDebugView;
188
186
  exports.migrateStorage = migrateStorage;
187
+
189
188
  //# sourceMappingURL=block_storage_callbacks.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"block_storage_callbacks.cjs","names":["createBlockStorage","isBlockStorage","normalizeBlockStorage","getStorageData","updateStorageData","migrateBlockStorage","BLOCK_STORAGE_KEY","BLOCK_STORAGE_SCHEMA_VERSION"],"sources":["../src/block_storage_callbacks.ts"],"sourcesContent":["/**\n * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().\n *\n * Provides pure functions for storage operations (migration, initialization,\n * args derivation, updates, debug views). Each function takes its dependencies\n * explicitly as parameters.\n *\n * @module block_storage_callbacks\n * @internal\n */\n\nimport {\n BLOCK_STORAGE_KEY,\n BLOCK_STORAGE_SCHEMA_VERSION,\n type BlockStorage,\n type MutateStoragePayload,\n type PluginRegistry,\n type VersionedData,\n createBlockStorage,\n getStorageData,\n isBlockStorage,\n migrateBlockStorage,\n normalizeBlockStorage,\n updateStorageData,\n} from \"./block_storage\";\nimport type { PluginHandle } from \"./plugin_handle\";\n\nimport { stringifyJson, type StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport type { DataVersioned, TransferRecord } from \"./block_migrations\";\nimport type { StorageDebugView } from \"@milaboratories/pl-model-middle-layer\";\n\n// =============================================================================\n// Hook interfaces for dependency injection\n// =============================================================================\n\n/** Dependencies for storage migration */\nexport interface MigrationHooks {\n migrateBlockData: (versioned: DataVersioned<unknown>) => DataVersioned<unknown> & {\n transfers: TransferRecord;\n };\n getPluginRegistry: () => PluginRegistry;\n migratePluginData: (\n handle: PluginHandle,\n versioned: DataVersioned<unknown>,\n ) => DataVersioned<unknown> | undefined;\n createPluginData: (\n handle: PluginHandle,\n transfer?: DataVersioned<unknown>,\n ) => DataVersioned<unknown>;\n}\n\n/** Dependencies for initial storage creation */\nexport interface InitialStorageHooks {\n getDefaultBlockData: () => DataVersioned<unknown>;\n getPluginRegistry: () => PluginRegistry;\n createPluginData: (handle: PluginHandle) => DataVersioned<unknown>;\n}\n\n/**\n * Result of storage normalization\n */\nexport interface NormalizeStorageResult {\n /** The normalized BlockStorage object */\n storage: BlockStorage;\n /** The extracted data (what developers see) */\n data: unknown;\n}\n\n/**\n * Normalizes raw storage data and extracts state.\n * Handles all formats:\n * - New BlockStorage format (has discriminator)\n * - Legacy V1/V2 format ({ args, uiState })\n * - Raw V3 state (any other format)\n *\n * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)\n * @returns Object with normalized storage and extracted state\n */\nfunction normalizeStorage(rawStorage: unknown): NormalizeStorageResult {\n // Handle undefined/null\n if (rawStorage === undefined || rawStorage === null) {\n const storage = createBlockStorage({});\n return { storage, data: {} };\n }\n\n // Parse JSON string if needed\n let parsed = rawStorage;\n if (typeof rawStorage === \"string\") {\n try {\n parsed = JSON.parse(rawStorage);\n } catch {\n // If parsing fails, treat string as the data\n const storage = createBlockStorage(rawStorage);\n return { storage, data: rawStorage };\n }\n }\n\n // Check for BlockStorage format (has discriminator)\n if (isBlockStorage(parsed)) {\n const storage = normalizeBlockStorage(parsed);\n return { storage, data: getStorageData(storage) };\n }\n\n // Check for legacy V1/V2 format: { args, uiState }\n if (isLegacyModelV1ApiFormat(parsed)) {\n // For legacy format, the whole object IS the data\n const storage = createBlockStorage(parsed);\n return { storage, data: parsed };\n }\n\n // Raw V3 data - wrap it\n const storage = createBlockStorage(parsed);\n return { storage, data: parsed };\n}\n\n/**\n * Applies a state update to existing storage.\n * Used when setData is called from the frontend.\n *\n * @param currentStorageJson - Current storage as JSON string (must be defined)\n * @param payload - Update payload with operation type and value\n * @returns Updated storage as StringifiedJson<BlockStorage>\n */\nexport function applyStorageUpdate(\n currentStorageJson: string,\n payload: MutateStoragePayload,\n): StringifiedJson<BlockStorage> {\n const { storage: currentStorage } = normalizeStorage(currentStorageJson);\n\n // Update data while preserving other storage fields (version, plugins)\n const updatedStorage = updateStorageData(currentStorage, payload);\n\n return stringifyJson(updatedStorage);\n}\n\n/**\n * Checks if data is in legacy Model API v1 format.\n * Legacy format has { args, uiState? } at top level without the BlockStorage discriminator.\n */\nfunction isLegacyModelV1ApiFormat(data: unknown): data is { args?: unknown } {\n if (data === null || typeof data !== \"object\") return false;\n if (isBlockStorage(data)) return false;\n\n const obj = data as Record<string, unknown>;\n return \"args\" in obj;\n}\n\n// =============================================================================\n// Facade Callback Implementations\n// =============================================================================\n\n/**\n * Gets storage debug view from raw storage data.\n * Returns structured debug info about the storage state.\n *\n * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)\n * @returns JSON string with storage debug view\n */\nexport function getStorageDebugView(rawStorage: unknown): StringifiedJson<StorageDebugView> {\n const { storage } = normalizeStorage(rawStorage);\n const debugView: StorageDebugView = {\n dataVersion: storage.__dataVersion,\n data: storage.__data,\n };\n return stringifyJson(debugView);\n}\n\n// =============================================================================\n// Migration Support\n// =============================================================================\n\n/**\n * Result of storage migration.\n * Returned by __pl_storage_migrate callback.\n *\n * - Error result: { error: string } - serious failure (no context, etc.)\n * - Success result: { newStorageJson: StringifiedJson<BlockStorage>, info: string } - migration succeeded\n */\nexport type MigrationResult =\n | { error: string }\n | { error?: undefined; newStorageJson: StringifiedJson<BlockStorage>; info: string };\n\n/**\n * Runs storage migration using the provided hooks.\n * This is the main entry point for the middle layer to trigger migrations.\n *\n * @param currentStorageJson - Current storage as JSON string (or undefined)\n * @param hooks - Migration dependencies (block/plugin data migration and creation functions)\n * @returns MigrationResult\n */\nexport function migrateStorage(\n currentStorageJson: string | undefined,\n hooks: MigrationHooks,\n): MigrationResult {\n // Normalize current storage\n const { storage: currentStorage } = normalizeStorage(currentStorageJson);\n\n const newPluginRegistry = hooks.getPluginRegistry();\n\n // Perform atomic migration of block + all plugins\n const migrationResult = migrateBlockStorage(currentStorage, {\n migrateBlockData: hooks.migrateBlockData,\n migratePluginData: hooks.migratePluginData,\n newPluginRegistry,\n createPluginData: hooks.createPluginData,\n });\n\n if (!migrationResult.success) {\n return {\n error: `Migration failed at '${migrationResult.failedAt}': ${migrationResult.error}`,\n };\n }\n\n // Build info message\n const oldVersion = currentStorage.__dataVersion;\n const newVersion = migrationResult.storage.__dataVersion;\n const info =\n oldVersion === newVersion\n ? `No migration needed (${oldVersion})`\n : `Migrated ${oldVersion} -> ${newVersion}`;\n\n return {\n newStorageJson: stringifyJson(migrationResult.storage),\n info,\n };\n}\n\n// =============================================================================\n// Initial Storage Creation\n// =============================================================================\n\n/**\n * Creates complete initial storage (block data + all plugin data) atomically.\n *\n * @param hooks - Dependencies for creating initial block and plugin data\n * @returns Initial storage as branded JSON string\n * @throws If initialDataFn or createPluginData throws\n */\nexport function createInitialStorage(hooks: InitialStorageHooks): StringifiedJson<BlockStorage> {\n const blockDefault = hooks.getDefaultBlockData();\n const pluginRegistry = hooks.getPluginRegistry();\n\n const plugins: Record<PluginHandle, VersionedData<unknown>> = {};\n for (const handle of Object.keys(pluginRegistry) as PluginHandle[]) {\n const initial = hooks.createPluginData(handle);\n plugins[handle] = { __dataVersion: initial.version, __data: initial.data };\n }\n\n const storage: BlockStorage = {\n [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,\n __dataVersion: blockDefault.version,\n __data: blockDefault.data,\n __pluginRegistry: pluginRegistry,\n __plugins: plugins,\n };\n return stringifyJson(storage);\n}\n\n// =============================================================================\n// Args Derivation from Storage\n// =============================================================================\n\n/**\n * Result of args derivation from storage.\n * Returned by __pl_args_derive and __pl_prerunArgs_derive callbacks.\n */\nexport type ArgsDeriveResult = { error: string } | { error?: undefined; value: unknown };\n\n/**\n * Derives args from storage using the provided args function.\n * This extracts data from storage and passes it to the block's args() function.\n *\n * @param storageJson - Storage as JSON string\n * @param argsFunction - The block's args derivation function\n * @returns ArgsDeriveResult with derived args or error\n */\nexport function deriveArgsFromStorage(\n storageJson: string,\n argsFunction: (data: unknown) => unknown,\n): ArgsDeriveResult {\n // Extract data from storage\n const { data } = normalizeStorage(storageJson);\n\n // Call the args function with extracted data\n try {\n const result = argsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `args() threw: ${errorMsg}` };\n }\n}\n\n/**\n * Derives prerunArgs from storage.\n * Uses prerunArgsFunction if provided, otherwise falls back to argsFunction.\n *\n * @param storageJson - Storage as JSON string\n * @param argsFunction - The block's args derivation function (fallback)\n * @param prerunArgsFunction - Optional prerun args derivation function\n * @returns ArgsDeriveResult with derived prerunArgs or error\n */\nexport function derivePrerunArgsFromStorage(\n storageJson: string,\n argsFunction: (data: unknown) => unknown,\n prerunArgsFunction?: (data: unknown) => unknown,\n): ArgsDeriveResult {\n // Extract data from storage\n const { data } = normalizeStorage(storageJson);\n\n // Try prerunArgs function first if available\n if (prerunArgsFunction) {\n try {\n const result = prerunArgsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `prerunArgs() threw: ${errorMsg}` };\n }\n }\n\n // Fall back to args function\n try {\n const result = argsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `args() threw (fallback): ${errorMsg}` };\n }\n}\n\n// Export discriminator key and schema version for external checks\nexport { BLOCK_STORAGE_KEY, BLOCK_STORAGE_SCHEMA_VERSION };\n"],"mappings":"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"}
1
+ {"version":3,"file":"block_storage_callbacks.cjs","names":["createBlockStorage","isBlockStorage","normalizeBlockStorage","getStorageData","updateStorageData","migrateBlockStorage","BLOCK_STORAGE_KEY"],"sources":["../src/block_storage_callbacks.ts"],"sourcesContent":["/**\n * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().\n *\n * Provides pure functions for storage operations (migration, initialization,\n * args derivation, updates, debug views). Each function takes its dependencies\n * explicitly as parameters.\n *\n * @module block_storage_callbacks\n * @internal\n */\n\nimport {\n BLOCK_STORAGE_KEY,\n BLOCK_STORAGE_SCHEMA_VERSION,\n type BlockStorage,\n type MutateStoragePayload,\n type PluginRegistry,\n type VersionedData,\n createBlockStorage,\n getStorageData,\n isBlockStorage,\n migrateBlockStorage,\n normalizeBlockStorage,\n updateStorageData,\n} from \"./block_storage\";\nimport type { PluginHandle } from \"./plugin_handle\";\n\nimport { stringifyJson, type StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport type { DataVersioned, TransferRecord } from \"./block_migrations\";\nimport type { StorageDebugView } from \"@milaboratories/pl-model-middle-layer\";\n\n// =============================================================================\n// Hook interfaces for dependency injection\n// =============================================================================\n\n/** Dependencies for storage migration */\nexport interface MigrationHooks {\n migrateBlockData: (versioned: DataVersioned<unknown>) => DataVersioned<unknown> & {\n transfers: TransferRecord;\n };\n getPluginRegistry: () => PluginRegistry;\n migratePluginData: (\n handle: PluginHandle,\n versioned: DataVersioned<unknown>,\n ) => DataVersioned<unknown> | undefined;\n createPluginData: (\n handle: PluginHandle,\n transfer?: DataVersioned<unknown>,\n ) => DataVersioned<unknown>;\n}\n\n/** Dependencies for initial storage creation */\nexport interface InitialStorageHooks {\n getDefaultBlockData: () => DataVersioned<unknown>;\n getPluginRegistry: () => PluginRegistry;\n createPluginData: (handle: PluginHandle) => DataVersioned<unknown>;\n}\n\n/**\n * Result of storage normalization\n */\nexport interface NormalizeStorageResult {\n /** The normalized BlockStorage object */\n storage: BlockStorage;\n /** The extracted data (what developers see) */\n data: unknown;\n}\n\n/**\n * Normalizes raw storage data and extracts state.\n * Handles all formats:\n * - New BlockStorage format (has discriminator)\n * - Legacy V1/V2 format ({ args, uiState })\n * - Raw V3 state (any other format)\n *\n * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)\n * @returns Object with normalized storage and extracted state\n */\nfunction normalizeStorage(rawStorage: unknown): NormalizeStorageResult {\n // Handle undefined/null\n if (rawStorage === undefined || rawStorage === null) {\n const storage = createBlockStorage({});\n return { storage, data: {} };\n }\n\n // Parse JSON string if needed\n let parsed = rawStorage;\n if (typeof rawStorage === \"string\") {\n try {\n parsed = JSON.parse(rawStorage);\n } catch {\n // If parsing fails, treat string as the data\n const storage = createBlockStorage(rawStorage);\n return { storage, data: rawStorage };\n }\n }\n\n // Check for BlockStorage format (has discriminator)\n if (isBlockStorage(parsed)) {\n const storage = normalizeBlockStorage(parsed);\n return { storage, data: getStorageData(storage) };\n }\n\n // Check for legacy V1/V2 format: { args, uiState }\n if (isLegacyModelV1ApiFormat(parsed)) {\n // For legacy format, the whole object IS the data\n const storage = createBlockStorage(parsed);\n return { storage, data: parsed };\n }\n\n // Raw V3 data - wrap it\n const storage = createBlockStorage(parsed);\n return { storage, data: parsed };\n}\n\n/**\n * Applies a state update to existing storage.\n * Used when setData is called from the frontend.\n *\n * @param currentStorageJson - Current storage as JSON string (must be defined)\n * @param payload - Update payload with operation type and value\n * @returns Updated storage as StringifiedJson<BlockStorage>\n */\nexport function applyStorageUpdate(\n currentStorageJson: string,\n payload: MutateStoragePayload,\n): StringifiedJson<BlockStorage> {\n const { storage: currentStorage } = normalizeStorage(currentStorageJson);\n\n // Update data while preserving other storage fields (version, plugins)\n const updatedStorage = updateStorageData(currentStorage, payload);\n\n return stringifyJson(updatedStorage);\n}\n\n/**\n * Checks if data is in legacy Model API v1 format.\n * Legacy format has { args, uiState? } at top level without the BlockStorage discriminator.\n */\nfunction isLegacyModelV1ApiFormat(data: unknown): data is { args?: unknown } {\n if (data === null || typeof data !== \"object\") return false;\n if (isBlockStorage(data)) return false;\n\n const obj = data as Record<string, unknown>;\n return \"args\" in obj;\n}\n\n// =============================================================================\n// Facade Callback Implementations\n// =============================================================================\n\n/**\n * Gets storage debug view from raw storage data.\n * Returns structured debug info about the storage state.\n *\n * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)\n * @returns JSON string with storage debug view\n */\nexport function getStorageDebugView(rawStorage: unknown): StringifiedJson<StorageDebugView> {\n const { storage } = normalizeStorage(rawStorage);\n const debugView: StorageDebugView = {\n dataVersion: storage.__dataVersion,\n data: storage.__data,\n };\n return stringifyJson(debugView);\n}\n\n// =============================================================================\n// Migration Support\n// =============================================================================\n\n/**\n * Result of storage migration.\n * Returned by __pl_storage_migrate callback.\n *\n * - Error result: { error: string } - serious failure (no context, etc.)\n * - Success result: { newStorageJson: StringifiedJson<BlockStorage>, info: string } - migration succeeded\n */\nexport type MigrationResult =\n | { error: string }\n | { error?: undefined; newStorageJson: StringifiedJson<BlockStorage>; info: string };\n\n/**\n * Runs storage migration using the provided hooks.\n * This is the main entry point for the middle layer to trigger migrations.\n *\n * @param currentStorageJson - Current storage as JSON string (or undefined)\n * @param hooks - Migration dependencies (block/plugin data migration and creation functions)\n * @returns MigrationResult\n */\nexport function migrateStorage(\n currentStorageJson: string | undefined,\n hooks: MigrationHooks,\n): MigrationResult {\n // Normalize current storage\n const { storage: currentStorage } = normalizeStorage(currentStorageJson);\n\n const newPluginRegistry = hooks.getPluginRegistry();\n\n // Perform atomic migration of block + all plugins\n const migrationResult = migrateBlockStorage(currentStorage, {\n migrateBlockData: hooks.migrateBlockData,\n migratePluginData: hooks.migratePluginData,\n newPluginRegistry,\n createPluginData: hooks.createPluginData,\n });\n\n if (!migrationResult.success) {\n return {\n error: `Migration failed at '${migrationResult.failedAt}': ${migrationResult.error}`,\n };\n }\n\n // Build info message\n const oldVersion = currentStorage.__dataVersion;\n const newVersion = migrationResult.storage.__dataVersion;\n const info =\n oldVersion === newVersion\n ? `No migration needed (${oldVersion})`\n : `Migrated ${oldVersion} -> ${newVersion}`;\n\n return {\n newStorageJson: stringifyJson(migrationResult.storage),\n info,\n };\n}\n\n// =============================================================================\n// Initial Storage Creation\n// =============================================================================\n\n/**\n * Creates complete initial storage (block data + all plugin data) atomically.\n *\n * @param hooks - Dependencies for creating initial block and plugin data\n * @returns Initial storage as branded JSON string\n * @throws If initialDataFn or createPluginData throws\n */\nexport function createInitialStorage(hooks: InitialStorageHooks): StringifiedJson<BlockStorage> {\n const blockDefault = hooks.getDefaultBlockData();\n const pluginRegistry = hooks.getPluginRegistry();\n\n const plugins: Record<PluginHandle, VersionedData<unknown>> = {};\n for (const handle of Object.keys(pluginRegistry) as PluginHandle[]) {\n const initial = hooks.createPluginData(handle);\n plugins[handle] = { __dataVersion: initial.version, __data: initial.data };\n }\n\n const storage: BlockStorage = {\n [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,\n __dataVersion: blockDefault.version,\n __data: blockDefault.data,\n __pluginRegistry: pluginRegistry,\n __plugins: plugins,\n };\n return stringifyJson(storage);\n}\n\n// =============================================================================\n// Args Derivation from Storage\n// =============================================================================\n\n/**\n * Result of args derivation from storage.\n * Returned by __pl_args_derive and __pl_prerunArgs_derive callbacks.\n */\nexport type ArgsDeriveResult = { error: string } | { error?: undefined; value: unknown };\n\n/**\n * Derives args from storage using the provided args function.\n * This extracts data from storage and passes it to the block's args() function.\n *\n * @param storageJson - Storage as JSON string\n * @param argsFunction - The block's args derivation function\n * @returns ArgsDeriveResult with derived args or error\n */\nexport function deriveArgsFromStorage(\n storageJson: string,\n argsFunction: (data: unknown) => unknown,\n): ArgsDeriveResult {\n // Extract data from storage\n const { data } = normalizeStorage(storageJson);\n\n // Call the args function with extracted data\n try {\n const result = argsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `args() threw: ${errorMsg}` };\n }\n}\n\n/**\n * Derives prerunArgs from storage.\n * Uses prerunArgsFunction if provided, otherwise falls back to argsFunction.\n *\n * @param storageJson - Storage as JSON string\n * @param argsFunction - The block's args derivation function (fallback)\n * @param prerunArgsFunction - Optional prerun args derivation function\n * @returns ArgsDeriveResult with derived prerunArgs or error\n */\nexport function derivePrerunArgsFromStorage(\n storageJson: string,\n argsFunction: (data: unknown) => unknown,\n prerunArgsFunction?: (data: unknown) => unknown,\n): ArgsDeriveResult {\n // Extract data from storage\n const { data } = normalizeStorage(storageJson);\n\n // Try prerunArgs function first if available\n if (prerunArgsFunction) {\n try {\n const result = prerunArgsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `prerunArgs() threw: ${errorMsg}` };\n }\n }\n\n // Fall back to args function\n try {\n const result = argsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `args() threw (fallback): ${errorMsg}` };\n }\n}\n\n// Export discriminator key and schema version for external checks\nexport { BLOCK_STORAGE_KEY, BLOCK_STORAGE_SCHEMA_VERSION };\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
- import { BLOCK_STORAGE_KEY, BLOCK_STORAGE_SCHEMA_VERSION, createBlockStorage, getStorageData, isBlockStorage, migrateBlockStorage, normalizeBlockStorage, updateStorageData } from "./block_storage.js";
1
+ import { BLOCK_STORAGE_KEY, createBlockStorage, getStorageData, isBlockStorage, migrateBlockStorage, normalizeBlockStorage, updateStorageData } from "./block_storage.js";
2
2
  import { stringifyJson } from "@milaboratories/pl-model-common";
3
-
4
3
  //#region src/block_storage_callbacks.ts
5
4
  /**
6
5
  * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().
@@ -132,7 +131,7 @@ function createInitialStorage(hooks) {
132
131
  };
133
132
  }
134
133
  return stringifyJson({
135
- [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,
134
+ [BLOCK_STORAGE_KEY]: "v1",
136
135
  __dataVersion: blockDefault.version,
137
136
  __data: blockDefault.data,
138
137
  __pluginRegistry: pluginRegistry,
@@ -177,7 +176,7 @@ function derivePrerunArgsFromStorage(storageJson, argsFunction, prerunArgsFuncti
177
176
  return { error: `args() threw (fallback): ${e instanceof Error ? e.message : String(e)}` };
178
177
  }
179
178
  }
180
-
181
179
  //#endregion
182
180
  export { applyStorageUpdate, createInitialStorage, deriveArgsFromStorage, derivePrerunArgsFromStorage, getStorageDebugView, migrateStorage };
181
+
183
182
  //# sourceMappingURL=block_storage_callbacks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"block_storage_callbacks.js","names":[],"sources":["../src/block_storage_callbacks.ts"],"sourcesContent":["/**\n * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().\n *\n * Provides pure functions for storage operations (migration, initialization,\n * args derivation, updates, debug views). Each function takes its dependencies\n * explicitly as parameters.\n *\n * @module block_storage_callbacks\n * @internal\n */\n\nimport {\n BLOCK_STORAGE_KEY,\n BLOCK_STORAGE_SCHEMA_VERSION,\n type BlockStorage,\n type MutateStoragePayload,\n type PluginRegistry,\n type VersionedData,\n createBlockStorage,\n getStorageData,\n isBlockStorage,\n migrateBlockStorage,\n normalizeBlockStorage,\n updateStorageData,\n} from \"./block_storage\";\nimport type { PluginHandle } from \"./plugin_handle\";\n\nimport { stringifyJson, type StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport type { DataVersioned, TransferRecord } from \"./block_migrations\";\nimport type { StorageDebugView } from \"@milaboratories/pl-model-middle-layer\";\n\n// =============================================================================\n// Hook interfaces for dependency injection\n// =============================================================================\n\n/** Dependencies for storage migration */\nexport interface MigrationHooks {\n migrateBlockData: (versioned: DataVersioned<unknown>) => DataVersioned<unknown> & {\n transfers: TransferRecord;\n };\n getPluginRegistry: () => PluginRegistry;\n migratePluginData: (\n handle: PluginHandle,\n versioned: DataVersioned<unknown>,\n ) => DataVersioned<unknown> | undefined;\n createPluginData: (\n handle: PluginHandle,\n transfer?: DataVersioned<unknown>,\n ) => DataVersioned<unknown>;\n}\n\n/** Dependencies for initial storage creation */\nexport interface InitialStorageHooks {\n getDefaultBlockData: () => DataVersioned<unknown>;\n getPluginRegistry: () => PluginRegistry;\n createPluginData: (handle: PluginHandle) => DataVersioned<unknown>;\n}\n\n/**\n * Result of storage normalization\n */\nexport interface NormalizeStorageResult {\n /** The normalized BlockStorage object */\n storage: BlockStorage;\n /** The extracted data (what developers see) */\n data: unknown;\n}\n\n/**\n * Normalizes raw storage data and extracts state.\n * Handles all formats:\n * - New BlockStorage format (has discriminator)\n * - Legacy V1/V2 format ({ args, uiState })\n * - Raw V3 state (any other format)\n *\n * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)\n * @returns Object with normalized storage and extracted state\n */\nfunction normalizeStorage(rawStorage: unknown): NormalizeStorageResult {\n // Handle undefined/null\n if (rawStorage === undefined || rawStorage === null) {\n const storage = createBlockStorage({});\n return { storage, data: {} };\n }\n\n // Parse JSON string if needed\n let parsed = rawStorage;\n if (typeof rawStorage === \"string\") {\n try {\n parsed = JSON.parse(rawStorage);\n } catch {\n // If parsing fails, treat string as the data\n const storage = createBlockStorage(rawStorage);\n return { storage, data: rawStorage };\n }\n }\n\n // Check for BlockStorage format (has discriminator)\n if (isBlockStorage(parsed)) {\n const storage = normalizeBlockStorage(parsed);\n return { storage, data: getStorageData(storage) };\n }\n\n // Check for legacy V1/V2 format: { args, uiState }\n if (isLegacyModelV1ApiFormat(parsed)) {\n // For legacy format, the whole object IS the data\n const storage = createBlockStorage(parsed);\n return { storage, data: parsed };\n }\n\n // Raw V3 data - wrap it\n const storage = createBlockStorage(parsed);\n return { storage, data: parsed };\n}\n\n/**\n * Applies a state update to existing storage.\n * Used when setData is called from the frontend.\n *\n * @param currentStorageJson - Current storage as JSON string (must be defined)\n * @param payload - Update payload with operation type and value\n * @returns Updated storage as StringifiedJson<BlockStorage>\n */\nexport function applyStorageUpdate(\n currentStorageJson: string,\n payload: MutateStoragePayload,\n): StringifiedJson<BlockStorage> {\n const { storage: currentStorage } = normalizeStorage(currentStorageJson);\n\n // Update data while preserving other storage fields (version, plugins)\n const updatedStorage = updateStorageData(currentStorage, payload);\n\n return stringifyJson(updatedStorage);\n}\n\n/**\n * Checks if data is in legacy Model API v1 format.\n * Legacy format has { args, uiState? } at top level without the BlockStorage discriminator.\n */\nfunction isLegacyModelV1ApiFormat(data: unknown): data is { args?: unknown } {\n if (data === null || typeof data !== \"object\") return false;\n if (isBlockStorage(data)) return false;\n\n const obj = data as Record<string, unknown>;\n return \"args\" in obj;\n}\n\n// =============================================================================\n// Facade Callback Implementations\n// =============================================================================\n\n/**\n * Gets storage debug view from raw storage data.\n * Returns structured debug info about the storage state.\n *\n * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)\n * @returns JSON string with storage debug view\n */\nexport function getStorageDebugView(rawStorage: unknown): StringifiedJson<StorageDebugView> {\n const { storage } = normalizeStorage(rawStorage);\n const debugView: StorageDebugView = {\n dataVersion: storage.__dataVersion,\n data: storage.__data,\n };\n return stringifyJson(debugView);\n}\n\n// =============================================================================\n// Migration Support\n// =============================================================================\n\n/**\n * Result of storage migration.\n * Returned by __pl_storage_migrate callback.\n *\n * - Error result: { error: string } - serious failure (no context, etc.)\n * - Success result: { newStorageJson: StringifiedJson<BlockStorage>, info: string } - migration succeeded\n */\nexport type MigrationResult =\n | { error: string }\n | { error?: undefined; newStorageJson: StringifiedJson<BlockStorage>; info: string };\n\n/**\n * Runs storage migration using the provided hooks.\n * This is the main entry point for the middle layer to trigger migrations.\n *\n * @param currentStorageJson - Current storage as JSON string (or undefined)\n * @param hooks - Migration dependencies (block/plugin data migration and creation functions)\n * @returns MigrationResult\n */\nexport function migrateStorage(\n currentStorageJson: string | undefined,\n hooks: MigrationHooks,\n): MigrationResult {\n // Normalize current storage\n const { storage: currentStorage } = normalizeStorage(currentStorageJson);\n\n const newPluginRegistry = hooks.getPluginRegistry();\n\n // Perform atomic migration of block + all plugins\n const migrationResult = migrateBlockStorage(currentStorage, {\n migrateBlockData: hooks.migrateBlockData,\n migratePluginData: hooks.migratePluginData,\n newPluginRegistry,\n createPluginData: hooks.createPluginData,\n });\n\n if (!migrationResult.success) {\n return {\n error: `Migration failed at '${migrationResult.failedAt}': ${migrationResult.error}`,\n };\n }\n\n // Build info message\n const oldVersion = currentStorage.__dataVersion;\n const newVersion = migrationResult.storage.__dataVersion;\n const info =\n oldVersion === newVersion\n ? `No migration needed (${oldVersion})`\n : `Migrated ${oldVersion} -> ${newVersion}`;\n\n return {\n newStorageJson: stringifyJson(migrationResult.storage),\n info,\n };\n}\n\n// =============================================================================\n// Initial Storage Creation\n// =============================================================================\n\n/**\n * Creates complete initial storage (block data + all plugin data) atomically.\n *\n * @param hooks - Dependencies for creating initial block and plugin data\n * @returns Initial storage as branded JSON string\n * @throws If initialDataFn or createPluginData throws\n */\nexport function createInitialStorage(hooks: InitialStorageHooks): StringifiedJson<BlockStorage> {\n const blockDefault = hooks.getDefaultBlockData();\n const pluginRegistry = hooks.getPluginRegistry();\n\n const plugins: Record<PluginHandle, VersionedData<unknown>> = {};\n for (const handle of Object.keys(pluginRegistry) as PluginHandle[]) {\n const initial = hooks.createPluginData(handle);\n plugins[handle] = { __dataVersion: initial.version, __data: initial.data };\n }\n\n const storage: BlockStorage = {\n [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,\n __dataVersion: blockDefault.version,\n __data: blockDefault.data,\n __pluginRegistry: pluginRegistry,\n __plugins: plugins,\n };\n return stringifyJson(storage);\n}\n\n// =============================================================================\n// Args Derivation from Storage\n// =============================================================================\n\n/**\n * Result of args derivation from storage.\n * Returned by __pl_args_derive and __pl_prerunArgs_derive callbacks.\n */\nexport type ArgsDeriveResult = { error: string } | { error?: undefined; value: unknown };\n\n/**\n * Derives args from storage using the provided args function.\n * This extracts data from storage and passes it to the block's args() function.\n *\n * @param storageJson - Storage as JSON string\n * @param argsFunction - The block's args derivation function\n * @returns ArgsDeriveResult with derived args or error\n */\nexport function deriveArgsFromStorage(\n storageJson: string,\n argsFunction: (data: unknown) => unknown,\n): ArgsDeriveResult {\n // Extract data from storage\n const { data } = normalizeStorage(storageJson);\n\n // Call the args function with extracted data\n try {\n const result = argsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `args() threw: ${errorMsg}` };\n }\n}\n\n/**\n * Derives prerunArgs from storage.\n * Uses prerunArgsFunction if provided, otherwise falls back to argsFunction.\n *\n * @param storageJson - Storage as JSON string\n * @param argsFunction - The block's args derivation function (fallback)\n * @param prerunArgsFunction - Optional prerun args derivation function\n * @returns ArgsDeriveResult with derived prerunArgs or error\n */\nexport function derivePrerunArgsFromStorage(\n storageJson: string,\n argsFunction: (data: unknown) => unknown,\n prerunArgsFunction?: (data: unknown) => unknown,\n): ArgsDeriveResult {\n // Extract data from storage\n const { data } = normalizeStorage(storageJson);\n\n // Try prerunArgs function first if available\n if (prerunArgsFunction) {\n try {\n const result = prerunArgsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `prerunArgs() threw: ${errorMsg}` };\n }\n }\n\n // Fall back to args function\n try {\n const result = argsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `args() threw (fallback): ${errorMsg}` };\n }\n}\n\n// Export discriminator key and schema version for external checks\nexport { BLOCK_STORAGE_KEY, BLOCK_STORAGE_SCHEMA_VERSION };\n"],"mappings":"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"}
1
+ {"version":3,"file":"block_storage_callbacks.js","names":[],"sources":["../src/block_storage_callbacks.ts"],"sourcesContent":["/**\n * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().\n *\n * Provides pure functions for storage operations (migration, initialization,\n * args derivation, updates, debug views). Each function takes its dependencies\n * explicitly as parameters.\n *\n * @module block_storage_callbacks\n * @internal\n */\n\nimport {\n BLOCK_STORAGE_KEY,\n BLOCK_STORAGE_SCHEMA_VERSION,\n type BlockStorage,\n type MutateStoragePayload,\n type PluginRegistry,\n type VersionedData,\n createBlockStorage,\n getStorageData,\n isBlockStorage,\n migrateBlockStorage,\n normalizeBlockStorage,\n updateStorageData,\n} from \"./block_storage\";\nimport type { PluginHandle } from \"./plugin_handle\";\n\nimport { stringifyJson, type StringifiedJson } from \"@milaboratories/pl-model-common\";\nimport type { DataVersioned, TransferRecord } from \"./block_migrations\";\nimport type { StorageDebugView } from \"@milaboratories/pl-model-middle-layer\";\n\n// =============================================================================\n// Hook interfaces for dependency injection\n// =============================================================================\n\n/** Dependencies for storage migration */\nexport interface MigrationHooks {\n migrateBlockData: (versioned: DataVersioned<unknown>) => DataVersioned<unknown> & {\n transfers: TransferRecord;\n };\n getPluginRegistry: () => PluginRegistry;\n migratePluginData: (\n handle: PluginHandle,\n versioned: DataVersioned<unknown>,\n ) => DataVersioned<unknown> | undefined;\n createPluginData: (\n handle: PluginHandle,\n transfer?: DataVersioned<unknown>,\n ) => DataVersioned<unknown>;\n}\n\n/** Dependencies for initial storage creation */\nexport interface InitialStorageHooks {\n getDefaultBlockData: () => DataVersioned<unknown>;\n getPluginRegistry: () => PluginRegistry;\n createPluginData: (handle: PluginHandle) => DataVersioned<unknown>;\n}\n\n/**\n * Result of storage normalization\n */\nexport interface NormalizeStorageResult {\n /** The normalized BlockStorage object */\n storage: BlockStorage;\n /** The extracted data (what developers see) */\n data: unknown;\n}\n\n/**\n * Normalizes raw storage data and extracts state.\n * Handles all formats:\n * - New BlockStorage format (has discriminator)\n * - Legacy V1/V2 format ({ args, uiState })\n * - Raw V3 state (any other format)\n *\n * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)\n * @returns Object with normalized storage and extracted state\n */\nfunction normalizeStorage(rawStorage: unknown): NormalizeStorageResult {\n // Handle undefined/null\n if (rawStorage === undefined || rawStorage === null) {\n const storage = createBlockStorage({});\n return { storage, data: {} };\n }\n\n // Parse JSON string if needed\n let parsed = rawStorage;\n if (typeof rawStorage === \"string\") {\n try {\n parsed = JSON.parse(rawStorage);\n } catch {\n // If parsing fails, treat string as the data\n const storage = createBlockStorage(rawStorage);\n return { storage, data: rawStorage };\n }\n }\n\n // Check for BlockStorage format (has discriminator)\n if (isBlockStorage(parsed)) {\n const storage = normalizeBlockStorage(parsed);\n return { storage, data: getStorageData(storage) };\n }\n\n // Check for legacy V1/V2 format: { args, uiState }\n if (isLegacyModelV1ApiFormat(parsed)) {\n // For legacy format, the whole object IS the data\n const storage = createBlockStorage(parsed);\n return { storage, data: parsed };\n }\n\n // Raw V3 data - wrap it\n const storage = createBlockStorage(parsed);\n return { storage, data: parsed };\n}\n\n/**\n * Applies a state update to existing storage.\n * Used when setData is called from the frontend.\n *\n * @param currentStorageJson - Current storage as JSON string (must be defined)\n * @param payload - Update payload with operation type and value\n * @returns Updated storage as StringifiedJson<BlockStorage>\n */\nexport function applyStorageUpdate(\n currentStorageJson: string,\n payload: MutateStoragePayload,\n): StringifiedJson<BlockStorage> {\n const { storage: currentStorage } = normalizeStorage(currentStorageJson);\n\n // Update data while preserving other storage fields (version, plugins)\n const updatedStorage = updateStorageData(currentStorage, payload);\n\n return stringifyJson(updatedStorage);\n}\n\n/**\n * Checks if data is in legacy Model API v1 format.\n * Legacy format has { args, uiState? } at top level without the BlockStorage discriminator.\n */\nfunction isLegacyModelV1ApiFormat(data: unknown): data is { args?: unknown } {\n if (data === null || typeof data !== \"object\") return false;\n if (isBlockStorage(data)) return false;\n\n const obj = data as Record<string, unknown>;\n return \"args\" in obj;\n}\n\n// =============================================================================\n// Facade Callback Implementations\n// =============================================================================\n\n/**\n * Gets storage debug view from raw storage data.\n * Returns structured debug info about the storage state.\n *\n * @param rawStorage - Raw data from blockStorage field (may be JSON string or object)\n * @returns JSON string with storage debug view\n */\nexport function getStorageDebugView(rawStorage: unknown): StringifiedJson<StorageDebugView> {\n const { storage } = normalizeStorage(rawStorage);\n const debugView: StorageDebugView = {\n dataVersion: storage.__dataVersion,\n data: storage.__data,\n };\n return stringifyJson(debugView);\n}\n\n// =============================================================================\n// Migration Support\n// =============================================================================\n\n/**\n * Result of storage migration.\n * Returned by __pl_storage_migrate callback.\n *\n * - Error result: { error: string } - serious failure (no context, etc.)\n * - Success result: { newStorageJson: StringifiedJson<BlockStorage>, info: string } - migration succeeded\n */\nexport type MigrationResult =\n | { error: string }\n | { error?: undefined; newStorageJson: StringifiedJson<BlockStorage>; info: string };\n\n/**\n * Runs storage migration using the provided hooks.\n * This is the main entry point for the middle layer to trigger migrations.\n *\n * @param currentStorageJson - Current storage as JSON string (or undefined)\n * @param hooks - Migration dependencies (block/plugin data migration and creation functions)\n * @returns MigrationResult\n */\nexport function migrateStorage(\n currentStorageJson: string | undefined,\n hooks: MigrationHooks,\n): MigrationResult {\n // Normalize current storage\n const { storage: currentStorage } = normalizeStorage(currentStorageJson);\n\n const newPluginRegistry = hooks.getPluginRegistry();\n\n // Perform atomic migration of block + all plugins\n const migrationResult = migrateBlockStorage(currentStorage, {\n migrateBlockData: hooks.migrateBlockData,\n migratePluginData: hooks.migratePluginData,\n newPluginRegistry,\n createPluginData: hooks.createPluginData,\n });\n\n if (!migrationResult.success) {\n return {\n error: `Migration failed at '${migrationResult.failedAt}': ${migrationResult.error}`,\n };\n }\n\n // Build info message\n const oldVersion = currentStorage.__dataVersion;\n const newVersion = migrationResult.storage.__dataVersion;\n const info =\n oldVersion === newVersion\n ? `No migration needed (${oldVersion})`\n : `Migrated ${oldVersion} -> ${newVersion}`;\n\n return {\n newStorageJson: stringifyJson(migrationResult.storage),\n info,\n };\n}\n\n// =============================================================================\n// Initial Storage Creation\n// =============================================================================\n\n/**\n * Creates complete initial storage (block data + all plugin data) atomically.\n *\n * @param hooks - Dependencies for creating initial block and plugin data\n * @returns Initial storage as branded JSON string\n * @throws If initialDataFn or createPluginData throws\n */\nexport function createInitialStorage(hooks: InitialStorageHooks): StringifiedJson<BlockStorage> {\n const blockDefault = hooks.getDefaultBlockData();\n const pluginRegistry = hooks.getPluginRegistry();\n\n const plugins: Record<PluginHandle, VersionedData<unknown>> = {};\n for (const handle of Object.keys(pluginRegistry) as PluginHandle[]) {\n const initial = hooks.createPluginData(handle);\n plugins[handle] = { __dataVersion: initial.version, __data: initial.data };\n }\n\n const storage: BlockStorage = {\n [BLOCK_STORAGE_KEY]: BLOCK_STORAGE_SCHEMA_VERSION,\n __dataVersion: blockDefault.version,\n __data: blockDefault.data,\n __pluginRegistry: pluginRegistry,\n __plugins: plugins,\n };\n return stringifyJson(storage);\n}\n\n// =============================================================================\n// Args Derivation from Storage\n// =============================================================================\n\n/**\n * Result of args derivation from storage.\n * Returned by __pl_args_derive and __pl_prerunArgs_derive callbacks.\n */\nexport type ArgsDeriveResult = { error: string } | { error?: undefined; value: unknown };\n\n/**\n * Derives args from storage using the provided args function.\n * This extracts data from storage and passes it to the block's args() function.\n *\n * @param storageJson - Storage as JSON string\n * @param argsFunction - The block's args derivation function\n * @returns ArgsDeriveResult with derived args or error\n */\nexport function deriveArgsFromStorage(\n storageJson: string,\n argsFunction: (data: unknown) => unknown,\n): ArgsDeriveResult {\n // Extract data from storage\n const { data } = normalizeStorage(storageJson);\n\n // Call the args function with extracted data\n try {\n const result = argsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `args() threw: ${errorMsg}` };\n }\n}\n\n/**\n * Derives prerunArgs from storage.\n * Uses prerunArgsFunction if provided, otherwise falls back to argsFunction.\n *\n * @param storageJson - Storage as JSON string\n * @param argsFunction - The block's args derivation function (fallback)\n * @param prerunArgsFunction - Optional prerun args derivation function\n * @returns ArgsDeriveResult with derived prerunArgs or error\n */\nexport function derivePrerunArgsFromStorage(\n storageJson: string,\n argsFunction: (data: unknown) => unknown,\n prerunArgsFunction?: (data: unknown) => unknown,\n): ArgsDeriveResult {\n // Extract data from storage\n const { data } = normalizeStorage(storageJson);\n\n // Try prerunArgs function first if available\n if (prerunArgsFunction) {\n try {\n const result = prerunArgsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `prerunArgs() threw: ${errorMsg}` };\n }\n }\n\n // Fall back to args function\n try {\n const result = argsFunction(data);\n return { value: result };\n } catch (e) {\n const errorMsg = e instanceof Error ? e.message : String(e);\n return { error: `args() threw (fallback): ${errorMsg}` };\n }\n}\n\n// Export discriminator key and schema version for external checks\nexport { BLOCK_STORAGE_KEY, BLOCK_STORAGE_SCHEMA_VERSION };\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
- const require_internal = require('./internal.cjs');
2
-
1
+ const require_internal = require("./internal.cjs");
3
2
  //#region src/block_storage_facade.ts
4
3
  /**
5
4
  * The current facade version. This value is used for `requiresModelAPIVersion`
@@ -39,10 +38,10 @@ const BlockStorageFacadeHandles = createFacadeHandles(BlockStorageFacadeCallback
39
38
  function registerFacadeCallbacks(callbacks) {
40
39
  for (const key of Object.values(BlockStorageFacadeCallbacks)) require_internal.tryRegisterCallback(key, callbacks[key]);
41
40
  }
42
-
43
41
  //#endregion
44
42
  exports.BLOCK_STORAGE_FACADE_VERSION = BLOCK_STORAGE_FACADE_VERSION;
45
43
  exports.BlockStorageFacadeCallbacks = BlockStorageFacadeCallbacks;
46
44
  exports.BlockStorageFacadeHandles = BlockStorageFacadeHandles;
47
45
  exports.registerFacadeCallbacks = registerFacadeCallbacks;
46
+
48
47
  //# sourceMappingURL=block_storage_facade.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"block_storage_facade.cjs","names":["createRenderLambda"],"sources":["../src/block_storage_facade.ts"],"sourcesContent":["/**\n * Block Storage Facade - Contract between bundled blocks and middle layer.\n *\n * ============================================================================\n * VERSIONING\n * ============================================================================\n *\n * Blocks declare their model API version via the `requiresModelAPIVersion` feature flag\n * (see BlockCodeKnownFeatureFlags). This determines how the middle layer manages block state:\n *\n * - Version 1: Legacy BlockModel - state is {args, uiState}, managed directly by middle layer\n * - Version 2: BlockModelV3 - uses blockStorage with VM-based callbacks (this facade)\n *\n * This facade (BlockStorageFacade) is used by blocks with `requiresModelAPIVersion: 2`.\n * The version number matches the model API version for clarity.\n *\n * ============================================================================\n * BACKWARD COMPATIBILITY WARNING\n * ============================================================================\n *\n * This file documents the FACADE between the SDK (bundled into blocks) and the\n * middle layer. Once a block is published, its SDK version is frozen. The middle\n * layer must support ALL previously released callback signatures indefinitely.\n *\n * RULES:\n * 1. NEVER change the signature of existing callbacks\n * 2. NEVER remove existing callbacks\n * 3. New callbacks CAN be added (old blocks won't register them, middle layer\n * should handle missing callbacks gracefully)\n * 4. Callback return types can be EXTENDED (add optional fields) but not changed\n * 5. Callback parameter types should remain compatible (middle layer may need\n * to handle both old and new formats)\n *\n * The facade consists of callbacks registered via `tryRegisterCallback()` with\n * the `__pl_` prefix. These are registered by the SDK when a block loads and\n * called by the middle layer to perform operations.\n *\n * ============================================================================\n * WHAT CAN BE CHANGED FREELY\n * ============================================================================\n *\n * - Middle layer code (lib/node/pl-middle-layer)\n * - SDK internal implementation (as long as callback contracts are preserved)\n * - SDK exports used ONLY by middle layer (not by blocks themselves)\n * - New SDK features that don't affect existing callbacks\n *\n * @module block_storage_facade\n */\n\nimport type { MutateStoragePayload } from \"./block_storage\";\nimport type { ConfigRenderLambda } from \"./bconfig\";\nimport { createRenderLambda, tryRegisterCallback } from \"./internal\";\nimport type { StringifiedJson } from \"@milaboratories/pl-model-common\";\n\n// =============================================================================\n// Facade Version\n// =============================================================================\n\n/**\n * The current facade version. This value is used for `requiresModelAPIVersion`\n * feature flag in BlockModelV3.\n */\nexport const BLOCK_STORAGE_FACADE_VERSION = 2;\n\n// =============================================================================\n// Facade Callback Names\n// =============================================================================\n\n/**\n * All facade callback names as constants.\n * These are the source of truth - the interface is derived from these.\n *\n * IMPORTANT: When adding a new callback:\n * 1. Add the constant here\n * 2. Add the callback signature to FacadeCallbackTypes below\n * 3. The BlockStorageFacade type will automatically include it\n */\nexport const BlockStorageFacadeCallbacks = {\n StorageApplyUpdate: \"__pl_storage_applyUpdate\",\n StorageDebugView: \"__pl_storage_debugView\",\n StorageMigrate: \"__pl_storage_migrate\",\n ArgsDerive: \"__pl_args_derive\",\n PrerunArgsDerive: \"__pl_prerunArgs_derive\",\n StorageInitial: \"__pl_storage_initial\",\n} as const;\n\n/**\n * Creates a map of lambda handles from a callbacks constant object.\n * Keys are the callback string values (e.g., '__pl_storage_applyUpdate').\n */\nfunction createFacadeHandles<T extends Record<string, string>>(\n callbacks: T,\n): { [K in T[keyof T]]: ConfigRenderLambda } {\n return Object.fromEntries(\n Object.values(callbacks).map((handle) => [handle, createRenderLambda({ handle })]),\n ) as { [K in T[keyof T]]: ConfigRenderLambda };\n}\n\n/**\n * Lambda handles for facade callbacks.\n * Used by the middle layer to invoke callbacks via executeSingleLambda().\n */\nexport const BlockStorageFacadeHandles = createFacadeHandles(BlockStorageFacadeCallbacks);\n\n// =============================================================================\n// Facade Interface (source of truth for callback signatures)\n// =============================================================================\n\n/**\n * The complete facade interface between bundled blocks (SDK) and middle layer.\n *\n * This interface defines ALL callbacks that a block registers. The middle layer\n * calls these callbacks to perform storage operations.\n *\n * ALL types are inlined to simplify versioning - when a callback changes,\n * the entire signature is visible in one place.\n *\n * BACKWARD COMPATIBILITY:\n * - This interface can only be EXTENDED, never shrunk\n * - Existing callback signatures MUST NOT change\n * - Middle layer should use Partial<BlockStorageFacade> when dealing with\n * blocks of unknown version (older blocks may not have all callbacks)\n *\n * Each callback is documented with:\n * - Purpose and when it's called\n * - Parameter descriptions\n * - Return value description\n */\nexport interface BlockStorageFacade {\n /**\n * Apply state update to storage.\n * Called when UI updates block state (setState) or plugin data.\n * @param currentStorageJson - Current storage as JSON string\n * @param payload - Update payload with operation type and value\n * @returns Updated storage as JSON string\n */\n [BlockStorageFacadeCallbacks.StorageApplyUpdate]: (\n currentStorageJson: StringifiedJson,\n payload: MutateStoragePayload,\n ) => StringifiedJson;\n\n /**\n * Get debug view of storage.\n * Called by developer tools to inspect storage state.\n * @param storageJson - Storage as JSON string (or undefined for new blocks)\n * @returns JSON string containing StorageDebugView\n */\n [BlockStorageFacadeCallbacks.StorageDebugView]: (\n storageJson: StringifiedJson | undefined,\n ) => StringifiedJson;\n\n /**\n * Run storage migration.\n * Called when block loads to migrate data to latest version.\n * @param currentStorageJson - Current storage as JSON string (or undefined for new blocks)\n * @returns Migration result - either error or success with new storage\n */\n [BlockStorageFacadeCallbacks.StorageMigrate]: (currentStorageJson: StringifiedJson | undefined) =>\n | { error: string }\n | {\n error?: undefined;\n newStorageJson: StringifiedJson;\n info: string;\n };\n\n /**\n * Derive args from storage.\n * Called to get block configuration args from storage.\n * @param storageJson - Storage as JSON string\n * @returns Args derivation result - either error or derived value\n */\n [BlockStorageFacadeCallbacks.ArgsDerive]: (\n storageJson: StringifiedJson,\n ) => { error: string } | { error?: undefined; value: unknown };\n\n /**\n * Derive prerunArgs from storage.\n * Called to get prerun args; falls back to args callback if not registered.\n * @param storageJson - Storage as JSON string\n * @returns Args derivation result - either error or derived value\n */\n [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (\n storageJson: StringifiedJson,\n ) => { error: string } | { error?: undefined; value: unknown };\n\n /**\n * Get initial storage JSON for new blocks.\n * Called when creating a new block to get complete initial storage.\n * @returns Initial storage as JSON string\n */\n [BlockStorageFacadeCallbacks.StorageInitial]: () => StringifiedJson;\n}\n\n/** Register all facade callbacks at once. Ensures all required callbacks are provided. */\nexport function registerFacadeCallbacks(callbacks: BlockStorageFacade): void {\n for (const key of Object.values(BlockStorageFacadeCallbacks)) {\n tryRegisterCallback(key, callbacks[key] as (...args: any[]) => any);\n }\n}\n"],"mappings":";;;;;;;AA8DA,MAAa,+BAA+B;;;;;;;;;;AAe5C,MAAa,8BAA8B;CACzC,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,YAAY;CACZ,kBAAkB;CAClB,gBAAgB;CACjB;;;;;AAMD,SAAS,oBACP,WAC2C;AAC3C,QAAO,OAAO,YACZ,OAAO,OAAO,UAAU,CAAC,KAAK,WAAW,CAAC,QAAQA,oCAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,CACnF;;;;;;AAOH,MAAa,4BAA4B,oBAAoB,4BAA4B;;AA4FzF,SAAgB,wBAAwB,WAAqC;AAC3E,MAAK,MAAM,OAAO,OAAO,OAAO,4BAA4B,CAC1D,sCAAoB,KAAK,UAAU,KAAgC"}
1
+ {"version":3,"file":"block_storage_facade.cjs","names":["createRenderLambda"],"sources":["../src/block_storage_facade.ts"],"sourcesContent":["/**\n * Block Storage Facade - Contract between bundled blocks and middle layer.\n *\n * ============================================================================\n * VERSIONING\n * ============================================================================\n *\n * Blocks declare their model API version via the `requiresModelAPIVersion` feature flag\n * (see BlockCodeKnownFeatureFlags). This determines how the middle layer manages block state:\n *\n * - Version 1: Legacy BlockModel - state is {args, uiState}, managed directly by middle layer\n * - Version 2: BlockModelV3 - uses blockStorage with VM-based callbacks (this facade)\n *\n * This facade (BlockStorageFacade) is used by blocks with `requiresModelAPIVersion: 2`.\n * The version number matches the model API version for clarity.\n *\n * ============================================================================\n * BACKWARD COMPATIBILITY WARNING\n * ============================================================================\n *\n * This file documents the FACADE between the SDK (bundled into blocks) and the\n * middle layer. Once a block is published, its SDK version is frozen. The middle\n * layer must support ALL previously released callback signatures indefinitely.\n *\n * RULES:\n * 1. NEVER change the signature of existing callbacks\n * 2. NEVER remove existing callbacks\n * 3. New callbacks CAN be added (old blocks won't register them, middle layer\n * should handle missing callbacks gracefully)\n * 4. Callback return types can be EXTENDED (add optional fields) but not changed\n * 5. Callback parameter types should remain compatible (middle layer may need\n * to handle both old and new formats)\n *\n * The facade consists of callbacks registered via `tryRegisterCallback()` with\n * the `__pl_` prefix. These are registered by the SDK when a block loads and\n * called by the middle layer to perform operations.\n *\n * ============================================================================\n * WHAT CAN BE CHANGED FREELY\n * ============================================================================\n *\n * - Middle layer code (lib/node/pl-middle-layer)\n * - SDK internal implementation (as long as callback contracts are preserved)\n * - SDK exports used ONLY by middle layer (not by blocks themselves)\n * - New SDK features that don't affect existing callbacks\n *\n * @module block_storage_facade\n */\n\nimport type { MutateStoragePayload } from \"./block_storage\";\nimport type { ConfigRenderLambda } from \"./bconfig\";\nimport { createRenderLambda, tryRegisterCallback } from \"./internal\";\nimport type { StringifiedJson } from \"@milaboratories/pl-model-common\";\n\n// =============================================================================\n// Facade Version\n// =============================================================================\n\n/**\n * The current facade version. This value is used for `requiresModelAPIVersion`\n * feature flag in BlockModelV3.\n */\nexport const BLOCK_STORAGE_FACADE_VERSION = 2;\n\n// =============================================================================\n// Facade Callback Names\n// =============================================================================\n\n/**\n * All facade callback names as constants.\n * These are the source of truth - the interface is derived from these.\n *\n * IMPORTANT: When adding a new callback:\n * 1. Add the constant here\n * 2. Add the callback signature to FacadeCallbackTypes below\n * 3. The BlockStorageFacade type will automatically include it\n */\nexport const BlockStorageFacadeCallbacks = {\n StorageApplyUpdate: \"__pl_storage_applyUpdate\",\n StorageDebugView: \"__pl_storage_debugView\",\n StorageMigrate: \"__pl_storage_migrate\",\n ArgsDerive: \"__pl_args_derive\",\n PrerunArgsDerive: \"__pl_prerunArgs_derive\",\n StorageInitial: \"__pl_storage_initial\",\n} as const;\n\n/**\n * Creates a map of lambda handles from a callbacks constant object.\n * Keys are the callback string values (e.g., '__pl_storage_applyUpdate').\n */\nfunction createFacadeHandles<T extends Record<string, string>>(\n callbacks: T,\n): { [K in T[keyof T]]: ConfigRenderLambda } {\n return Object.fromEntries(\n Object.values(callbacks).map((handle) => [handle, createRenderLambda({ handle })]),\n ) as { [K in T[keyof T]]: ConfigRenderLambda };\n}\n\n/**\n * Lambda handles for facade callbacks.\n * Used by the middle layer to invoke callbacks via executeSingleLambda().\n */\nexport const BlockStorageFacadeHandles = createFacadeHandles(BlockStorageFacadeCallbacks);\n\n// =============================================================================\n// Facade Interface (source of truth for callback signatures)\n// =============================================================================\n\n/**\n * The complete facade interface between bundled blocks (SDK) and middle layer.\n *\n * This interface defines ALL callbacks that a block registers. The middle layer\n * calls these callbacks to perform storage operations.\n *\n * ALL types are inlined to simplify versioning - when a callback changes,\n * the entire signature is visible in one place.\n *\n * BACKWARD COMPATIBILITY:\n * - This interface can only be EXTENDED, never shrunk\n * - Existing callback signatures MUST NOT change\n * - Middle layer should use Partial<BlockStorageFacade> when dealing with\n * blocks of unknown version (older blocks may not have all callbacks)\n *\n * Each callback is documented with:\n * - Purpose and when it's called\n * - Parameter descriptions\n * - Return value description\n */\nexport interface BlockStorageFacade {\n /**\n * Apply state update to storage.\n * Called when UI updates block state (setState) or plugin data.\n * @param currentStorageJson - Current storage as JSON string\n * @param payload - Update payload with operation type and value\n * @returns Updated storage as JSON string\n */\n [BlockStorageFacadeCallbacks.StorageApplyUpdate]: (\n currentStorageJson: StringifiedJson,\n payload: MutateStoragePayload,\n ) => StringifiedJson;\n\n /**\n * Get debug view of storage.\n * Called by developer tools to inspect storage state.\n * @param storageJson - Storage as JSON string (or undefined for new blocks)\n * @returns JSON string containing StorageDebugView\n */\n [BlockStorageFacadeCallbacks.StorageDebugView]: (\n storageJson: StringifiedJson | undefined,\n ) => StringifiedJson;\n\n /**\n * Run storage migration.\n * Called when block loads to migrate data to latest version.\n * @param currentStorageJson - Current storage as JSON string (or undefined for new blocks)\n * @returns Migration result - either error or success with new storage\n */\n [BlockStorageFacadeCallbacks.StorageMigrate]: (currentStorageJson: StringifiedJson | undefined) =>\n | { error: string }\n | {\n error?: undefined;\n newStorageJson: StringifiedJson;\n info: string;\n };\n\n /**\n * Derive args from storage.\n * Called to get block configuration args from storage.\n * @param storageJson - Storage as JSON string\n * @returns Args derivation result - either error or derived value\n */\n [BlockStorageFacadeCallbacks.ArgsDerive]: (\n storageJson: StringifiedJson,\n ) => { error: string } | { error?: undefined; value: unknown };\n\n /**\n * Derive prerunArgs from storage.\n * Called to get prerun args; falls back to args callback if not registered.\n * @param storageJson - Storage as JSON string\n * @returns Args derivation result - either error or derived value\n */\n [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (\n storageJson: StringifiedJson,\n ) => { error: string } | { error?: undefined; value: unknown };\n\n /**\n * Get initial storage JSON for new blocks.\n * Called when creating a new block to get complete initial storage.\n * @returns Initial storage as JSON string\n */\n [BlockStorageFacadeCallbacks.StorageInitial]: () => StringifiedJson;\n}\n\n/** Register all facade callbacks at once. Ensures all required callbacks are provided. */\nexport function registerFacadeCallbacks(callbacks: BlockStorageFacade): void {\n for (const key of Object.values(BlockStorageFacadeCallbacks)) {\n tryRegisterCallback(key, callbacks[key] as (...args: any[]) => any);\n }\n}\n"],"mappings":";;;;;;AA8DA,MAAa,+BAA+B;;;;;;;;;;AAe5C,MAAa,8BAA8B;CACzC,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,YAAY;CACZ,kBAAkB;CAClB,gBAAgB;CACjB;;;;;AAMD,SAAS,oBACP,WAC2C;AAC3C,QAAO,OAAO,YACZ,OAAO,OAAO,UAAU,CAAC,KAAK,WAAW,CAAC,QAAQA,iBAAAA,mBAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,CACnF;;;;;;AAOH,MAAa,4BAA4B,oBAAoB,4BAA4B;;AA4FzF,SAAgB,wBAAwB,WAAqC;AAC3E,MAAK,MAAM,OAAO,OAAO,OAAO,4BAA4B,CAC1D,kBAAA,oBAAoB,KAAK,UAAU,KAAgC"}
@@ -1,6 +1,5 @@
1
1
  import { MutateStoragePayload } from "./block_storage.js";
2
2
  import { ConfigRenderLambda } from "./bconfig/lambdas.js";
3
- import "./bconfig/index.js";
4
3
  import { StringifiedJson } from "@milaboratories/pl-model-common";
5
4
 
6
5
  //#region src/block_storage_facade.d.ts
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block_storage_facade.d.ts","names":[],"sources":["../src/block_storage_facade.ts"],"mappings":";;;;;;;;;cA8Da,4BAAA;;;;;;;;;;cAeA,2BAAA;EAAA;;;;;;;;;;;cAyBA,yBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA0BI,kBAAA;EAuDR;;;;;;;EAAA,CA/CN,2BAAA,CAA4B,kBAAA,IAC3B,kBAAA,EAAoB,eAAA,EACpB,OAAA,EAAS,oBAAA,KACN,eAAA;EAmD8D;AAIrE;;;;;EAJqE,CA3ClE,2BAAA,CAA4B,gBAAA,IAC3B,WAAA,EAAa,eAAA,iBACV,eAAA;;;;;;;GAQJ,2BAAA,CAA4B,cAAA,IAAkB,kBAAA,EAAoB,eAAA;IAC7D,KAAA;EAAA;IAEA,KAAA;IACA,cAAA,EAAgB,eAAA;IAChB,IAAA;EAAA;;;;;;;GASL,2BAAA,CAA4B,UAAA,IAC3B,WAAA,EAAa,eAAA;IACR,KAAA;EAAA;IAAoB,KAAA;IAAmB,KAAA;EAAA;;;;;;;GAQ7C,2BAAA,CAA4B,gBAAA,IAC3B,WAAA,EAAa,eAAA;IACR,KAAA;EAAA;IAAoB,KAAA;IAAmB,KAAA;EAAA;;;;;;GAO7C,2BAAA,CAA4B,cAAA,SAAuB,eAAA;AAAA;;iBAItC,uBAAA,CAAwB,SAAA,EAAW,kBAAA"}
@@ -1,5 +1,4 @@
1
1
  import { createRenderLambda, tryRegisterCallback } from "./internal.js";
2
-
3
2
  //#region src/block_storage_facade.ts
4
3
  /**
5
4
  * The current facade version. This value is used for `requiresModelAPIVersion`
@@ -39,7 +38,7 @@ const BlockStorageFacadeHandles = createFacadeHandles(BlockStorageFacadeCallback
39
38
  function registerFacadeCallbacks(callbacks) {
40
39
  for (const key of Object.values(BlockStorageFacadeCallbacks)) tryRegisterCallback(key, callbacks[key]);
41
40
  }
42
-
43
41
  //#endregion
44
42
  export { BLOCK_STORAGE_FACADE_VERSION, BlockStorageFacadeCallbacks, BlockStorageFacadeHandles, registerFacadeCallbacks };
43
+
45
44
  //# sourceMappingURL=block_storage_facade.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"block_storage_facade.js","names":[],"sources":["../src/block_storage_facade.ts"],"sourcesContent":["/**\n * Block Storage Facade - Contract between bundled blocks and middle layer.\n *\n * ============================================================================\n * VERSIONING\n * ============================================================================\n *\n * Blocks declare their model API version via the `requiresModelAPIVersion` feature flag\n * (see BlockCodeKnownFeatureFlags). This determines how the middle layer manages block state:\n *\n * - Version 1: Legacy BlockModel - state is {args, uiState}, managed directly by middle layer\n * - Version 2: BlockModelV3 - uses blockStorage with VM-based callbacks (this facade)\n *\n * This facade (BlockStorageFacade) is used by blocks with `requiresModelAPIVersion: 2`.\n * The version number matches the model API version for clarity.\n *\n * ============================================================================\n * BACKWARD COMPATIBILITY WARNING\n * ============================================================================\n *\n * This file documents the FACADE between the SDK (bundled into blocks) and the\n * middle layer. Once a block is published, its SDK version is frozen. The middle\n * layer must support ALL previously released callback signatures indefinitely.\n *\n * RULES:\n * 1. NEVER change the signature of existing callbacks\n * 2. NEVER remove existing callbacks\n * 3. New callbacks CAN be added (old blocks won't register them, middle layer\n * should handle missing callbacks gracefully)\n * 4. Callback return types can be EXTENDED (add optional fields) but not changed\n * 5. Callback parameter types should remain compatible (middle layer may need\n * to handle both old and new formats)\n *\n * The facade consists of callbacks registered via `tryRegisterCallback()` with\n * the `__pl_` prefix. These are registered by the SDK when a block loads and\n * called by the middle layer to perform operations.\n *\n * ============================================================================\n * WHAT CAN BE CHANGED FREELY\n * ============================================================================\n *\n * - Middle layer code (lib/node/pl-middle-layer)\n * - SDK internal implementation (as long as callback contracts are preserved)\n * - SDK exports used ONLY by middle layer (not by blocks themselves)\n * - New SDK features that don't affect existing callbacks\n *\n * @module block_storage_facade\n */\n\nimport type { MutateStoragePayload } from \"./block_storage\";\nimport type { ConfigRenderLambda } from \"./bconfig\";\nimport { createRenderLambda, tryRegisterCallback } from \"./internal\";\nimport type { StringifiedJson } from \"@milaboratories/pl-model-common\";\n\n// =============================================================================\n// Facade Version\n// =============================================================================\n\n/**\n * The current facade version. This value is used for `requiresModelAPIVersion`\n * feature flag in BlockModelV3.\n */\nexport const BLOCK_STORAGE_FACADE_VERSION = 2;\n\n// =============================================================================\n// Facade Callback Names\n// =============================================================================\n\n/**\n * All facade callback names as constants.\n * These are the source of truth - the interface is derived from these.\n *\n * IMPORTANT: When adding a new callback:\n * 1. Add the constant here\n * 2. Add the callback signature to FacadeCallbackTypes below\n * 3. The BlockStorageFacade type will automatically include it\n */\nexport const BlockStorageFacadeCallbacks = {\n StorageApplyUpdate: \"__pl_storage_applyUpdate\",\n StorageDebugView: \"__pl_storage_debugView\",\n StorageMigrate: \"__pl_storage_migrate\",\n ArgsDerive: \"__pl_args_derive\",\n PrerunArgsDerive: \"__pl_prerunArgs_derive\",\n StorageInitial: \"__pl_storage_initial\",\n} as const;\n\n/**\n * Creates a map of lambda handles from a callbacks constant object.\n * Keys are the callback string values (e.g., '__pl_storage_applyUpdate').\n */\nfunction createFacadeHandles<T extends Record<string, string>>(\n callbacks: T,\n): { [K in T[keyof T]]: ConfigRenderLambda } {\n return Object.fromEntries(\n Object.values(callbacks).map((handle) => [handle, createRenderLambda({ handle })]),\n ) as { [K in T[keyof T]]: ConfigRenderLambda };\n}\n\n/**\n * Lambda handles for facade callbacks.\n * Used by the middle layer to invoke callbacks via executeSingleLambda().\n */\nexport const BlockStorageFacadeHandles = createFacadeHandles(BlockStorageFacadeCallbacks);\n\n// =============================================================================\n// Facade Interface (source of truth for callback signatures)\n// =============================================================================\n\n/**\n * The complete facade interface between bundled blocks (SDK) and middle layer.\n *\n * This interface defines ALL callbacks that a block registers. The middle layer\n * calls these callbacks to perform storage operations.\n *\n * ALL types are inlined to simplify versioning - when a callback changes,\n * the entire signature is visible in one place.\n *\n * BACKWARD COMPATIBILITY:\n * - This interface can only be EXTENDED, never shrunk\n * - Existing callback signatures MUST NOT change\n * - Middle layer should use Partial<BlockStorageFacade> when dealing with\n * blocks of unknown version (older blocks may not have all callbacks)\n *\n * Each callback is documented with:\n * - Purpose and when it's called\n * - Parameter descriptions\n * - Return value description\n */\nexport interface BlockStorageFacade {\n /**\n * Apply state update to storage.\n * Called when UI updates block state (setState) or plugin data.\n * @param currentStorageJson - Current storage as JSON string\n * @param payload - Update payload with operation type and value\n * @returns Updated storage as JSON string\n */\n [BlockStorageFacadeCallbacks.StorageApplyUpdate]: (\n currentStorageJson: StringifiedJson,\n payload: MutateStoragePayload,\n ) => StringifiedJson;\n\n /**\n * Get debug view of storage.\n * Called by developer tools to inspect storage state.\n * @param storageJson - Storage as JSON string (or undefined for new blocks)\n * @returns JSON string containing StorageDebugView\n */\n [BlockStorageFacadeCallbacks.StorageDebugView]: (\n storageJson: StringifiedJson | undefined,\n ) => StringifiedJson;\n\n /**\n * Run storage migration.\n * Called when block loads to migrate data to latest version.\n * @param currentStorageJson - Current storage as JSON string (or undefined for new blocks)\n * @returns Migration result - either error or success with new storage\n */\n [BlockStorageFacadeCallbacks.StorageMigrate]: (currentStorageJson: StringifiedJson | undefined) =>\n | { error: string }\n | {\n error?: undefined;\n newStorageJson: StringifiedJson;\n info: string;\n };\n\n /**\n * Derive args from storage.\n * Called to get block configuration args from storage.\n * @param storageJson - Storage as JSON string\n * @returns Args derivation result - either error or derived value\n */\n [BlockStorageFacadeCallbacks.ArgsDerive]: (\n storageJson: StringifiedJson,\n ) => { error: string } | { error?: undefined; value: unknown };\n\n /**\n * Derive prerunArgs from storage.\n * Called to get prerun args; falls back to args callback if not registered.\n * @param storageJson - Storage as JSON string\n * @returns Args derivation result - either error or derived value\n */\n [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (\n storageJson: StringifiedJson,\n ) => { error: string } | { error?: undefined; value: unknown };\n\n /**\n * Get initial storage JSON for new blocks.\n * Called when creating a new block to get complete initial storage.\n * @returns Initial storage as JSON string\n */\n [BlockStorageFacadeCallbacks.StorageInitial]: () => StringifiedJson;\n}\n\n/** Register all facade callbacks at once. Ensures all required callbacks are provided. */\nexport function registerFacadeCallbacks(callbacks: BlockStorageFacade): void {\n for (const key of Object.values(BlockStorageFacadeCallbacks)) {\n tryRegisterCallback(key, callbacks[key] as (...args: any[]) => any);\n }\n}\n"],"mappings":";;;;;;;AA8DA,MAAa,+BAA+B;;;;;;;;;;AAe5C,MAAa,8BAA8B;CACzC,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,YAAY;CACZ,kBAAkB;CAClB,gBAAgB;CACjB;;;;;AAMD,SAAS,oBACP,WAC2C;AAC3C,QAAO,OAAO,YACZ,OAAO,OAAO,UAAU,CAAC,KAAK,WAAW,CAAC,QAAQ,mBAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,CACnF;;;;;;AAOH,MAAa,4BAA4B,oBAAoB,4BAA4B;;AA4FzF,SAAgB,wBAAwB,WAAqC;AAC3E,MAAK,MAAM,OAAO,OAAO,OAAO,4BAA4B,CAC1D,qBAAoB,KAAK,UAAU,KAAgC"}
1
+ {"version":3,"file":"block_storage_facade.js","names":[],"sources":["../src/block_storage_facade.ts"],"sourcesContent":["/**\n * Block Storage Facade - Contract between bundled blocks and middle layer.\n *\n * ============================================================================\n * VERSIONING\n * ============================================================================\n *\n * Blocks declare their model API version via the `requiresModelAPIVersion` feature flag\n * (see BlockCodeKnownFeatureFlags). This determines how the middle layer manages block state:\n *\n * - Version 1: Legacy BlockModel - state is {args, uiState}, managed directly by middle layer\n * - Version 2: BlockModelV3 - uses blockStorage with VM-based callbacks (this facade)\n *\n * This facade (BlockStorageFacade) is used by blocks with `requiresModelAPIVersion: 2`.\n * The version number matches the model API version for clarity.\n *\n * ============================================================================\n * BACKWARD COMPATIBILITY WARNING\n * ============================================================================\n *\n * This file documents the FACADE between the SDK (bundled into blocks) and the\n * middle layer. Once a block is published, its SDK version is frozen. The middle\n * layer must support ALL previously released callback signatures indefinitely.\n *\n * RULES:\n * 1. NEVER change the signature of existing callbacks\n * 2. NEVER remove existing callbacks\n * 3. New callbacks CAN be added (old blocks won't register them, middle layer\n * should handle missing callbacks gracefully)\n * 4. Callback return types can be EXTENDED (add optional fields) but not changed\n * 5. Callback parameter types should remain compatible (middle layer may need\n * to handle both old and new formats)\n *\n * The facade consists of callbacks registered via `tryRegisterCallback()` with\n * the `__pl_` prefix. These are registered by the SDK when a block loads and\n * called by the middle layer to perform operations.\n *\n * ============================================================================\n * WHAT CAN BE CHANGED FREELY\n * ============================================================================\n *\n * - Middle layer code (lib/node/pl-middle-layer)\n * - SDK internal implementation (as long as callback contracts are preserved)\n * - SDK exports used ONLY by middle layer (not by blocks themselves)\n * - New SDK features that don't affect existing callbacks\n *\n * @module block_storage_facade\n */\n\nimport type { MutateStoragePayload } from \"./block_storage\";\nimport type { ConfigRenderLambda } from \"./bconfig\";\nimport { createRenderLambda, tryRegisterCallback } from \"./internal\";\nimport type { StringifiedJson } from \"@milaboratories/pl-model-common\";\n\n// =============================================================================\n// Facade Version\n// =============================================================================\n\n/**\n * The current facade version. This value is used for `requiresModelAPIVersion`\n * feature flag in BlockModelV3.\n */\nexport const BLOCK_STORAGE_FACADE_VERSION = 2;\n\n// =============================================================================\n// Facade Callback Names\n// =============================================================================\n\n/**\n * All facade callback names as constants.\n * These are the source of truth - the interface is derived from these.\n *\n * IMPORTANT: When adding a new callback:\n * 1. Add the constant here\n * 2. Add the callback signature to FacadeCallbackTypes below\n * 3. The BlockStorageFacade type will automatically include it\n */\nexport const BlockStorageFacadeCallbacks = {\n StorageApplyUpdate: \"__pl_storage_applyUpdate\",\n StorageDebugView: \"__pl_storage_debugView\",\n StorageMigrate: \"__pl_storage_migrate\",\n ArgsDerive: \"__pl_args_derive\",\n PrerunArgsDerive: \"__pl_prerunArgs_derive\",\n StorageInitial: \"__pl_storage_initial\",\n} as const;\n\n/**\n * Creates a map of lambda handles from a callbacks constant object.\n * Keys are the callback string values (e.g., '__pl_storage_applyUpdate').\n */\nfunction createFacadeHandles<T extends Record<string, string>>(\n callbacks: T,\n): { [K in T[keyof T]]: ConfigRenderLambda } {\n return Object.fromEntries(\n Object.values(callbacks).map((handle) => [handle, createRenderLambda({ handle })]),\n ) as { [K in T[keyof T]]: ConfigRenderLambda };\n}\n\n/**\n * Lambda handles for facade callbacks.\n * Used by the middle layer to invoke callbacks via executeSingleLambda().\n */\nexport const BlockStorageFacadeHandles = createFacadeHandles(BlockStorageFacadeCallbacks);\n\n// =============================================================================\n// Facade Interface (source of truth for callback signatures)\n// =============================================================================\n\n/**\n * The complete facade interface between bundled blocks (SDK) and middle layer.\n *\n * This interface defines ALL callbacks that a block registers. The middle layer\n * calls these callbacks to perform storage operations.\n *\n * ALL types are inlined to simplify versioning - when a callback changes,\n * the entire signature is visible in one place.\n *\n * BACKWARD COMPATIBILITY:\n * - This interface can only be EXTENDED, never shrunk\n * - Existing callback signatures MUST NOT change\n * - Middle layer should use Partial<BlockStorageFacade> when dealing with\n * blocks of unknown version (older blocks may not have all callbacks)\n *\n * Each callback is documented with:\n * - Purpose and when it's called\n * - Parameter descriptions\n * - Return value description\n */\nexport interface BlockStorageFacade {\n /**\n * Apply state update to storage.\n * Called when UI updates block state (setState) or plugin data.\n * @param currentStorageJson - Current storage as JSON string\n * @param payload - Update payload with operation type and value\n * @returns Updated storage as JSON string\n */\n [BlockStorageFacadeCallbacks.StorageApplyUpdate]: (\n currentStorageJson: StringifiedJson,\n payload: MutateStoragePayload,\n ) => StringifiedJson;\n\n /**\n * Get debug view of storage.\n * Called by developer tools to inspect storage state.\n * @param storageJson - Storage as JSON string (or undefined for new blocks)\n * @returns JSON string containing StorageDebugView\n */\n [BlockStorageFacadeCallbacks.StorageDebugView]: (\n storageJson: StringifiedJson | undefined,\n ) => StringifiedJson;\n\n /**\n * Run storage migration.\n * Called when block loads to migrate data to latest version.\n * @param currentStorageJson - Current storage as JSON string (or undefined for new blocks)\n * @returns Migration result - either error or success with new storage\n */\n [BlockStorageFacadeCallbacks.StorageMigrate]: (currentStorageJson: StringifiedJson | undefined) =>\n | { error: string }\n | {\n error?: undefined;\n newStorageJson: StringifiedJson;\n info: string;\n };\n\n /**\n * Derive args from storage.\n * Called to get block configuration args from storage.\n * @param storageJson - Storage as JSON string\n * @returns Args derivation result - either error or derived value\n */\n [BlockStorageFacadeCallbacks.ArgsDerive]: (\n storageJson: StringifiedJson,\n ) => { error: string } | { error?: undefined; value: unknown };\n\n /**\n * Derive prerunArgs from storage.\n * Called to get prerun args; falls back to args callback if not registered.\n * @param storageJson - Storage as JSON string\n * @returns Args derivation result - either error or derived value\n */\n [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (\n storageJson: StringifiedJson,\n ) => { error: string } | { error?: undefined; value: unknown };\n\n /**\n * Get initial storage JSON for new blocks.\n * Called when creating a new block to get complete initial storage.\n * @returns Initial storage as JSON string\n */\n [BlockStorageFacadeCallbacks.StorageInitial]: () => StringifiedJson;\n}\n\n/** Register all facade callbacks at once. Ensures all required callbacks are provided. */\nexport function registerFacadeCallbacks(callbacks: BlockStorageFacade): void {\n for (const key of Object.values(BlockStorageFacadeCallbacks)) {\n tryRegisterCallback(key, callbacks[key] as (...args: any[]) => any);\n }\n}\n"],"mappings":";;;;;;AA8DA,MAAa,+BAA+B;;;;;;;;;;AAe5C,MAAa,8BAA8B;CACzC,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,YAAY;CACZ,kBAAkB;CAClB,gBAAgB;CACjB;;;;;AAMD,SAAS,oBACP,WAC2C;AAC3C,QAAO,OAAO,YACZ,OAAO,OAAO,UAAU,CAAC,KAAK,WAAW,CAAC,QAAQ,mBAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,CACnF;;;;;;AAOH,MAAa,4BAA4B,oBAAoB,4BAA4B;;AA4FzF,SAAgB,wBAAwB,WAAqC;AAC3E,MAAK,MAAM,OAAO,OAAO,OAAO,4BAA4B,CAC1D,qBAAoB,KAAK,UAAU,KAAgC"}
@@ -1,10 +1,9 @@
1
- const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
2
- const require_accessor = require('../render/accessor.cjs');
3
- const require_column_snapshot = require('./column_snapshot.cjs');
4
- const require_column_snapshot_provider = require('./column_snapshot_provider.cjs');
5
- const require_column_selector = require('./column_selector.cjs');
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_accessor = require("../render/accessor.cjs");
3
+ const require_column_snapshot = require("./column_snapshot.cjs");
4
+ const require_column_snapshot_provider = require("./column_snapshot_provider.cjs");
5
+ const require_column_selector = require("./column_selector.cjs");
6
6
  let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
7
-
8
7
  //#region src/columns/column_collection_builder.ts
9
8
  /**
10
9
  * Mutable builder that accumulates column sources, then produces
@@ -224,7 +223,7 @@ function matchingModeToConstraints(mode) {
224
223
  };
225
224
  }
226
225
  }
227
-
228
226
  //#endregion
229
227
  exports.ColumnCollectionBuilder = ColumnCollectionBuilder;
228
+
230
229
  //# sourceMappingURL=column_collection_builder.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"column_collection_builder.cjs","names":["TreeNodeAccessor","ArrayColumnProvider","toColumnSnapshotProvider","AnchoredIdDeriver","createColumnSnapshot","normalizeSelectors"],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsStepInfo,\n MultiColumnSelector,\n NativePObjectId,\n PColumnSpec,\n PlRef,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport { AnchoredIdDeriver, deriveNativeId, isPlRef } from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelectorInput } from \"./column_selector\";\nimport { normalizeSelectors } from \"./column_selector\";\nimport { TreeNodeAccessor } from \"../render/accessor\";\nimport type { ColumnSnapshot } from \"./column_snapshot\";\nimport { createColumnSnapshot } from \"./column_snapshot\";\nimport type { ColumnSnapshotProvider, ColumnSource } from \"./column_snapshot_provider\";\nimport { ArrayColumnProvider, toColumnSnapshotProvider } from \"./column_snapshot_provider\";\n\nimport type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from \"@milaboratories/pl-model-common\";\n\n// --- FindColumnsOptions ---\n\n/** Options for plain collection findColumns. */\nexport interface FindColumnsOptions {\n /** Include columns matching these selectors. If omitted, includes all columns. */\n include?: ColumnSelectorInput;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelectorInput;\n}\n\n// --- ColumnCollection ---\n\n/** Plain collection — no axis context, selector-based filtering only. */\nexport interface ColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n /** Point lookup by provider-native ID. */\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;\n\n /** Find columns matching selectors. Returns flat list of snapshots.\n * No axis compatibility matching, no linker traversal.\n * Never returns undefined — the \"not ready\" state was absorbed by the builder. */\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];\n}\n\n// --- AnchoredColumnCollection ---\n\n/** Axis-aware column collection with anchored identity derivation. */\nexport interface AnchoredColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n /** Point lookup by anchored ID. */\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;\n\n /** Axis-aware column discovery. */\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];\n}\n\n/** Controls axis matching behavior for anchored discovery. */\nexport type MatchingMode = \"enrichment\" | \"related\" | \"exact\";\n\n/** Options for anchored collection findColumns. */\nexport interface AnchoredFindColumnsOptions extends FindColumnsOptions {\n /** Controls axis matching behavior. Default: 'enrichment'. */\n mode?: MatchingMode;\n /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */\n maxHops?: number;\n}\n\n/** Result of anchored discovery — column snapshot + routing info. */\nexport interface ColumnMatch {\n /** Column snapshot with anchored SUniversalPColumnId. */\n readonly column: ColumnSnapshot<SUniversalPColumnId>;\n /** Provider-native ID — for lookups back to the source provider. */\n readonly originalId: PObjectId;\n /** Match variants — different paths/qualifications that reach this column. */\n readonly variants: MatchVariant[];\n /** Linker steps traversed to reach this hit; empty for direct matches. */\n readonly path: DiscoverColumnsStepInfo[];\n}\n\n/** Qualifications needed for both query (already-integrated) columns and the hit column. */\nexport interface MatchQualifications {\n /** Qualifications for each query (already-integrated) column set. */\n readonly forQueries: AxisQualification[][];\n /** Qualifications for the hit column. */\n readonly forHit: AxisQualification[];\n}\n\n/** A single mapping variant describing how a hit column can be integrated. */\nexport interface MatchVariant {\n /** Full qualifications needed for integration. */\n readonly qualifications: MatchQualifications;\n /** Distinctive (minimal) qualifications needed for integration. */\n readonly distinctiveQualifications: MatchQualifications;\n}\n\n// --- Build options ---\n\nexport interface BuildOptions {\n allowPartialColumnList?: true;\n}\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, PlRef | PObjectId | PColumnSpec>;\n}\n\n// --- ColumnCollectionBuilder ---\n\n/**\n * Mutable builder that accumulates column sources, then produces\n * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).\n *\n * Each output lambda creates its own builder — a constraint of the\n * computable framework where each output tracks its own dependencies.\n */\nexport class ColumnCollectionBuilder {\n private readonly providers: ColumnSnapshotProvider[] = [];\n\n constructor(private readonly specDriver: PFrameSpecDriver) {}\n\n /**\n * Register a column source. Sources added first take precedence for dedup.\n * Does NOT accept undefined — if a source isn't available yet,\n * the caller should return undefined from the output lambda.\n */\n addSource(source: ColumnSource | TreeNodeAccessor): this {\n if (source instanceof TreeNodeAccessor) {\n const columns = source.getPColumns();\n if (columns) this.providers.push(new ArrayColumnProvider(columns));\n } else {\n this.providers.push(toColumnSnapshotProvider(source));\n }\n return this;\n }\n\n addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this {\n for (const source of sources) {\n this.addSource(source);\n }\n return this;\n }\n\n /** Plain collection — selector-based filtering, PObjectId namespace. */\n build(): undefined | ColumnCollection;\n build(options: {\n allowPartialColumnList: true;\n }): ColumnCollection & { readonly columnListComplete: boolean };\n /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */\n build(\n options: AnchoredBuildOptions & { allowPartialColumnList: true },\n ): AnchoredColumnCollection & { readonly columnListComplete: boolean };\n build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;\n build(\n options?: BuildOptions | AnchoredBuildOptions,\n ):\n | undefined\n | ColumnCollection\n | AnchoredColumnCollection\n | (ColumnCollection & { readonly columnListComplete: boolean })\n | (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {\n const allowPartial = options?.allowPartialColumnList === true;\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n // Check column list completeness\n const allComplete = this.providers.every((p) => p.isColumnListComplete());\n if (!allComplete && !allowPartial) return undefined;\n\n // Collect all columns, dedup by native ID (first source wins)\n const columnMap = this.collectColumns();\n\n if (hasAnchors) {\n const anchorSpecs = resolveAnchorSpecs(options.anchors, columnMap);\n const idDeriver = new AnchoredIdDeriver(anchorSpecs);\n\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n columns: columnMap,\n idDeriver,\n anchorSpecs,\n columnListComplete: allowPartial ? allComplete : false,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns: columnMap,\n columnListComplete: allowPartial ? allComplete : false,\n });\n }\n }\n\n /**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\n private collectColumns(): Map<PObjectId, ColumnSnapshot<PObjectId>> {\n const seen = new Set<NativePObjectId>();\n const result = new Map<PObjectId, ColumnSnapshot<PObjectId>>();\n\n for (const provider of this.providers) {\n const columns = provider.getAllColumns();\n for (const col of columns) {\n const nativeId = deriveNativeId(col.spec);\n if (seen.has(nativeId)) continue;\n seen.add(nativeId);\n result.set(col.id, col);\n }\n }\n\n return result;\n }\n}\n\n// --- Permissive constraints for plain (non-anchored) filtering ---\n\nconst PLAIN_CONSTRAINTS: DiscoverColumnsConstraints = {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n};\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n readonly columnListComplete?: boolean;\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n public readonly columnListComplete: boolean;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = options.columns;\n this.columnListComplete = options.columnListComplete ?? false;\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {\n const col = this.columns.get(id);\n if (col === undefined) return undefined;\n return this.toSnapshot(col);\n }\n\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[] {\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n axes: [],\n maxHops: 0,\n constraints: PLAIN_CONSTRAINTS,\n });\n\n // Map hits back to snapshots\n const results = response.hits\n .map((hit) => this.columns.get(hit.hit.columnId as PObjectId))\n .filter((col): col is ColumnSnapshot<PObjectId> => col !== undefined)\n .map((col) => this.toSnapshot(col));\n\n return results;\n }\n\n private toSnapshot(col: ColumnSnapshot<PObjectId>): ColumnSnapshot<PObjectId> {\n return remapSnapshot(col.id, col);\n }\n}\n\n// --- AnchoredColumnCollectionImpl ---\n\ninterface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {\n readonly idDeriver: AnchoredIdDeriver;\n readonly anchorSpecs: Record<string, PColumnSpec>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n private readonly anchorAxes: ColumnAxesWithQualifications[];\n /** Reverse lookup: SUniversalPColumnId → PObjectId */\n private readonly idToOriginal: Map<SUniversalPColumnId, PObjectId>;\n public readonly columnListComplete: boolean;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n this.columns = options.columns;\n this.idDeriver = options.idDeriver;\n this.columnListComplete = options.columnListComplete ?? false;\n\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])),\n );\n\n // Build anchor axes for discovery requests\n this.anchorAxes = Object.values(options.anchorSpecs).map((spec) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n }));\n\n // Build reverse lookup map\n this.idToOriginal = new Map(\n Array.from(this.columns.entries()).map(\n ([id, col]) => [this.idDeriver.deriveS(col.spec), id] as const,\n ),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginal.get(id);\n if (origId === undefined) return undefined;\n const col = this.columns.get(origId);\n if (col === undefined) return undefined;\n return this.toSnapshot(id, col);\n }\n\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {\n const mode = options?.mode ?? \"enrichment\";\n const constraints = matchingModeToConstraints(mode);\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n constraints,\n axes: this.anchorAxes,\n maxHops: options?.maxHops ?? 4,\n });\n\n // Map hits back to ColumnMatch entries\n const results = response.hits\n .map((hit) => {\n const origId = hit.hit.columnId as PObjectId;\n const col = this.columns.get(origId);\n if (!col) return undefined;\n const universalId = this.idDeriver.deriveS(col.spec);\n return {\n column: this.toSnapshot(universalId, col),\n originalId: origId,\n variants: hit.mappingVariants.map(\n (v): MatchVariant => ({\n qualifications: v.qualifications,\n distinctiveQualifications: v.distinctiveQualifications,\n }),\n ),\n path: hit.path,\n } satisfies ColumnMatch;\n })\n .filter((m): m is ColumnMatch => m !== undefined);\n\n return results;\n }\n\n private toSnapshot(\n universalId: SUniversalPColumnId,\n col: ColumnSnapshot<PObjectId>,\n ): ColumnSnapshot<SUniversalPColumnId> {\n return remapSnapshot(universalId, col);\n }\n}\n\n// --- Shared snapshot helpers ---\n\n/** Create a new snapshot with a different ID, preserving data accessors. */\nfunction remapSnapshot<Id extends PObjectId>(\n id: Id,\n col: ColumnSnapshot<PObjectId>,\n): ColumnSnapshot<Id> {\n return createColumnSnapshot(id, col.spec, col.dataStatus, col.data);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelectorInput): MultiColumnSelector[] {\n return normalizeSelectors(input);\n}\n\n// --- Anchor resolution ---\n\n/**\n * Resolve each anchor value to a PColumnSpec.\n * - PColumnSpec: used directly\n * - PObjectId (string): looked up in the collected column map\n * - PlRef: not supported at this level — caller must resolve before building\n */\nfunction resolveAnchorSpecs(\n anchors: Record<string, PlRef | PObjectId | PColumnSpec>,\n columnMap: Map<PObjectId, ColumnSnapshot<PObjectId>>,\n): Record<string, PColumnSpec> {\n const result: Record<string, PColumnSpec> = {};\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n // PObjectId — look up in collected columns\n const col = columnMap.get(anchor as PObjectId);\n if (!col) throw new Error(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n result[key] = col.spec;\n } else if (isPlRef(anchor)) {\n throw new Error(\n `Anchor \"${key}\": PlRef anchors must be resolved to PColumnSpec before building. ` +\n `Use the column's spec directly or pass its PObjectId.`,\n );\n } else {\n // PColumnSpec\n result[key] = anchor;\n }\n }\n return result;\n}\n\n// --- MatchingMode → DiscoverColumnsConstraints ---\n\nfunction matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstraints {\n switch (mode) {\n case \"enrichment\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n case \"related\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"exact\":\n return {\n allowFloatingSourceAxes: false,\n allowFloatingHitAxes: false,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"column_collection_builder.cjs","names":["TreeNodeAccessor","ArrayColumnProvider","toColumnSnapshotProvider","AnchoredIdDeriver","createColumnSnapshot","normalizeSelectors"],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsStepInfo,\n MultiColumnSelector,\n NativePObjectId,\n PColumnSpec,\n PlRef,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport { AnchoredIdDeriver, deriveNativeId, isPlRef } from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelectorInput } from \"./column_selector\";\nimport { normalizeSelectors } from \"./column_selector\";\nimport { TreeNodeAccessor } from \"../render/accessor\";\nimport type { ColumnSnapshot } from \"./column_snapshot\";\nimport { createColumnSnapshot } from \"./column_snapshot\";\nimport type { ColumnSnapshotProvider, ColumnSource } from \"./column_snapshot_provider\";\nimport { ArrayColumnProvider, toColumnSnapshotProvider } from \"./column_snapshot_provider\";\n\nimport type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from \"@milaboratories/pl-model-common\";\n\n// --- FindColumnsOptions ---\n\n/** Options for plain collection findColumns. */\nexport interface FindColumnsOptions {\n /** Include columns matching these selectors. If omitted, includes all columns. */\n include?: ColumnSelectorInput;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelectorInput;\n}\n\n// --- ColumnCollection ---\n\n/** Plain collection — no axis context, selector-based filtering only. */\nexport interface ColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n /** Point lookup by provider-native ID. */\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;\n\n /** Find columns matching selectors. Returns flat list of snapshots.\n * No axis compatibility matching, no linker traversal.\n * Never returns undefined — the \"not ready\" state was absorbed by the builder. */\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];\n}\n\n// --- AnchoredColumnCollection ---\n\n/** Axis-aware column collection with anchored identity derivation. */\nexport interface AnchoredColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n /** Point lookup by anchored ID. */\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;\n\n /** Axis-aware column discovery. */\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];\n}\n\n/** Controls axis matching behavior for anchored discovery. */\nexport type MatchingMode = \"enrichment\" | \"related\" | \"exact\";\n\n/** Options for anchored collection findColumns. */\nexport interface AnchoredFindColumnsOptions extends FindColumnsOptions {\n /** Controls axis matching behavior. Default: 'enrichment'. */\n mode?: MatchingMode;\n /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */\n maxHops?: number;\n}\n\n/** Result of anchored discovery — column snapshot + routing info. */\nexport interface ColumnMatch {\n /** Column snapshot with anchored SUniversalPColumnId. */\n readonly column: ColumnSnapshot<SUniversalPColumnId>;\n /** Provider-native ID — for lookups back to the source provider. */\n readonly originalId: PObjectId;\n /** Match variants — different paths/qualifications that reach this column. */\n readonly variants: MatchVariant[];\n /** Linker steps traversed to reach this hit; empty for direct matches. */\n readonly path: DiscoverColumnsStepInfo[];\n}\n\n/** Qualifications needed for both query (already-integrated) columns and the hit column. */\nexport interface MatchQualifications {\n /** Qualifications for each query (already-integrated) column set. */\n readonly forQueries: AxisQualification[][];\n /** Qualifications for the hit column. */\n readonly forHit: AxisQualification[];\n}\n\n/** A single mapping variant describing how a hit column can be integrated. */\nexport interface MatchVariant {\n /** Full qualifications needed for integration. */\n readonly qualifications: MatchQualifications;\n /** Distinctive (minimal) qualifications needed for integration. */\n readonly distinctiveQualifications: MatchQualifications;\n}\n\n// --- Build options ---\n\nexport interface BuildOptions {\n allowPartialColumnList?: true;\n}\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, PlRef | PObjectId | PColumnSpec>;\n}\n\n// --- ColumnCollectionBuilder ---\n\n/**\n * Mutable builder that accumulates column sources, then produces\n * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).\n *\n * Each output lambda creates its own builder — a constraint of the\n * computable framework where each output tracks its own dependencies.\n */\nexport class ColumnCollectionBuilder {\n private readonly providers: ColumnSnapshotProvider[] = [];\n\n constructor(private readonly specDriver: PFrameSpecDriver) {}\n\n /**\n * Register a column source. Sources added first take precedence for dedup.\n * Does NOT accept undefined — if a source isn't available yet,\n * the caller should return undefined from the output lambda.\n */\n addSource(source: ColumnSource | TreeNodeAccessor): this {\n if (source instanceof TreeNodeAccessor) {\n const columns = source.getPColumns();\n if (columns) this.providers.push(new ArrayColumnProvider(columns));\n } else {\n this.providers.push(toColumnSnapshotProvider(source));\n }\n return this;\n }\n\n addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this {\n for (const source of sources) {\n this.addSource(source);\n }\n return this;\n }\n\n /** Plain collection — selector-based filtering, PObjectId namespace. */\n build(): undefined | ColumnCollection;\n build(options: {\n allowPartialColumnList: true;\n }): ColumnCollection & { readonly columnListComplete: boolean };\n /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */\n build(\n options: AnchoredBuildOptions & { allowPartialColumnList: true },\n ): AnchoredColumnCollection & { readonly columnListComplete: boolean };\n build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;\n build(\n options?: BuildOptions | AnchoredBuildOptions,\n ):\n | undefined\n | ColumnCollection\n | AnchoredColumnCollection\n | (ColumnCollection & { readonly columnListComplete: boolean })\n | (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {\n const allowPartial = options?.allowPartialColumnList === true;\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n // Check column list completeness\n const allComplete = this.providers.every((p) => p.isColumnListComplete());\n if (!allComplete && !allowPartial) return undefined;\n\n // Collect all columns, dedup by native ID (first source wins)\n const columnMap = this.collectColumns();\n\n if (hasAnchors) {\n const anchorSpecs = resolveAnchorSpecs(options.anchors, columnMap);\n const idDeriver = new AnchoredIdDeriver(anchorSpecs);\n\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n columns: columnMap,\n idDeriver,\n anchorSpecs,\n columnListComplete: allowPartial ? allComplete : false,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns: columnMap,\n columnListComplete: allowPartial ? allComplete : false,\n });\n }\n }\n\n /**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\n private collectColumns(): Map<PObjectId, ColumnSnapshot<PObjectId>> {\n const seen = new Set<NativePObjectId>();\n const result = new Map<PObjectId, ColumnSnapshot<PObjectId>>();\n\n for (const provider of this.providers) {\n const columns = provider.getAllColumns();\n for (const col of columns) {\n const nativeId = deriveNativeId(col.spec);\n if (seen.has(nativeId)) continue;\n seen.add(nativeId);\n result.set(col.id, col);\n }\n }\n\n return result;\n }\n}\n\n// --- Permissive constraints for plain (non-anchored) filtering ---\n\nconst PLAIN_CONSTRAINTS: DiscoverColumnsConstraints = {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n};\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n readonly columnListComplete?: boolean;\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n public readonly columnListComplete: boolean;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = options.columns;\n this.columnListComplete = options.columnListComplete ?? false;\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {\n const col = this.columns.get(id);\n if (col === undefined) return undefined;\n return this.toSnapshot(col);\n }\n\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[] {\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n axes: [],\n maxHops: 0,\n constraints: PLAIN_CONSTRAINTS,\n });\n\n // Map hits back to snapshots\n const results = response.hits\n .map((hit) => this.columns.get(hit.hit.columnId as PObjectId))\n .filter((col): col is ColumnSnapshot<PObjectId> => col !== undefined)\n .map((col) => this.toSnapshot(col));\n\n return results;\n }\n\n private toSnapshot(col: ColumnSnapshot<PObjectId>): ColumnSnapshot<PObjectId> {\n return remapSnapshot(col.id, col);\n }\n}\n\n// --- AnchoredColumnCollectionImpl ---\n\ninterface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {\n readonly idDeriver: AnchoredIdDeriver;\n readonly anchorSpecs: Record<string, PColumnSpec>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n private readonly anchorAxes: ColumnAxesWithQualifications[];\n /** Reverse lookup: SUniversalPColumnId → PObjectId */\n private readonly idToOriginal: Map<SUniversalPColumnId, PObjectId>;\n public readonly columnListComplete: boolean;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n this.columns = options.columns;\n this.idDeriver = options.idDeriver;\n this.columnListComplete = options.columnListComplete ?? false;\n\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])),\n );\n\n // Build anchor axes for discovery requests\n this.anchorAxes = Object.values(options.anchorSpecs).map((spec) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n }));\n\n // Build reverse lookup map\n this.idToOriginal = new Map(\n Array.from(this.columns.entries()).map(\n ([id, col]) => [this.idDeriver.deriveS(col.spec), id] as const,\n ),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginal.get(id);\n if (origId === undefined) return undefined;\n const col = this.columns.get(origId);\n if (col === undefined) return undefined;\n return this.toSnapshot(id, col);\n }\n\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {\n const mode = options?.mode ?? \"enrichment\";\n const constraints = matchingModeToConstraints(mode);\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n constraints,\n axes: this.anchorAxes,\n maxHops: options?.maxHops ?? 4,\n });\n\n // Map hits back to ColumnMatch entries\n const results = response.hits\n .map((hit) => {\n const origId = hit.hit.columnId as PObjectId;\n const col = this.columns.get(origId);\n if (!col) return undefined;\n const universalId = this.idDeriver.deriveS(col.spec);\n return {\n column: this.toSnapshot(universalId, col),\n originalId: origId,\n variants: hit.mappingVariants.map(\n (v): MatchVariant => ({\n qualifications: v.qualifications,\n distinctiveQualifications: v.distinctiveQualifications,\n }),\n ),\n path: hit.path,\n } satisfies ColumnMatch;\n })\n .filter((m): m is ColumnMatch => m !== undefined);\n\n return results;\n }\n\n private toSnapshot(\n universalId: SUniversalPColumnId,\n col: ColumnSnapshot<PObjectId>,\n ): ColumnSnapshot<SUniversalPColumnId> {\n return remapSnapshot(universalId, col);\n }\n}\n\n// --- Shared snapshot helpers ---\n\n/** Create a new snapshot with a different ID, preserving data accessors. */\nfunction remapSnapshot<Id extends PObjectId>(\n id: Id,\n col: ColumnSnapshot<PObjectId>,\n): ColumnSnapshot<Id> {\n return createColumnSnapshot(id, col.spec, col.dataStatus, col.data);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelectorInput): MultiColumnSelector[] {\n return normalizeSelectors(input);\n}\n\n// --- Anchor resolution ---\n\n/**\n * Resolve each anchor value to a PColumnSpec.\n * - PColumnSpec: used directly\n * - PObjectId (string): looked up in the collected column map\n * - PlRef: not supported at this level — caller must resolve before building\n */\nfunction resolveAnchorSpecs(\n anchors: Record<string, PlRef | PObjectId | PColumnSpec>,\n columnMap: Map<PObjectId, ColumnSnapshot<PObjectId>>,\n): Record<string, PColumnSpec> {\n const result: Record<string, PColumnSpec> = {};\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n // PObjectId — look up in collected columns\n const col = columnMap.get(anchor as PObjectId);\n if (!col) throw new Error(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n result[key] = col.spec;\n } else if (isPlRef(anchor)) {\n throw new Error(\n `Anchor \"${key}\": PlRef anchors must be resolved to PColumnSpec before building. ` +\n `Use the column's spec directly or pass its PObjectId.`,\n );\n } else {\n // PColumnSpec\n result[key] = anchor;\n }\n }\n return result;\n}\n\n// --- MatchingMode → DiscoverColumnsConstraints ---\n\nfunction matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstraints {\n switch (mode) {\n case \"enrichment\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n case \"related\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"exact\":\n return {\n allowFloatingSourceAxes: false,\n allowFloatingHitAxes: false,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column_collection_builder.d.ts","names":[],"sources":["../../src/columns/column_collection_builder.ts"],"mappings":";;;;;;;;UA0BiB,kBAAA;EAAkB;EAEjC,OAAA,GAAU,mBAAA;EAEmB;EAA7B,OAAA,GAAU,mBAAA;AAAA;;UAMK,gBAAA,SAAyB,UAAA;EANX;EAQ7B,OAAA;EAFe;EAIf,SAAA,CAAU,EAAA,EAAI,SAAA,eAAwB,cAAA,CAAe,SAAA;;;;EAKrD,WAAA,CAAY,OAAA,GAAU,kBAAA,GAAqB,cAAA,CAAe,SAAA;AAAA;;UAM3C,wBAAA,SAAiC,UAAA;EAfR;EAiBxC,OAAA;EAjBkD;EAmBlD,SAAA,CAAU,EAAA,EAAI,mBAAA,eAAkC,cAAA,CAAe,mBAAA;EAjB/D;EAoBA,WAAA,CAAY,OAAA,GAAU,0BAAA,GAA6B,WAAA;AAAA;;KAIzC,YAAA;;UAGK,0BAAA,SAAmC,kBAAA;EApB5B;EAsBtB,IAAA,GAAO,YAAA;EAtBoC;EAwB3C,OAAA;AAAA;;UAIe,WAAA;EAtByB;EAAA,SAwB/B,MAAA,EAAQ,cAAA,CAAe,mBAAA;EApBlB;EAAA,SAsBL,UAAA,EAAY,SAAA;EAtB2B;EAAA,SAwBvC,QAAA,EAAU,YAAA;EArBgC;EAAA,SAuB1C,IAAA,EAAM,uBAAA;AAAA;;UAIA,mBAAA;EAhCf;EAAA,SAkCS,UAAA,EAAY,iBAAA;EAhCP;EAAA,SAkCL,MAAA,EAAQ,iBAAA;AAAA;;UAIF,YAAA;EAnCO;EAAA,SAqCb,cAAA,EAAgB,mBAAA;EArC0B;EAAA,SAuC1C,yBAAA,EAA2B,mBAAA;AAAA;AAAA,UAKrB,YAAA;EACf,sBAAA;AAAA;AAAA,UAGe,oBAAA,SAA6B,YAAA;EAC5C,OAAA,EAAS,MAAA,SAAe,KAAA,GAAQ,SAAA,GAAY,WAAA;AAAA;;;;;;;;cAYjC,uBAAA;EAAA,iBAGkB,UAAA;EAAA,iBAFZ,SAAA;cAEY,UAAA,EAAY,gBAAA;;;;;;EAOzC,SAAA,CAAU,MAAA,EAAQ,YAAA,GAAe,gBAAA;EAUjC,UAAA,CAAW,OAAA,GAAU,YAAA,GAAe,gBAAA;EA1DE;EAkEtC,KAAA,CAAA,eAAqB,gBAAA;EACrB,KAAA,CAAM,OAAA;IACJ,sBAAA;EAAA,IACE,gBAAA;IAAA,SAA8B,kBAAA;EAAA;EAvEf;EAyEnB,KAAA,CACE,OAAA,EAAS,oBAAA;IAAyB,sBAAA;EAAA,IACjC,wBAAA;IAAA,SAAsC,kBAAA;EAAA;EACzC,KAAA,CAAM,OAAA,EAAS,oBAAA,eAAmC,wBAAA;;;;;UAyC1C,cAAA;AAAA"}
@@ -3,7 +3,6 @@ import { createColumnSnapshot } from "./column_snapshot.js";
3
3
  import { ArrayColumnProvider, toColumnSnapshotProvider } from "./column_snapshot_provider.js";
4
4
  import { normalizeSelectors } from "./column_selector.js";
5
5
  import { AnchoredIdDeriver, deriveNativeId, isPlRef } from "@milaboratories/pl-model-common";
6
-
7
6
  //#region src/columns/column_collection_builder.ts
8
7
  /**
9
8
  * Mutable builder that accumulates column sources, then produces
@@ -223,7 +222,7 @@ function matchingModeToConstraints(mode) {
223
222
  };
224
223
  }
225
224
  }
226
-
227
225
  //#endregion
228
226
  export { ColumnCollectionBuilder };
227
+
229
228
  //# sourceMappingURL=column_collection_builder.js.map