@platforma-sdk/model 1.63.1 → 1.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (399) 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 +111 -99
  70. package/dist/columns/column_collection_builder.cjs.map +1 -1
  71. package/dist/columns/column_collection_builder.d.ts +13 -12
  72. package/dist/columns/column_collection_builder.d.ts.map +1 -0
  73. package/dist/columns/column_collection_builder.js +108 -96
  74. package/dist/columns/column_collection_builder.js.map +1 -1
  75. package/dist/columns/column_selector.cjs +9 -82
  76. package/dist/columns/column_selector.cjs.map +1 -1
  77. package/dist/columns/column_selector.d.ts +6 -14
  78. package/dist/columns/column_selector.d.ts.map +1 -0
  79. package/dist/columns/column_selector.js +7 -78
  80. package/dist/columns/column_selector.js.map +1 -1
  81. package/dist/columns/column_snapshot.cjs +4 -5
  82. package/dist/columns/column_snapshot.cjs.map +1 -1
  83. package/dist/columns/column_snapshot.d.ts +3 -3
  84. package/dist/columns/column_snapshot.d.ts.map +1 -0
  85. package/dist/columns/column_snapshot.js +4 -4
  86. package/dist/columns/column_snapshot.js.map +1 -1
  87. package/dist/columns/column_snapshot_provider.cjs +2 -3
  88. package/dist/columns/column_snapshot_provider.cjs.map +1 -1
  89. package/dist/columns/column_snapshot_provider.d.ts +8 -8
  90. package/dist/columns/column_snapshot_provider.d.ts.map +1 -0
  91. package/dist/columns/column_snapshot_provider.js +2 -2
  92. package/dist/columns/column_snapshot_provider.js.map +1 -1
  93. package/dist/columns/ctx_column_sources.cjs +3 -4
  94. package/dist/columns/ctx_column_sources.cjs.map +1 -1
  95. package/dist/columns/ctx_column_sources.d.ts +2 -2
  96. package/dist/columns/ctx_column_sources.d.ts.map +1 -0
  97. package/dist/columns/ctx_column_sources.js +1 -2
  98. package/dist/columns/ctx_column_sources.js.map +1 -1
  99. package/dist/columns/expand_by_partition.cjs +106 -0
  100. package/dist/columns/expand_by_partition.cjs.map +1 -0
  101. package/dist/columns/expand_by_partition.d.ts +33 -0
  102. package/dist/columns/expand_by_partition.d.ts.map +1 -0
  103. package/dist/columns/expand_by_partition.js +105 -0
  104. package/dist/columns/expand_by_partition.js.map +1 -0
  105. package/dist/columns/index.cjs +6 -5
  106. package/dist/columns/index.d.ts +4 -3
  107. package/dist/columns/index.js +6 -5
  108. package/dist/components/PFrameForGraphs.cjs +4 -5
  109. package/dist/components/PFrameForGraphs.cjs.map +1 -1
  110. package/dist/components/PFrameForGraphs.d.ts +0 -1
  111. package/dist/components/PFrameForGraphs.d.ts.map +1 -0
  112. package/dist/components/PFrameForGraphs.js +2 -3
  113. package/dist/components/PFrameForGraphs.js.map +1 -1
  114. package/dist/components/PlAnnotations/filter.d.ts.map +1 -0
  115. package/dist/components/PlAnnotations/filters_ui.cjs +1 -2
  116. package/dist/components/PlAnnotations/filters_ui.cjs.map +1 -1
  117. package/dist/components/PlAnnotations/filters_ui.d.ts +0 -2
  118. package/dist/components/PlAnnotations/filters_ui.d.ts.map +1 -0
  119. package/dist/components/PlAnnotations/filters_ui.js +1 -1
  120. package/dist/components/PlAnnotations/filters_ui.js.map +1 -1
  121. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +26 -0
  122. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -0
  123. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js +25 -0
  124. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -0
  125. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs +68 -0
  126. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs.map +1 -0
  127. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js +67 -0
  128. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js.map +1 -0
  129. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +28 -18
  130. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
  131. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +4 -1
  132. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts.map +1 -0
  133. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +22 -12
  134. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
  135. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +262 -181
  136. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  137. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +37 -23
  138. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -0
  139. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +261 -177
  140. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  141. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +64 -0
  142. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -0
  143. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts +17 -0
  144. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts.map +1 -0
  145. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +63 -0
  146. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -0
  147. package/dist/components/PlDataTable/createPlDataTable/index.cjs +4 -4
  148. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
  149. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -2
  150. package/dist/components/PlDataTable/createPlDataTable/index.d.ts.map +1 -0
  151. package/dist/components/PlDataTable/createPlDataTable/index.js +3 -3
  152. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
  153. package/dist/components/PlDataTable/createPlDataTable/utils.cjs +109 -0
  154. package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -0
  155. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts +19 -0
  156. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts.map +1 -0
  157. package/dist/components/PlDataTable/createPlDataTable/utils.js +102 -0
  158. package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -0
  159. package/dist/components/PlDataTable/createPlDataTableSheet.cjs +1 -2
  160. package/dist/components/PlDataTable/createPlDataTableSheet.cjs.map +1 -1
  161. package/dist/components/PlDataTable/createPlDataTableSheet.d.ts +0 -1
  162. package/dist/components/PlDataTable/createPlDataTableSheet.d.ts.map +1 -0
  163. package/dist/components/PlDataTable/createPlDataTableSheet.js +1 -1
  164. package/dist/components/PlDataTable/index.cjs +7 -5
  165. package/dist/components/PlDataTable/index.d.ts +4 -2
  166. package/dist/components/PlDataTable/index.js +7 -5
  167. package/dist/components/PlDataTable/labels.cjs +27 -14
  168. package/dist/components/PlDataTable/labels.cjs.map +1 -1
  169. package/dist/components/PlDataTable/labels.js +26 -13
  170. package/dist/components/PlDataTable/labels.js.map +1 -1
  171. package/dist/components/PlDataTable/state-migration.cjs +8 -6
  172. package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
  173. package/dist/components/PlDataTable/state-migration.d.ts.map +1 -0
  174. package/dist/components/PlDataTable/state-migration.js +5 -3
  175. package/dist/components/PlDataTable/state-migration.js.map +1 -1
  176. package/dist/components/PlDataTable/typesV4.d.ts.map +1 -0
  177. package/dist/components/PlDataTable/typesV5.d.ts +5 -5
  178. package/dist/components/PlDataTable/typesV5.d.ts.map +1 -0
  179. package/dist/components/PlMultiSequenceAlignment.cjs +2 -3
  180. package/dist/components/PlMultiSequenceAlignment.cjs.map +1 -1
  181. package/dist/components/PlMultiSequenceAlignment.d.ts.map +1 -0
  182. package/dist/components/PlMultiSequenceAlignment.js +1 -2
  183. package/dist/components/PlMultiSequenceAlignment.js.map +1 -1
  184. package/dist/components/PlSelectionModel.cjs +1 -2
  185. package/dist/components/PlSelectionModel.cjs.map +1 -1
  186. package/dist/components/PlSelectionModel.d.ts.map +1 -0
  187. package/dist/components/PlSelectionModel.js +1 -1
  188. package/dist/components/index.cjs +13 -11
  189. package/dist/components/index.d.ts +3 -3
  190. package/dist/components/index.js +12 -10
  191. package/dist/config/actions.cjs +1 -2
  192. package/dist/config/actions.cjs.map +1 -1
  193. package/dist/config/actions.d.ts.map +1 -0
  194. package/dist/config/actions.js +1 -1
  195. package/dist/config/actions_kinds.d.ts.map +1 -0
  196. package/dist/config/index.cjs +1 -1
  197. package/dist/config/index.js +1 -1
  198. package/dist/config/model.d.ts.map +1 -0
  199. package/dist/config/model_meta.d.ts.map +1 -0
  200. package/dist/config/type_engine.d.ts.map +1 -0
  201. package/dist/config/type_util.d.ts.map +1 -0
  202. package/dist/env_value.cjs +1 -2
  203. package/dist/env_value.cjs.map +1 -1
  204. package/dist/env_value.d.ts.map +1 -0
  205. package/dist/env_value.js +1 -1
  206. package/dist/env_value.js.map +1 -1
  207. package/dist/filters/converters/filterToQuery.cjs +3 -4
  208. package/dist/filters/converters/filterToQuery.cjs.map +1 -1
  209. package/dist/filters/converters/filterToQuery.d.ts.map +1 -0
  210. package/dist/filters/converters/filterToQuery.js +1 -2
  211. package/dist/filters/converters/filterToQuery.js.map +1 -1
  212. package/dist/filters/converters/filterUiToExpressionImpl.cjs +3 -4
  213. package/dist/filters/converters/filterUiToExpressionImpl.cjs.map +1 -1
  214. package/dist/filters/converters/filterUiToExpressionImpl.d.ts.map +1 -0
  215. package/dist/filters/converters/filterUiToExpressionImpl.js +1 -2
  216. package/dist/filters/converters/filterUiToExpressionImpl.js.map +1 -1
  217. package/dist/filters/converters/index.cjs +2 -2
  218. package/dist/filters/converters/index.js +2 -2
  219. package/dist/filters/distill.cjs +3 -4
  220. package/dist/filters/distill.cjs.map +1 -1
  221. package/dist/filters/distill.d.ts.map +1 -0
  222. package/dist/filters/distill.js +1 -2
  223. package/dist/filters/distill.js.map +1 -1
  224. package/dist/filters/index.cjs +4 -4
  225. package/dist/filters/index.d.ts +0 -1
  226. package/dist/filters/index.js +3 -3
  227. package/dist/filters/traverse.cjs +1 -2
  228. package/dist/filters/traverse.cjs.map +1 -1
  229. package/dist/filters/traverse.js +1 -1
  230. package/dist/filters/traverse.js.map +1 -1
  231. package/dist/filters/types.d.ts.map +1 -0
  232. package/dist/index.cjs +89 -83
  233. package/dist/index.d.ts +8 -15
  234. package/dist/index.js +8 -9
  235. package/dist/internal.cjs +1 -2
  236. package/dist/internal.cjs.map +1 -1
  237. package/dist/internal.js +1 -1
  238. package/dist/internal.js.map +1 -1
  239. package/dist/labels/derive_distinct_labels.cjs +41 -30
  240. package/dist/labels/derive_distinct_labels.cjs.map +1 -1
  241. package/dist/labels/derive_distinct_labels.d.ts +15 -15
  242. package/dist/labels/derive_distinct_labels.d.ts.map +1 -0
  243. package/dist/labels/derive_distinct_labels.js +40 -29
  244. package/dist/labels/derive_distinct_labels.js.map +1 -1
  245. package/dist/labels/index.cjs +1 -2
  246. package/dist/labels/index.d.ts +1 -2
  247. package/dist/labels/index.js +1 -2
  248. package/dist/package.cjs +7 -8
  249. package/dist/package.js +2 -2
  250. package/dist/pframe.cjs +2 -3
  251. package/dist/pframe.cjs.map +1 -1
  252. package/dist/pframe.d.ts.map +1 -0
  253. package/dist/pframe.js +1 -2
  254. package/dist/pframe.js.map +1 -1
  255. package/dist/pframe_utils/axes.cjs +2 -3
  256. package/dist/pframe_utils/axes.cjs.map +1 -1
  257. package/dist/pframe_utils/axes.d.ts +0 -1
  258. package/dist/pframe_utils/axes.d.ts.map +1 -0
  259. package/dist/pframe_utils/axes.js +1 -2
  260. package/dist/pframe_utils/axes.js.map +1 -1
  261. package/dist/pframe_utils/columns.cjs +5 -6
  262. package/dist/pframe_utils/columns.cjs.map +1 -1
  263. package/dist/pframe_utils/columns.d.ts +0 -1
  264. package/dist/pframe_utils/columns.d.ts.map +1 -0
  265. package/dist/pframe_utils/columns.js +1 -2
  266. package/dist/pframe_utils/columns.js.map +1 -1
  267. package/dist/pframe_utils/index.cjs +3 -4
  268. package/dist/pframe_utils/index.cjs.map +1 -1
  269. package/dist/pframe_utils/index.d.ts.map +1 -0
  270. package/dist/pframe_utils/index.js +2 -3
  271. package/dist/pframe_utils/index.js.map +1 -1
  272. package/dist/platforma.d.ts.map +1 -0
  273. package/dist/plugin_handle.cjs +1 -2
  274. package/dist/plugin_handle.cjs.map +1 -1
  275. package/dist/plugin_handle.d.ts.map +1 -0
  276. package/dist/plugin_handle.js +1 -1
  277. package/dist/plugin_model.cjs +3 -4
  278. package/dist/plugin_model.cjs.map +1 -1
  279. package/dist/plugin_model.d.ts +0 -1
  280. package/dist/plugin_model.d.ts.map +1 -0
  281. package/dist/plugin_model.js +1 -2
  282. package/dist/plugin_model.js.map +1 -1
  283. package/dist/raw_globals.cjs +3 -4
  284. package/dist/raw_globals.cjs.map +1 -1
  285. package/dist/raw_globals.d.ts.map +1 -0
  286. package/dist/raw_globals.js +1 -2
  287. package/dist/raw_globals.js.map +1 -1
  288. package/dist/ref_util.cjs +3 -4
  289. package/dist/ref_util.cjs.map +1 -1
  290. package/dist/ref_util.d.ts +0 -2
  291. package/dist/ref_util.d.ts.map +1 -0
  292. package/dist/ref_util.js +1 -2
  293. package/dist/ref_util.js.map +1 -1
  294. package/dist/render/accessor.cjs +4 -5
  295. package/dist/render/accessor.cjs.map +1 -1
  296. package/dist/render/accessor.d.ts.map +1 -0
  297. package/dist/render/accessor.js +1 -2
  298. package/dist/render/accessor.js.map +1 -1
  299. package/dist/render/api.cjs +20 -14
  300. package/dist/render/api.cjs.map +1 -1
  301. package/dist/render/api.d.ts +2 -3
  302. package/dist/render/api.d.ts.map +1 -0
  303. package/dist/render/api.js +11 -5
  304. package/dist/render/api.js.map +1 -1
  305. package/dist/render/future.cjs +2 -3
  306. package/dist/render/future.cjs.map +1 -1
  307. package/dist/render/future.d.ts.map +1 -0
  308. package/dist/render/future.js +1 -2
  309. package/dist/render/future.js.map +1 -1
  310. package/dist/render/index.cjs +8 -8
  311. package/dist/render/index.d.ts +1 -2
  312. package/dist/render/index.js +7 -7
  313. package/dist/render/internal.cjs +7 -9
  314. package/dist/render/internal.cjs.map +1 -1
  315. package/dist/render/internal.d.ts.map +1 -0
  316. package/dist/render/internal.js +1 -2
  317. package/dist/render/internal.js.map +1 -1
  318. package/dist/render/traversal_ops.d.ts.map +1 -0
  319. package/dist/render/util/axis_filtering.cjs +1 -2
  320. package/dist/render/util/axis_filtering.cjs.map +1 -1
  321. package/dist/render/util/axis_filtering.d.ts.map +1 -0
  322. package/dist/render/util/axis_filtering.js +1 -1
  323. package/dist/render/util/column_collection.cjs +8 -9
  324. package/dist/render/util/column_collection.cjs.map +1 -1
  325. package/dist/render/util/column_collection.d.ts +0 -1
  326. package/dist/render/util/column_collection.d.ts.map +1 -0
  327. package/dist/render/util/column_collection.js +4 -5
  328. package/dist/render/util/column_collection.js.map +1 -1
  329. package/dist/render/util/index.cjs +4 -4
  330. package/dist/render/util/index.js +4 -4
  331. package/dist/render/util/label.cjs +4 -5
  332. package/dist/render/util/label.cjs.map +1 -1
  333. package/dist/render/util/label.d.ts.map +1 -0
  334. package/dist/render/util/label.js +3 -4
  335. package/dist/render/util/label.js.map +1 -1
  336. package/dist/render/util/pcolumn_data.cjs +9 -10
  337. package/dist/render/util/pcolumn_data.cjs.map +1 -1
  338. package/dist/render/util/pcolumn_data.d.ts +2 -2
  339. package/dist/render/util/pcolumn_data.d.ts.map +1 -0
  340. package/dist/render/util/pcolumn_data.js +7 -8
  341. package/dist/render/util/pcolumn_data.js.map +1 -1
  342. package/dist/render/util/pframe_upgraders.cjs +1 -2
  343. package/dist/render/util/pframe_upgraders.cjs.map +1 -1
  344. package/dist/render/util/pframe_upgraders.js +1 -1
  345. package/dist/render/util/split_selectors.d.ts.map +1 -0
  346. package/dist/services/block_services.cjs +2 -3
  347. package/dist/services/block_services.cjs.map +1 -1
  348. package/dist/services/block_services.d.ts +2 -2
  349. package/dist/services/block_services.d.ts.map +1 -0
  350. package/dist/services/block_services.js +1 -2
  351. package/dist/services/block_services.js.map +1 -1
  352. package/dist/services/index.cjs +2 -2
  353. package/dist/services/index.js +2 -2
  354. package/dist/services/service_bridge.cjs +1 -2
  355. package/dist/services/service_bridge.cjs.map +1 -1
  356. package/dist/services/service_bridge.d.ts.map +1 -0
  357. package/dist/services/service_bridge.js +1 -1
  358. package/dist/services/service_resolve.d.ts.map +1 -0
  359. package/dist/version.cjs +2 -4
  360. package/dist/version.cjs.map +1 -1
  361. package/dist/version.d.ts.map +1 -0
  362. package/dist/version.js +1 -2
  363. package/dist/version.js.map +1 -1
  364. package/package.json +13 -13
  365. package/src/columns/column_collection_builder.test.ts +40 -27
  366. package/src/columns/column_collection_builder.ts +176 -131
  367. package/src/columns/column_selector.test.ts +17 -399
  368. package/src/columns/column_selector.ts +14 -127
  369. package/src/columns/column_snapshot.ts +5 -5
  370. package/src/columns/column_snapshot_provider.ts +11 -10
  371. package/src/columns/ctx_column_sources.ts +2 -2
  372. package/src/columns/expand_by_partition.test.ts +4 -4
  373. package/src/columns/expand_by_partition.ts +4 -3
  374. package/src/columns/index.ts +1 -0
  375. package/src/components/PlDataTable/createPlDataTable/createPTableDefV2.ts +42 -0
  376. package/src/components/PlDataTable/createPlDataTable/createPTableDefV3.ts +89 -0
  377. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +39 -11
  378. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +502 -313
  379. package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +122 -0
  380. package/src/components/PlDataTable/createPlDataTable/index.ts +4 -2
  381. package/src/components/PlDataTable/createPlDataTable/utils.test.ts +257 -0
  382. package/src/components/PlDataTable/createPlDataTable/utils.ts +160 -0
  383. package/src/components/PlDataTable/index.ts +13 -2
  384. package/src/components/PlDataTable/labels.ts +29 -18
  385. package/src/components/PlDataTable/state-migration.ts +3 -1
  386. package/src/components/PlDataTable/typesV5.ts +4 -4
  387. package/src/labels/derive_distinct_labels.test.ts +143 -45
  388. package/src/labels/derive_distinct_labels.ts +102 -49
  389. package/src/labels/index.ts +0 -1
  390. package/src/render/api.ts +15 -5
  391. package/src/render/util/column_collection.ts +4 -3
  392. package/src/render/util/label.ts +2 -2
  393. package/src/render/util/pcolumn_data.ts +5 -3
  394. package/dist/labels/write_labels_to_specs.cjs +0 -15
  395. package/dist/labels/write_labels_to_specs.cjs.map +0 -1
  396. package/dist/labels/write_labels_to_specs.d.ts +0 -9
  397. package/dist/labels/write_labels_to_specs.js +0 -14
  398. package/dist/labels/write_labels_to_specs.js.map +0 -1
  399. package/src/labels/write_labels_to_specs.ts +0 -12
@@ -1,9 +1,10 @@
1
1
  import { TreeNodeAccessor } from "../render/accessor.js";
2
2
  import { createColumnSnapshot } from "./column_snapshot.js";
3
3
  import { ArrayColumnProvider, toColumnSnapshotProvider } from "./column_snapshot_provider.js";
4
- import { normalizeSelectors } from "./column_selector.js";
5
- import { AnchoredIdDeriver, deriveNativeId, isPlRef } from "@milaboratories/pl-model-common";
6
-
4
+ import { convertColumnSelectorToMultiColumnSelector } from "./column_selector.js";
5
+ import { AnchoredIdDeriver, canonicalizeJson, deriveNativeId, getAxesId, isPColumnSpec } from "@milaboratories/pl-model-common";
6
+ import { throwError } from "@milaboratories/helpers";
7
+ import { uniqBy } from "es-toolkit";
7
8
  //#region src/columns/column_collection_builder.ts
8
9
  /**
9
10
  * Mutable builder that accumulates column sources, then produces
@@ -35,58 +36,22 @@ var ColumnCollectionBuilder = class {
35
36
  }
36
37
  build(options) {
37
38
  const allowPartial = options?.allowPartialColumnList === true;
38
- const hasAnchors = options !== void 0 && "anchors" in options;
39
- const allComplete = this.providers.every((p) => p.isColumnListComplete());
40
- if (!allComplete && !allowPartial) return void 0;
41
- const columnMap = this.collectColumns();
42
- if (hasAnchors) {
43
- const anchorSpecs = resolveAnchorSpecs(options.anchors, columnMap);
44
- const idDeriver = new AnchoredIdDeriver(anchorSpecs);
45
- return new AnchoredColumnCollectionImpl(this.specDriver, {
46
- columns: columnMap,
47
- idDeriver,
48
- anchorSpecs,
49
- columnListComplete: allowPartial ? allComplete : false
50
- });
51
- } else return new ColumnCollectionImpl(this.specDriver, {
52
- columns: columnMap,
53
- columnListComplete: allowPartial ? allComplete : false
39
+ if (!this.providers.every((p) => p.isColumnListComplete()) && !allowPartial) return void 0;
40
+ const columns = collectColumns(this.providers);
41
+ if (options !== void 0 && "anchors" in options) return new AnchoredColumnCollectionImpl(this.specDriver, {
42
+ anchors: options.anchors,
43
+ columns
54
44
  });
45
+ else return new ColumnCollectionImpl(this.specDriver, { columns });
55
46
  }
56
- /**
57
- * Collect all columns from all providers, dedup by NativePObjectId.
58
- * First source wins.
59
- */
60
- collectColumns() {
61
- const seen = /* @__PURE__ */ new Set();
62
- const result = /* @__PURE__ */ new Map();
63
- for (const provider of this.providers) {
64
- const columns = provider.getAllColumns();
65
- for (const col of columns) {
66
- const nativeId = deriveNativeId(col.spec);
67
- if (seen.has(nativeId)) continue;
68
- seen.add(nativeId);
69
- result.set(col.id, col);
70
- }
71
- }
72
- return result;
73
- }
74
- };
75
- const PLAIN_CONSTRAINTS = {
76
- allowFloatingSourceAxes: true,
77
- allowFloatingHitAxes: true,
78
- allowSourceQualifications: false,
79
- allowHitQualifications: false
80
47
  };
81
48
  var ColumnCollectionImpl = class {
82
49
  columns;
83
50
  specFrameEntry;
84
- columnListComplete;
85
51
  constructor(specDriver, options) {
86
52
  this.specDriver = specDriver;
87
- this.columns = options.columns;
88
- this.columnListComplete = options.columnListComplete ?? false;
89
- this.specFrameEntry = this.specDriver.createSpecFrame(Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])));
53
+ this.columns = new Map(options.columns.map((col) => [col.id, col]));
54
+ this.specFrameEntry = this.specDriver.createSpecFrame(Object.fromEntries(options.columns.map((col) => [col.id, col.spec])));
90
55
  }
91
56
  dispose() {
92
57
  this.specFrameEntry.unref();
@@ -107,7 +72,7 @@ var ColumnCollectionImpl = class {
107
72
  excludeColumns,
108
73
  axes: [],
109
74
  maxHops: 0,
110
- constraints: PLAIN_CONSTRAINTS
75
+ constraints: matchingModeToConstraints("enrichment")
111
76
  }).hits.map((hit) => this.columns.get(hit.hit.columnId)).filter((col) => col !== void 0).map((col) => this.toSnapshot(col));
112
77
  }
113
78
  toSnapshot(col) {
@@ -115,24 +80,23 @@ var ColumnCollectionImpl = class {
115
80
  }
116
81
  };
117
82
  var AnchoredColumnCollectionImpl = class {
118
- columns;
83
+ anchorsMap;
84
+ columnsMap;
119
85
  idDeriver;
86
+ uniqAnchorAxes;
87
+ idToOriginalIdMap;
120
88
  specFrameEntry;
121
- anchorAxes;
122
- /** Reverse lookup: SUniversalPColumnId → PObjectId */
123
- idToOriginal;
124
- columnListComplete;
125
89
  constructor(specDriver, options) {
126
90
  this.specDriver = specDriver;
127
- this.columns = options.columns;
128
- this.idDeriver = options.idDeriver;
129
- this.columnListComplete = options.columnListComplete ?? false;
130
- this.specFrameEntry = this.specDriver.createSpecFrame(Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])));
131
- this.anchorAxes = Object.values(options.anchorSpecs).map((spec) => ({
91
+ this.specFrameEntry = this.specDriver.createSpecFrame(Object.fromEntries(options.columns.map((col) => [col.id, col.spec])));
92
+ this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));
93
+ this.anchorsMap = resolveAnchorMap(options.anchors, options.columns, this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key));
94
+ this.idDeriver = new AnchoredIdDeriver(Object.fromEntries(Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec])));
95
+ this.uniqAnchorAxes = uniqBy(Array.from(this.anchorsMap.values(), ({ spec }) => ({
132
96
  axesSpec: spec.axesSpec,
133
97
  qualifications: []
134
- }));
135
- this.idToOriginal = new Map(Array.from(this.columns.entries()).map(([id, col]) => [this.idDeriver.deriveS(col.spec), id]));
98
+ })), (axis) => canonicalizeJson(getAxesId(axis.axesSpec)) + canonicalizeJson(axis.qualifications));
99
+ this.idToOriginalIdMap = new Map(options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id]));
136
100
  }
137
101
  dispose() {
138
102
  this.specFrameEntry.unref();
@@ -140,74 +104,122 @@ var AnchoredColumnCollectionImpl = class {
140
104
  [Symbol.dispose]() {
141
105
  this.dispose();
142
106
  }
107
+ getAnchors() {
108
+ return this.anchorsMap;
109
+ }
143
110
  getColumn(id) {
144
- const origId = this.idToOriginal.get(id);
111
+ const origId = this.idToOriginalIdMap.get(id);
145
112
  if (origId === void 0) return void 0;
146
- const col = this.columns.get(origId);
113
+ const col = this.columnsMap.get(origId);
147
114
  if (col === void 0) return void 0;
148
- return this.toSnapshot(id, col);
115
+ return remapSnapshot(id, col);
149
116
  }
150
117
  findColumns(options) {
151
118
  const constraints = matchingModeToConstraints(options?.mode ?? "enrichment");
152
119
  const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : void 0;
153
120
  const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : void 0;
154
- return this.specDriver.discoverColumns(this.specFrameEntry.key, {
121
+ const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {
155
122
  includeColumns,
156
123
  excludeColumns,
157
124
  constraints,
158
- axes: this.anchorAxes,
159
- maxHops: options?.maxHops ?? 4
160
- }).hits.map((hit) => {
125
+ maxHops: options?.maxHops ?? 4,
126
+ axes: this.uniqAnchorAxes
127
+ });
128
+ const results = [];
129
+ for (const hit of response.hits) {
161
130
  const origId = hit.hit.columnId;
162
- const col = this.columns.get(origId);
163
- if (!col) return void 0;
164
- const universalId = this.idDeriver.deriveS(col.spec);
165
- return {
166
- column: this.toSnapshot(universalId, col),
167
- originalId: origId,
168
- variants: hit.mappingVariants.map((v) => ({
169
- qualifications: v.qualifications,
170
- distinctiveQualifications: v.distinctiveQualifications
131
+ const col = this.columnsMap.get(origId) ?? throwError(`Column with id ${origId} not found in collection`);
132
+ const associatedId = this.idDeriver.deriveS(col.spec);
133
+ results.push({
134
+ path: hit.path.map((step) => ({
135
+ linker: remapSnapshot(this.idDeriver.deriveS(step.linker.spec), this.columnsMap.get(step.linker.columnId) ?? throwError(`Linker column with id ${step.linker.columnId} not found in collection`)),
136
+ qualifications: step.qualifications
171
137
  })),
172
- path: hit.path
173
- };
174
- }).filter((m) => m !== void 0);
175
- }
176
- toSnapshot(universalId, col) {
177
- return remapSnapshot(universalId, col);
138
+ column: remapSnapshot(associatedId, col),
139
+ variants: hit.mappingVariants,
140
+ originalId: origId
141
+ });
142
+ }
143
+ return results;
178
144
  }
179
145
  };
146
+ /**
147
+ * Collect all columns from all providers, dedup by NativePObjectId.
148
+ * First source wins.
149
+ */
150
+ function collectColumns(providers) {
151
+ const seen = /* @__PURE__ */ new Set();
152
+ const result = [];
153
+ for (const provider of providers) {
154
+ const columns = provider.getAllColumns();
155
+ for (const col of columns) {
156
+ const nativeId = deriveNativeId(col.spec);
157
+ if (seen.has(nativeId)) continue;
158
+ seen.add(nativeId);
159
+ result.push(col);
160
+ }
161
+ }
162
+ return result;
163
+ }
180
164
  /** Create a new snapshot with a different ID, preserving data accessors. */
181
165
  function remapSnapshot(id, col) {
182
- return createColumnSnapshot(id, col.spec, col.dataStatus, col.data);
166
+ return createColumnSnapshot(id, col.spec, col.data, col.dataStatus);
183
167
  }
184
168
  /** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */
185
169
  function toMultiColumnSelectors(input) {
186
- return normalizeSelectors(input);
170
+ return convertColumnSelectorToMultiColumnSelector(input);
187
171
  }
188
172
  /**
189
173
  * Resolve each anchor value to a PColumnSpec.
190
174
  * - PColumnSpec: used directly
191
175
  * - PObjectId (string): looked up in the collected column map
192
- * - PlRef: not supported at this level — caller must resolve before building
193
176
  */
194
- function resolveAnchorSpecs(anchors, columnMap) {
195
- const result = {};
177
+ function resolveAnchorMap(anchors, columns, discoverColumns) {
178
+ const result = /* @__PURE__ */ new Map();
179
+ const resovedIds = /* @__PURE__ */ new Set();
180
+ const getDuplicateError = (key) => `Anchor "${key}": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;
196
181
  for (const [key, anchor] of Object.entries(anchors)) if (typeof anchor === "string") {
197
- const col = columnMap.get(anchor);
198
- if (!col) throw new Error(`Anchor "${key}": column with id "${anchor}" not found in sources`);
199
- result[key] = col.spec;
200
- } else if (isPlRef(anchor)) throw new Error(`Anchor "${key}": PlRef anchors must be resolved to PColumnSpec before building. Use the column's spec directly or pass its PObjectId.`);
201
- else result[key] = anchor;
182
+ const found = columns.find((col) => col.id === anchor) ?? throwError(`Anchor "${key}": column with id "${anchor}" not found in sources`);
183
+ if (resovedIds.has(found.id)) throwError(getDuplicateError(key));
184
+ result.set(key, {
185
+ columnId: found.id,
186
+ spec: found.spec
187
+ });
188
+ resovedIds.add(found.id);
189
+ } else if ("kind" in anchor) {
190
+ if (!isPColumnSpec(anchor)) throwError(`Anchor "${key}": invalid PColumnSpec`);
191
+ const nativeId = deriveNativeId(anchor);
192
+ const found = columns.find((col) => deriveNativeId(col.spec) === nativeId) ?? throwError(`Anchor "${key}": no column matching spec found in sources`);
193
+ if (resovedIds.has(found.id)) throwError(getDuplicateError(key));
194
+ result.set(key, {
195
+ columnId: found.id,
196
+ spec: anchor
197
+ });
198
+ resovedIds.add(found.id);
199
+ } else {
200
+ const matched = discoverColumns({
201
+ includeColumns: toMultiColumnSelectors(anchor),
202
+ excludeColumns: void 0,
203
+ axes: [],
204
+ maxHops: 0,
205
+ constraints: matchingModeToConstraints("exact")
206
+ });
207
+ if (matched.hits.length === 0) throwError(`Anchor "${key}": no columns matched selector`);
208
+ if (matched.hits.length > 1) throwError(`Anchor "${key}": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`);
209
+ if (resovedIds.has(matched.hits[0].hit.columnId)) throwError(getDuplicateError(key));
210
+ result.set(key, matched.hits[0].hit);
211
+ resovedIds.add(matched.hits[0].hit.columnId);
212
+ }
213
+ if (resovedIds.size === 0) throwError("At least one anchor must be resolved to a valid column");
202
214
  return result;
203
215
  }
204
216
  function matchingModeToConstraints(mode) {
205
217
  switch (mode) {
206
218
  case "enrichment": return {
207
219
  allowFloatingSourceAxes: true,
208
- allowFloatingHitAxes: true,
209
- allowSourceQualifications: false,
210
- allowHitQualifications: false
220
+ allowFloatingHitAxes: false,
221
+ allowSourceQualifications: true,
222
+ allowHitQualifications: true
211
223
  };
212
224
  case "related": return {
213
225
  allowFloatingSourceAxes: true,
@@ -223,7 +235,7 @@ function matchingModeToConstraints(mode) {
223
235
  };
224
236
  }
225
237
  }
226
-
227
238
  //#endregion
228
239
  export { ColumnCollectionBuilder };
240
+
229
241
  //# sourceMappingURL=column_collection_builder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"column_collection_builder.js","names":[],"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.js","names":[],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n MultiColumnSelector,\n NativePObjectId,\n PColumnIdAndSpec,\n PColumnSpec,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n AnchoredIdDeriver,\n canonicalizeJson,\n deriveNativeId,\n getAxesId,\n isPColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelector, RelaxedColumnSelector } from \"./column_selector\";\nimport { convertColumnSelectorToMultiColumnSelector } 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\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { uniqBy } from \"es-toolkit\";\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?: ColumnSelector;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelector;\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\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\n /** List of anchors used for discovery, with their resolved specs. */\n getAnchors(): Map<string, PColumnIdAndSpec>;\n\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: {\n linker: ColumnSnapshot<SUniversalPColumnId>;\n qualifications: AxisQualification[];\n }[];\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 type AnchorEntry = PObjectId | PColumnSpec | RelaxedColumnSelector;\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, AnchorEntry>;\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\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 columns = collectColumns(this.providers);\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n if (hasAnchors) {\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n anchors: options.anchors,\n columns,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns,\n });\n }\n }\n}\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: ColumnSnapshot<PObjectId>[];\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = new Map(options.columns.map((col) => [col.id, col]));\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [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: matchingModeToConstraints(\"enrichment\"),\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 anchors: Record<string, AnchorEntry>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly anchorsMap: Map<string, PColumnIdAndSpec>;\n private readonly columnsMap: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly uniqAnchorAxes: ColumnAxesWithQualifications[];\n private readonly idToOriginalIdMap: Map<SUniversalPColumnId, PObjectId>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));\n this.anchorsMap = resolveAnchorMap(\n options.anchors,\n options.columns,\n this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key),\n );\n this.idDeriver = new AnchoredIdDeriver(\n Object.fromEntries(\n Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec] as const),\n ),\n );\n this.uniqAnchorAxes = uniqBy(\n Array.from(this.anchorsMap.values(), ({ spec }) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n })),\n (axis) => canonicalizeJson(getAxesId(axis.axesSpec)) + canonicalizeJson(axis.qualifications),\n );\n this.idToOriginalIdMap = new Map(\n options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id] as const),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getAnchors(): Map<string, PColumnIdAndSpec> {\n return this.anchorsMap;\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginalIdMap.get(id);\n if (origId === undefined) return undefined;\n const col = this.columnsMap.get(origId);\n if (col === undefined) return undefined;\n return remapSnapshot(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 maxHops: options?.maxHops ?? 4,\n axes: this.uniqAnchorAxes,\n });\n\n // Map every WASM discovery hit to a ColumnMatch.\n // The same physical column may appear multiple times when reachable through\n // different linker paths — each hit becomes a separate ColumnMatch so that\n // the caller can expand them into distinct table columns.\n const results: ColumnMatch[] = [];\n for (const hit of response.hits) {\n const origId = hit.hit.columnId as PObjectId;\n const col =\n this.columnsMap.get(origId) ??\n throwError(`Column with id ${origId} not found in collection`);\n const associatedId = this.idDeriver.deriveS(col.spec);\n\n results.push({\n path: hit.path.map((step) => ({\n linker: remapSnapshot(\n this.idDeriver.deriveS(step.linker.spec),\n this.columnsMap.get(step.linker.columnId) ??\n throwError(`Linker column with id ${step.linker.columnId} not found in collection`),\n ),\n qualifications: step.qualifications,\n })),\n column: remapSnapshot(associatedId, col),\n variants: hit.mappingVariants,\n originalId: origId,\n });\n }\n\n return results;\n }\n}\n\n/**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\nfunction collectColumns(providers: ColumnSnapshotProvider[]): ColumnSnapshot<PObjectId>[] {\n const seen = new Set<NativePObjectId>();\n const result: ColumnSnapshot<PObjectId>[] = [];\n\n for (const provider of 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.push(col);\n }\n }\n\n return result;\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.data, col.dataStatus);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelector): MultiColumnSelector[] {\n return convertColumnSelectorToMultiColumnSelector(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 */\nfunction resolveAnchorMap(\n anchors: Record<string, AnchorEntry>,\n columns: ColumnSnapshot<PObjectId>[],\n discoverColumns: (request: DiscoverColumnsRequest) => DiscoverColumnsResponse,\n): Map<string, PColumnIdAndSpec> {\n const result = new Map<string, PColumnIdAndSpec>();\n const resovedIds = new Set<PObjectId>();\n const getDuplicateError = (key: string) =>\n `Anchor \"${key}\": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;\n\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n const found =\n columns.find((col) => col.id === anchor) ??\n throwError(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: found.spec });\n resovedIds.add(found.id);\n } else if (\"kind\" in anchor) {\n if (!isPColumnSpec(anchor)) throwError(`Anchor \"${key}\": invalid PColumnSpec`);\n const nativeId = deriveNativeId(anchor);\n const found =\n columns.find((col) => deriveNativeId(col.spec) === nativeId) ??\n throwError(`Anchor \"${key}\": no column matching spec found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: anchor });\n resovedIds.add(found.id);\n } else {\n const matched = discoverColumns({\n includeColumns: toMultiColumnSelectors(anchor),\n excludeColumns: undefined,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"exact\"),\n });\n if (matched.hits.length === 0) {\n throwError(`Anchor \"${key}\": no columns matched selector`);\n }\n if (matched.hits.length > 1) {\n throwError(\n `Anchor \"${key}\": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`,\n );\n }\n if (resovedIds.has(matched.hits[0].hit.columnId as PObjectId)) {\n throwError(getDuplicateError(key));\n }\n\n result.set(key, matched.hits[0].hit);\n resovedIds.add(matched.hits[0].hit.columnId);\n }\n }\n\n if (resovedIds.size === 0) {\n throwError(\"At least one anchor must be resolved to a valid column\");\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: false,\n allowSourceQualifications: true,\n allowHitQualifications: true,\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,4 +1,3 @@
1
-
2
1
  //#region src/columns/column_selector.ts
3
2
  function normalizeStringMatchers(input) {
4
3
  if (typeof input === "string") return [{
@@ -19,7 +18,7 @@ function normalizeRecord(input) {
19
18
  function normalizeTypes(input) {
20
19
  return Array.isArray(input) ? input : [input];
21
20
  }
22
- function normalizeAxisSelector(input) {
21
+ function convertRelaxedAxisSelectorToMultiAxisSelector(input) {
23
22
  const result = {};
24
23
  if (input.name !== void 0) result.name = normalizeStringMatchers(input.name);
25
24
  if (input.type !== void 0) result.type = normalizeTypes(input.type);
@@ -28,95 +27,23 @@ function normalizeAxisSelector(input) {
28
27
  if (input.annotations !== void 0) result.annotations = normalizeRecord(input.annotations);
29
28
  return result;
30
29
  }
31
- /** Normalize relaxed input to strict ColumnSelector[]. */
32
- function normalizeSelectors(input) {
33
- return (Array.isArray(input) ? input : [input]).map(normalizeSingleSelector);
34
- }
35
- function normalizeSingleSelector(input) {
30
+ function convertRelaxedColumnSelectorToMultiColumnSelector(input) {
36
31
  const result = {};
37
32
  if (input.name !== void 0) result.name = normalizeStringMatchers(input.name);
38
33
  if (input.type !== void 0) result.type = normalizeTypes(input.type);
39
34
  if (input.domain !== void 0) result.domain = normalizeRecord(input.domain);
40
35
  if (input.contextDomain !== void 0) result.contextDomain = normalizeRecord(input.contextDomain);
41
36
  if (input.annotations !== void 0) result.annotations = normalizeRecord(input.annotations);
42
- if (input.axes !== void 0) result.axes = input.axes.map(normalizeAxisSelector);
37
+ if (input.axes !== void 0) result.axes = input.axes.map(convertRelaxedAxisSelectorToMultiAxisSelector);
43
38
  if (input.partialAxesMatch !== void 0) result.partialAxesMatch = input.partialAxesMatch;
44
39
  return result;
45
40
  }
46
- function matchStringValue(value, matchers) {
47
- return matchers.some((m) => {
48
- if (m.type === "exact") return value === m.value;
49
- return new RegExp(`^(?:${m.value})$`).test(value);
50
- });
51
- }
52
- function matchRecordField(actual, required) {
53
- const record = actual ?? {};
54
- for (const [key, matchers] of Object.entries(required)) {
55
- const value = record[key];
56
- if (value === void 0) return false;
57
- if (!matchStringValue(value, matchers)) return false;
58
- }
59
- return true;
60
- }
61
- /** Get combined domain: column's own domain merged with all axis domains. */
62
- function getCombinedDomain(spec) {
63
- const result = {};
64
- if (spec.domain) Object.assign(result, spec.domain);
65
- for (const axis of spec.axesSpec) if (axis.domain) Object.assign(result, axis.domain);
66
- return result;
41
+ function convertColumnSelectorToMultiColumnSelector(input) {
42
+ return (Array.isArray(input) ? input : [input]).map(convertRelaxedColumnSelectorToMultiColumnSelector);
67
43
  }
68
- /** Get combined context domain: column's own contextDomain merged with all axis contextDomains. */
69
- function getCombinedContextDomain(spec) {
70
- const result = {};
71
- if (spec.contextDomain) Object.assign(result, spec.contextDomain);
72
- for (const axis of spec.axesSpec) if ("contextDomain" in axis && axis.contextDomain) Object.assign(result, axis.contextDomain);
73
- return result;
74
- }
75
- function matchAxisSelector(axis, selector) {
76
- if (selector.name !== void 0 && !matchStringValue(axis.name, selector.name)) return false;
77
- if (selector.type !== void 0 && !selector.type.includes(axis.type)) return false;
78
- if (selector.domain !== void 0 && !matchRecordField(axis.domain, selector.domain)) return false;
79
- if (selector.contextDomain !== void 0 && !matchRecordField("contextDomain" in axis ? axis.contextDomain : void 0, selector.contextDomain)) return false;
80
- if (selector.annotations !== void 0 && !matchRecordField(axis.annotations, selector.annotations)) return false;
81
- return true;
82
- }
83
- /** Check if a PColumnSpec matches a single strict ColumnSelector. */
84
- function matchColumn(spec, selector) {
85
- if (selector.name !== void 0 && !matchStringValue(spec.name, selector.name)) return false;
86
- if (selector.type !== void 0 && !selector.type.includes(spec.valueType)) return false;
87
- if (selector.domain !== void 0) {
88
- if (!matchRecordField(getCombinedDomain(spec), selector.domain)) return false;
89
- }
90
- if (selector.contextDomain !== void 0) {
91
- if (!matchRecordField(getCombinedContextDomain(spec), selector.contextDomain)) return false;
92
- }
93
- if (selector.annotations !== void 0) {
94
- if (!matchRecordField(spec.annotations, selector.annotations)) return false;
95
- }
96
- if (selector.axes !== void 0) if (selector.partialAxesMatch ?? true) {
97
- for (const axisSel of selector.axes) if (!spec.axesSpec.some((axis) => matchAxisSelector(axis, axisSel))) return false;
98
- } else {
99
- if (spec.axesSpec.length !== selector.axes.length) return false;
100
- for (let i = 0; i < selector.axes.length; i++) if (!matchAxisSelector(spec.axesSpec[i], selector.axes[i])) return false;
101
- }
102
- return true;
103
- }
104
- /** Check if a PColumnSpec matches any of the selectors (OR across array). */
105
- function matchColumnSelectors(selectors, spec) {
106
- return selectors.some((sel) => matchColumn(spec, sel));
107
- }
108
- /**
109
- * Convert selector input to a predicate function.
110
- * Normalizes relaxed form, then returns a function that OR-matches.
111
- */
112
- function columnSelectorsToPredicate(input) {
113
- const selectors = normalizeSelectors(input);
114
- return (spec) => matchColumnSelectors(selectors, spec);
115
- }
116
-
117
44
  //#endregion
118
- exports.columnSelectorsToPredicate = columnSelectorsToPredicate;
119
- exports.matchColumn = matchColumn;
120
- exports.matchColumnSelectors = matchColumnSelectors;
121
- exports.normalizeSelectors = normalizeSelectors;
45
+ exports.convertColumnSelectorToMultiColumnSelector = convertColumnSelectorToMultiColumnSelector;
46
+ exports.convertRelaxedAxisSelectorToMultiAxisSelector = convertRelaxedAxisSelectorToMultiAxisSelector;
47
+ exports.convertRelaxedColumnSelectorToMultiColumnSelector = convertRelaxedColumnSelectorToMultiColumnSelector;
48
+
122
49
  //# sourceMappingURL=column_selector.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"column_selector.cjs","names":[],"sources":["../../src/columns/column_selector.ts"],"sourcesContent":["import type {\n AxisValueType,\n ColumnValueType,\n MultiAxisSelector,\n MultiColumnSelector,\n PColumnSpec,\n StringMatcher,\n} from \"@milaboratories/pl-model-common\";\n\nexport type { StringMatcher } from \"@milaboratories/pl-model-common\";\n\n// --- Relaxed types ---\n\n/** Relaxed string matcher input: plain string, single matcher, or array of mixed. */\nexport type RelaxedStringMatchers = string | StringMatcher | (string | StringMatcher)[];\n\n/** Relaxed record matcher: values can be plain strings or relaxed matchers. */\nexport type RelaxedRecord = Record<string, RelaxedStringMatchers>;\n\n/** Relaxed axis selector — accepts plain strings where strict requires StringMatcher[]. */\nexport interface RelaxedAxisSelector {\n name?: RelaxedStringMatchers;\n type?: AxisValueType | AxisValueType[];\n domain?: RelaxedRecord;\n contextDomain?: RelaxedRecord;\n annotations?: RelaxedRecord;\n}\n\n/** Relaxed column selector — convenient hand-written form. */\nexport interface RelaxedColumnSelector {\n name?: RelaxedStringMatchers;\n type?: ColumnValueType | ColumnValueType[];\n domain?: RelaxedRecord;\n contextDomain?: RelaxedRecord;\n annotations?: RelaxedRecord;\n axes?: RelaxedAxisSelector[];\n partialAxesMatch?: boolean;\n}\n\n/** Input that normalizes to ColumnSelector[]. */\nexport type ColumnSelectorInput = RelaxedColumnSelector | RelaxedColumnSelector[];\n\n// --- Normalization ---\n\nfunction normalizeStringMatchers(input: RelaxedStringMatchers): StringMatcher[] {\n if (typeof input === \"string\") return [{ type: \"regex\", value: input }];\n if (!Array.isArray(input)) return [input];\n return input.map((v) =>\n typeof v === \"string\" ? ({ type: \"regex\", value: v } satisfies StringMatcher) : v,\n );\n}\n\nfunction normalizeRecord(input: RelaxedRecord): Record<string, StringMatcher[]> {\n const result: Record<string, StringMatcher[]> = {};\n for (const [key, value] of Object.entries(input)) {\n result[key] = normalizeStringMatchers(value);\n }\n return result;\n}\n\nfunction normalizeTypes<T>(input: T | T[]): T[] {\n return Array.isArray(input) ? input : [input];\n}\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\nfunction normalizeAxisSelector(input: RelaxedAxisSelector): MultiAxisSelector {\n const result: Mutable<MultiAxisSelector> = {};\n if (input.name !== undefined) result.name = normalizeStringMatchers(input.name);\n if (input.type !== undefined) result.type = normalizeTypes(input.type);\n if (input.domain !== undefined) result.domain = normalizeRecord(input.domain);\n if (input.contextDomain !== undefined)\n result.contextDomain = normalizeRecord(input.contextDomain);\n if (input.annotations !== undefined) result.annotations = normalizeRecord(input.annotations);\n return result;\n}\n\n/** Normalize relaxed input to strict ColumnSelector[]. */\nexport function normalizeSelectors(input: ColumnSelectorInput): MultiColumnSelector[] {\n const arr = Array.isArray(input) ? input : [input];\n return arr.map(normalizeSingleSelector);\n}\n\nfunction normalizeSingleSelector(input: RelaxedColumnSelector): MultiColumnSelector {\n const result: Mutable<MultiColumnSelector> = {};\n if (input.name !== undefined) result.name = normalizeStringMatchers(input.name);\n if (input.type !== undefined) result.type = normalizeTypes(input.type);\n if (input.domain !== undefined) result.domain = normalizeRecord(input.domain);\n if (input.contextDomain !== undefined)\n result.contextDomain = normalizeRecord(input.contextDomain);\n if (input.annotations !== undefined) result.annotations = normalizeRecord(input.annotations);\n if (input.axes !== undefined) result.axes = input.axes.map(normalizeAxisSelector);\n if (input.partialAxesMatch !== undefined) result.partialAxesMatch = input.partialAxesMatch;\n return result;\n}\n\n// --- Matching ---\n\nfunction matchStringValue(value: string, matchers: StringMatcher[]): boolean {\n return matchers.some((m) => {\n if (m.type === \"exact\") return value === m.value;\n return new RegExp(`^(?:${m.value})$`).test(value);\n });\n}\n\nfunction matchRecordField(\n actual: Record<string, string> | undefined,\n required: Record<string, StringMatcher[]>,\n): boolean {\n const record = actual ?? {};\n for (const [key, matchers] of Object.entries(required)) {\n const value = record[key];\n if (value === undefined) return false;\n if (!matchStringValue(value, matchers)) return false;\n }\n return true;\n}\n\n/** Get combined domain: column's own domain merged with all axis domains. */\nfunction getCombinedDomain(spec: PColumnSpec): Record<string, string> {\n const result: Record<string, string> = {};\n if (spec.domain) Object.assign(result, spec.domain);\n for (const axis of spec.axesSpec) {\n if (axis.domain) Object.assign(result, axis.domain);\n }\n return result;\n}\n\n/** Get combined context domain: column's own contextDomain merged with all axis contextDomains. */\nfunction getCombinedContextDomain(spec: PColumnSpec): Record<string, string> {\n const result: Record<string, string> = {};\n if (spec.contextDomain) Object.assign(result, spec.contextDomain);\n for (const axis of spec.axesSpec) {\n if (\"contextDomain\" in axis && axis.contextDomain) Object.assign(result, axis.contextDomain);\n }\n return result;\n}\n\nfunction matchAxisSelector(\n axis: PColumnSpec[\"axesSpec\"][number],\n selector: MultiAxisSelector,\n): boolean {\n if (selector.name !== undefined && !matchStringValue(axis.name, selector.name)) return false;\n if (selector.type !== undefined && !selector.type.includes(axis.type)) return false;\n if (selector.domain !== undefined && !matchRecordField(axis.domain, selector.domain))\n return false;\n if (\n selector.contextDomain !== undefined &&\n !matchRecordField(\n \"contextDomain\" in axis ? (axis.contextDomain as Record<string, string>) : undefined,\n selector.contextDomain,\n )\n )\n return false;\n if (\n selector.annotations !== undefined &&\n !matchRecordField(axis.annotations, selector.annotations)\n )\n return false;\n return true;\n}\n\n/** Check if a PColumnSpec matches a single strict ColumnSelector. */\nexport function matchColumn(spec: PColumnSpec, selector: MultiColumnSelector): boolean {\n if (selector.name !== undefined && !matchStringValue(spec.name, selector.name)) return false;\n if (selector.type !== undefined && !selector.type.includes(spec.valueType)) return false;\n\n if (selector.domain !== undefined) {\n const combined = getCombinedDomain(spec);\n if (!matchRecordField(combined, selector.domain)) return false;\n }\n\n if (selector.contextDomain !== undefined) {\n const combined = getCombinedContextDomain(spec);\n if (!matchRecordField(combined, selector.contextDomain)) return false;\n }\n\n if (selector.annotations !== undefined) {\n if (!matchRecordField(spec.annotations, selector.annotations)) return false;\n }\n\n if (selector.axes !== undefined) {\n const partialMatch = selector.partialAxesMatch ?? true;\n if (partialMatch) {\n for (const axisSel of selector.axes) {\n if (!spec.axesSpec.some((axis) => matchAxisSelector(axis, axisSel))) return false;\n }\n } else {\n if (spec.axesSpec.length !== selector.axes.length) return false;\n for (let i = 0; i < selector.axes.length; i++) {\n if (!matchAxisSelector(spec.axesSpec[i], selector.axes[i])) return false;\n }\n }\n }\n\n return true;\n}\n\n/** Check if a PColumnSpec matches any of the selectors (OR across array). */\nexport function matchColumnSelectors(selectors: MultiColumnSelector[], spec: PColumnSpec): boolean {\n return selectors.some((sel) => matchColumn(spec, sel));\n}\n\n/**\n * Convert selector input to a predicate function.\n * Normalizes relaxed form, then returns a function that OR-matches.\n */\nexport function columnSelectorsToPredicate(\n input: ColumnSelectorInput,\n): (spec: PColumnSpec) => boolean {\n const selectors = normalizeSelectors(input);\n return (spec) => matchColumnSelectors(selectors, spec);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"column_selector.cjs","names":[],"sources":["../../src/columns/column_selector.ts"],"sourcesContent":["import type {\n AxisValueType,\n ColumnValueType,\n MultiAxisSelector,\n MultiColumnSelector,\n StringMatcher,\n} from \"@milaboratories/pl-model-common\";\n\nexport type { StringMatcher } from \"@milaboratories/pl-model-common\";\n\n// --- Relaxed types ---\n\n/** Relaxed string matcher input: plain string, single matcher, or array of mixed. */\nexport type RelaxedStringMatchers = string | StringMatcher | (string | StringMatcher)[];\n\n/** Relaxed record matcher: values can be plain strings or relaxed matchers. */\nexport type RelaxedRecord = Record<string, RelaxedStringMatchers>;\n\n/** Relaxed axis selector — accepts plain strings where strict requires StringMatcher[]. */\nexport interface RelaxedAxisSelector {\n name?: RelaxedStringMatchers;\n type?: AxisValueType | AxisValueType[];\n domain?: RelaxedRecord;\n contextDomain?: RelaxedRecord;\n annotations?: RelaxedRecord;\n}\n\n/** Relaxed column selector — convenient hand-written form. */\nexport interface RelaxedColumnSelector {\n name?: RelaxedStringMatchers;\n type?: ColumnValueType | ColumnValueType[];\n domain?: RelaxedRecord;\n contextDomain?: RelaxedRecord;\n annotations?: RelaxedRecord;\n axes?: RelaxedAxisSelector[];\n partialAxesMatch?: boolean;\n}\n\n/** Input that normalizes to ColumnSelector[]. */\nexport type ColumnSelector = RelaxedColumnSelector | RelaxedColumnSelector[];\n\n// --- Normalization ---\n\nfunction normalizeStringMatchers(input: RelaxedStringMatchers): StringMatcher[] {\n if (typeof input === \"string\") return [{ type: \"regex\", value: input }];\n if (!Array.isArray(input)) return [input];\n return input.map((v) =>\n typeof v === \"string\" ? ({ type: \"regex\", value: v } satisfies StringMatcher) : v,\n );\n}\n\nfunction normalizeRecord(input: RelaxedRecord): Record<string, StringMatcher[]> {\n const result: Record<string, StringMatcher[]> = {};\n for (const [key, value] of Object.entries(input)) {\n result[key] = normalizeStringMatchers(value);\n }\n return result;\n}\n\nfunction normalizeTypes<T>(input: T | T[]): T[] {\n return Array.isArray(input) ? input : [input];\n}\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\nexport function convertRelaxedAxisSelectorToMultiAxisSelector(\n input: RelaxedAxisSelector,\n): MultiAxisSelector {\n const result: Mutable<MultiAxisSelector> = {};\n if (input.name !== undefined) result.name = normalizeStringMatchers(input.name);\n if (input.type !== undefined) result.type = normalizeTypes(input.type);\n if (input.domain !== undefined) result.domain = normalizeRecord(input.domain);\n if (input.contextDomain !== undefined)\n result.contextDomain = normalizeRecord(input.contextDomain);\n if (input.annotations !== undefined) result.annotations = normalizeRecord(input.annotations);\n return result;\n}\n\nexport function convertRelaxedColumnSelectorToMultiColumnSelector(\n input: RelaxedColumnSelector,\n): MultiColumnSelector {\n const result: Mutable<MultiColumnSelector> = {};\n if (input.name !== undefined) result.name = normalizeStringMatchers(input.name);\n if (input.type !== undefined) result.type = normalizeTypes(input.type);\n if (input.domain !== undefined) result.domain = normalizeRecord(input.domain);\n if (input.contextDomain !== undefined)\n result.contextDomain = normalizeRecord(input.contextDomain);\n if (input.annotations !== undefined) result.annotations = normalizeRecord(input.annotations);\n if (input.axes !== undefined)\n result.axes = input.axes.map(convertRelaxedAxisSelectorToMultiAxisSelector);\n if (input.partialAxesMatch !== undefined) result.partialAxesMatch = input.partialAxesMatch;\n return result;\n}\n\nexport function convertColumnSelectorToMultiColumnSelector(\n input: ColumnSelector,\n): MultiColumnSelector[] {\n const arr = Array.isArray(input) ? input : [input];\n return arr.map(convertRelaxedColumnSelectorToMultiColumnSelector);\n}\n"],"mappings":";AA2CA,SAAS,wBAAwB,OAA+C;AAC9E,KAAI,OAAO,UAAU,SAAU,QAAO,CAAC;EAAE,MAAM;EAAS,OAAO;EAAO,CAAC;AACvE,KAAI,CAAC,MAAM,QAAQ,MAAM,CAAE,QAAO,CAAC,MAAM;AACzC,QAAO,MAAM,KAAK,MAChB,OAAO,MAAM,WAAY;EAAE,MAAM;EAAS,OAAO;EAAG,GAA4B,EACjF;;AAGH,SAAS,gBAAgB,OAAuD;CAC9E,MAAM,SAA0C,EAAE;AAClD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,QAAO,OAAO,wBAAwB,MAAM;AAE9C,QAAO;;AAGT,SAAS,eAAkB,OAAqB;AAC9C,QAAO,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;;AAK/C,SAAgB,8CACd,OACmB;CACnB,MAAM,SAAqC,EAAE;AAC7C,KAAI,MAAM,SAAS,KAAA,EAAW,QAAO,OAAO,wBAAwB,MAAM,KAAK;AAC/E,KAAI,MAAM,SAAS,KAAA,EAAW,QAAO,OAAO,eAAe,MAAM,KAAK;AACtE,KAAI,MAAM,WAAW,KAAA,EAAW,QAAO,SAAS,gBAAgB,MAAM,OAAO;AAC7E,KAAI,MAAM,kBAAkB,KAAA,EAC1B,QAAO,gBAAgB,gBAAgB,MAAM,cAAc;AAC7D,KAAI,MAAM,gBAAgB,KAAA,EAAW,QAAO,cAAc,gBAAgB,MAAM,YAAY;AAC5F,QAAO;;AAGT,SAAgB,kDACd,OACqB;CACrB,MAAM,SAAuC,EAAE;AAC/C,KAAI,MAAM,SAAS,KAAA,EAAW,QAAO,OAAO,wBAAwB,MAAM,KAAK;AAC/E,KAAI,MAAM,SAAS,KAAA,EAAW,QAAO,OAAO,eAAe,MAAM,KAAK;AACtE,KAAI,MAAM,WAAW,KAAA,EAAW,QAAO,SAAS,gBAAgB,MAAM,OAAO;AAC7E,KAAI,MAAM,kBAAkB,KAAA,EAC1B,QAAO,gBAAgB,gBAAgB,MAAM,cAAc;AAC7D,KAAI,MAAM,gBAAgB,KAAA,EAAW,QAAO,cAAc,gBAAgB,MAAM,YAAY;AAC5F,KAAI,MAAM,SAAS,KAAA,EACjB,QAAO,OAAO,MAAM,KAAK,IAAI,8CAA8C;AAC7E,KAAI,MAAM,qBAAqB,KAAA,EAAW,QAAO,mBAAmB,MAAM;AAC1E,QAAO;;AAGT,SAAgB,2CACd,OACuB;AAEvB,SADY,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM,EACvC,IAAI,kDAAkD"}
@@ -1,4 +1,4 @@
1
- import { AxisValueType, ColumnValueType, MultiColumnSelector, PColumnSpec, StringMatcher, StringMatcher as StringMatcher$1 } from "@milaboratories/pl-model-common";
1
+ import { AxisValueType, ColumnValueType, MultiAxisSelector, MultiColumnSelector, StringMatcher, StringMatcher as StringMatcher$1 } from "@milaboratories/pl-model-common";
2
2
 
3
3
  //#region src/columns/column_selector.d.ts
4
4
  /** Relaxed string matcher input: plain string, single matcher, or array of mixed. */
@@ -24,18 +24,10 @@ interface RelaxedColumnSelector {
24
24
  partialAxesMatch?: boolean;
25
25
  }
26
26
  /** Input that normalizes to ColumnSelector[]. */
27
- type ColumnSelectorInput = RelaxedColumnSelector | RelaxedColumnSelector[];
28
- /** Normalize relaxed input to strict ColumnSelector[]. */
29
- declare function normalizeSelectors(input: ColumnSelectorInput): MultiColumnSelector[];
30
- /** Check if a PColumnSpec matches a single strict ColumnSelector. */
31
- declare function matchColumn(spec: PColumnSpec, selector: MultiColumnSelector): boolean;
32
- /** Check if a PColumnSpec matches any of the selectors (OR across array). */
33
- declare function matchColumnSelectors(selectors: MultiColumnSelector[], spec: PColumnSpec): boolean;
34
- /**
35
- * Convert selector input to a predicate function.
36
- * Normalizes relaxed form, then returns a function that OR-matches.
37
- */
38
- declare function columnSelectorsToPredicate(input: ColumnSelectorInput): (spec: PColumnSpec) => boolean;
27
+ type ColumnSelector = RelaxedColumnSelector | RelaxedColumnSelector[];
28
+ declare function convertRelaxedAxisSelectorToMultiAxisSelector(input: RelaxedAxisSelector): MultiAxisSelector;
29
+ declare function convertRelaxedColumnSelectorToMultiColumnSelector(input: RelaxedColumnSelector): MultiColumnSelector;
30
+ declare function convertColumnSelectorToMultiColumnSelector(input: ColumnSelector): MultiColumnSelector[];
39
31
  //#endregion
40
- export { ColumnSelectorInput, RelaxedAxisSelector, RelaxedColumnSelector, RelaxedRecord, RelaxedStringMatchers, type StringMatcher$1 as StringMatcher, columnSelectorsToPredicate, matchColumn, matchColumnSelectors, normalizeSelectors };
32
+ export { ColumnSelector, RelaxedAxisSelector, RelaxedColumnSelector, RelaxedRecord, RelaxedStringMatchers, type StringMatcher$1 as StringMatcher, convertColumnSelectorToMultiColumnSelector, convertRelaxedAxisSelectorToMultiAxisSelector, convertRelaxedColumnSelectorToMultiColumnSelector };
41
33
  //# sourceMappingURL=column_selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column_selector.d.ts","names":[],"sources":["../../src/columns/column_selector.ts"],"mappings":";;;;KAaY,qBAAA,YAAiC,aAAA,aAA0B,aAAA;;KAG3D,aAAA,GAAgB,MAAA,SAAe,qBAAA;;UAG1B,mBAAA;EACf,IAAA,GAAO,qBAAA;EACP,IAAA,GAAO,aAAA,GAAgB,aAAA;EACvB,MAAA,GAAS,aAAA;EACT,aAAA,GAAgB,aAAA;EAChB,WAAA,GAAc,aAAA;AAAA;;UAIC,qBAAA;EACf,IAAA,GAAO,qBAAA;EACP,IAAA,GAAO,eAAA,GAAkB,eAAA;EACzB,MAAA,GAAS,aAAA;EACT,aAAA,GAAgB,aAAA;EAChB,WAAA,GAAc,aAAA;EACd,IAAA,GAAO,mBAAA;EACP,gBAAA;AAAA;;KAIU,cAAA,GAAiB,qBAAA,GAAwB,qBAAA;AAAA,iBA0BrC,6CAAA,CACd,KAAA,EAAO,mBAAA,GACN,iBAAA;AAAA,iBAWa,iDAAA,CACd,KAAA,EAAO,qBAAA,GACN,mBAAA;AAAA,iBAca,0CAAA,CACd,KAAA,EAAO,cAAA,GACN,mBAAA"}