@platforma-sdk/model 1.79.27 → 1.80.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 (356) hide show
  1. package/dist/block_model.d.ts +2 -0
  2. package/dist/block_model.d.ts.map +1 -1
  3. package/dist/columns/column.cjs +28 -0
  4. package/dist/columns/column.cjs.map +1 -0
  5. package/dist/columns/column.d.ts +30 -0
  6. package/dist/columns/column.d.ts.map +1 -0
  7. package/dist/columns/column.js +27 -0
  8. package/dist/columns/column.js.map +1 -0
  9. package/dist/columns/column_lazy.cjs +248 -0
  10. package/dist/columns/column_lazy.cjs.map +1 -0
  11. package/dist/columns/column_lazy.d.ts +137 -0
  12. package/dist/columns/column_lazy.d.ts.map +1 -0
  13. package/dist/columns/column_lazy.js +245 -0
  14. package/dist/columns/column_lazy.js.map +1 -0
  15. package/dist/columns/column_providers/index.cjs +62 -0
  16. package/dist/columns/column_providers/index.cjs.map +1 -0
  17. package/dist/columns/column_providers/index.d.ts +30 -0
  18. package/dist/columns/column_providers/index.d.ts.map +1 -0
  19. package/dist/columns/column_providers/index.js +53 -0
  20. package/dist/columns/column_providers/index.js.map +1 -0
  21. package/dist/columns/column_providers/providers.cjs +123 -0
  22. package/dist/columns/column_providers/providers.cjs.map +1 -0
  23. package/dist/columns/column_providers/providers.d.ts +75 -0
  24. package/dist/columns/column_providers/providers.d.ts.map +1 -0
  25. package/dist/columns/column_providers/providers.js +118 -0
  26. package/dist/columns/column_providers/providers.js.map +1 -0
  27. package/dist/columns/column_providers/types.d.ts +23 -0
  28. package/dist/columns/column_providers/types.d.ts.map +1 -0
  29. package/dist/columns/column_recipes/column_discovered_recipe.cjs +180 -0
  30. package/dist/columns/column_recipes/column_discovered_recipe.cjs.map +1 -0
  31. package/dist/columns/column_recipes/column_discovered_recipe.d.ts +120 -0
  32. package/dist/columns/column_recipes/column_discovered_recipe.d.ts.map +1 -0
  33. package/dist/columns/column_recipes/column_discovered_recipe.js +180 -0
  34. package/dist/columns/column_recipes/column_discovered_recipe.js.map +1 -0
  35. package/dist/columns/column_recipes/column_filtered_recipe.cjs +133 -0
  36. package/dist/columns/column_recipes/column_filtered_recipe.cjs.map +1 -0
  37. package/dist/columns/column_recipes/column_filtered_recipe.d.ts +75 -0
  38. package/dist/columns/column_recipes/column_filtered_recipe.d.ts.map +1 -0
  39. package/dist/columns/column_recipes/column_filtered_recipe.js +133 -0
  40. package/dist/columns/column_recipes/column_filtered_recipe.js.map +1 -0
  41. package/dist/columns/column_recipes/column_overrided_recipe.cjs +101 -0
  42. package/dist/columns/column_recipes/column_overrided_recipe.cjs.map +1 -0
  43. package/dist/columns/column_recipes/column_overrided_recipe.d.ts +73 -0
  44. package/dist/columns/column_recipes/column_overrided_recipe.d.ts.map +1 -0
  45. package/dist/columns/column_recipes/column_overrided_recipe.js +101 -0
  46. package/dist/columns/column_recipes/column_overrided_recipe.js.map +1 -0
  47. package/dist/columns/column_recipes/index.cjs +72 -0
  48. package/dist/columns/column_recipes/index.cjs.map +1 -0
  49. package/dist/columns/column_recipes/index.d.ts +52 -0
  50. package/dist/columns/column_recipes/index.d.ts.map +1 -0
  51. package/dist/columns/column_recipes/index.js +68 -0
  52. package/dist/columns/column_recipes/index.js.map +1 -0
  53. package/dist/columns/column_recipes/leaf_rebrand.cjs +22 -0
  54. package/dist/columns/column_recipes/leaf_rebrand.cjs.map +1 -0
  55. package/dist/columns/column_recipes/leaf_rebrand.js +22 -0
  56. package/dist/columns/column_recipes/leaf_rebrand.js.map +1 -0
  57. package/dist/columns/column_recipes/types.d.ts +101 -0
  58. package/dist/columns/column_recipes/types.d.ts.map +1 -0
  59. package/dist/columns/columns_collection.cjs +124 -0
  60. package/dist/columns/columns_collection.cjs.map +1 -0
  61. package/dist/columns/columns_collection.d.ts +64 -0
  62. package/dist/columns/columns_collection.d.ts.map +1 -0
  63. package/dist/columns/columns_collection.js +122 -0
  64. package/dist/columns/columns_collection.js.map +1 -0
  65. package/dist/columns/derive_axis_values_labels.cjs +76 -0
  66. package/dist/columns/derive_axis_values_labels.cjs.map +1 -0
  67. package/dist/columns/derive_axis_values_labels.d.ts +30 -0
  68. package/dist/columns/derive_axis_values_labels.d.ts.map +1 -0
  69. package/dist/columns/derive_axis_values_labels.js +76 -0
  70. package/dist/columns/derive_axis_values_labels.js.map +1 -0
  71. package/dist/columns/expand_by_partition.cjs +53 -56
  72. package/dist/columns/expand_by_partition.cjs.map +1 -1
  73. package/dist/columns/expand_by_partition.d.ts +22 -18
  74. package/dist/columns/expand_by_partition.d.ts.map +1 -1
  75. package/dist/columns/expand_by_partition.js +55 -58
  76. package/dist/columns/expand_by_partition.js.map +1 -1
  77. package/dist/columns/index.cjs +44 -18
  78. package/dist/columns/index.d.ts +15 -7
  79. package/dist/columns/index.js +12 -6
  80. package/dist/columns/utils.cjs +186 -0
  81. package/dist/columns/utils.cjs.map +1 -0
  82. package/dist/columns/utils.d.ts +96 -0
  83. package/dist/columns/utils.d.ts.map +1 -0
  84. package/dist/columns/utils.js +179 -0
  85. package/dist/columns/utils.js.map +1 -0
  86. package/dist/components/PFrameForGraphs.cjs +1 -0
  87. package/dist/components/PFrameForGraphs.cjs.map +1 -1
  88. package/dist/components/PFrameForGraphs.d.ts +1 -1
  89. package/dist/components/PFrameForGraphs.d.ts.map +1 -1
  90. package/dist/components/PFrameForGraphs.js +1 -0
  91. package/dist/components/PFrameForGraphs.js.map +1 -1
  92. package/dist/components/PlDataTable/columnResolver.cjs +28 -0
  93. package/dist/components/PlDataTable/columnResolver.cjs.map +1 -0
  94. package/dist/components/PlDataTable/columnResolver.js +28 -0
  95. package/dist/components/PlDataTable/columnResolver.js.map +1 -0
  96. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +4 -2
  97. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -1
  98. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js +4 -2
  99. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -1
  100. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs +20 -25
  101. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs.map +1 -1
  102. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js +20 -25
  103. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js.map +1 -1
  104. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +58 -26
  105. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
  106. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +1 -1
  107. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts.map +1 -1
  108. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +60 -28
  109. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
  110. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +224 -194
  111. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  112. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +13 -16
  113. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -1
  114. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +228 -198
  115. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  116. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +40 -98
  117. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -1
  118. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts +17 -8
  119. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts.map +1 -1
  120. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +40 -98
  121. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -1
  122. package/dist/components/PlDataTable/createPlDataTable/index.cjs +1 -1
  123. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
  124. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -2
  125. package/dist/components/PlDataTable/createPlDataTable/index.js +2 -2
  126. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
  127. package/dist/components/PlDataTable/createPlDataTable/utils.cjs +51 -169
  128. package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -1
  129. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts +1 -1
  130. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts.map +1 -1
  131. package/dist/components/PlDataTable/createPlDataTable/utils.js +52 -166
  132. package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -1
  133. package/dist/components/PlDataTable/createPlDataTableSheet.cjs.map +1 -1
  134. package/dist/components/PlDataTable/createPlDataTableSheet.d.ts +1 -1
  135. package/dist/components/PlDataTable/createPlDataTableSheet.js.map +1 -1
  136. package/dist/components/PlDataTable/index.cjs +1 -1
  137. package/dist/components/PlDataTable/index.d.ts +4 -4
  138. package/dist/components/PlDataTable/index.js +2 -2
  139. package/dist/components/PlDataTable/labels.cjs +0 -1
  140. package/dist/components/PlDataTable/labels.cjs.map +1 -1
  141. package/dist/components/PlDataTable/labels.js +0 -1
  142. package/dist/components/PlDataTable/labels.js.map +1 -1
  143. package/dist/components/PlDataTable/state-migration.cjs +107 -10
  144. package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
  145. package/dist/components/PlDataTable/state-migration.d.ts +5 -4
  146. package/dist/components/PlDataTable/state-migration.d.ts.map +1 -1
  147. package/dist/components/PlDataTable/state-migration.js +107 -10
  148. package/dist/components/PlDataTable/state-migration.js.map +1 -1
  149. package/dist/components/PlDataTable/typesV7.d.ts +1 -36
  150. package/dist/components/PlDataTable/typesV7.d.ts.map +1 -1
  151. package/dist/components/PlDataTable/typesV8.d.ts +123 -0
  152. package/dist/components/PlDataTable/typesV8.d.ts.map +1 -0
  153. package/dist/components/PlDatasetSelector/build_dataset_options.cjs +27 -34
  154. package/dist/components/PlDatasetSelector/build_dataset_options.cjs.map +1 -1
  155. package/dist/components/PlDatasetSelector/build_dataset_options.d.ts.map +1 -1
  156. package/dist/components/PlDatasetSelector/build_dataset_options.js +27 -34
  157. package/dist/components/PlDatasetSelector/build_dataset_options.js.map +1 -1
  158. package/dist/components/PlDatasetSelector/enrichment_discovery.cjs +28 -33
  159. package/dist/components/PlDatasetSelector/enrichment_discovery.cjs.map +1 -1
  160. package/dist/components/PlDatasetSelector/enrichment_discovery.js +29 -34
  161. package/dist/components/PlDatasetSelector/enrichment_discovery.js.map +1 -1
  162. package/dist/components/PlDatasetSelector/filter_discovery.cjs +27 -17
  163. package/dist/components/PlDatasetSelector/filter_discovery.cjs.map +1 -1
  164. package/dist/components/PlDatasetSelector/filter_discovery.d.ts +24 -10
  165. package/dist/components/PlDatasetSelector/filter_discovery.d.ts.map +1 -1
  166. package/dist/components/PlDatasetSelector/filter_discovery.js +28 -18
  167. package/dist/components/PlDatasetSelector/filter_discovery.js.map +1 -1
  168. package/dist/components/PlDatasetSelector/index.d.ts +2 -2
  169. package/dist/components/index.cjs +1 -1
  170. package/dist/components/index.d.ts +5 -5
  171. package/dist/components/index.js +2 -2
  172. package/dist/filters/converters/filterToQuery.cjs +5 -6
  173. package/dist/filters/converters/filterToQuery.cjs.map +1 -1
  174. package/dist/filters/converters/filterToQuery.d.ts +12 -3
  175. package/dist/filters/converters/filterToQuery.d.ts.map +1 -1
  176. package/dist/filters/converters/filterToQuery.js +5 -6
  177. package/dist/filters/converters/filterToQuery.js.map +1 -1
  178. package/dist/filters/converters/index.d.ts +2 -2
  179. package/dist/filters/index.d.ts +2 -2
  180. package/dist/index.cjs +64 -35
  181. package/dist/index.d.ts +23 -15
  182. package/dist/index.js +15 -9
  183. package/dist/labels/derive_distinct_labels.cjs.map +1 -1
  184. package/dist/labels/derive_distinct_labels.d.ts +1 -2
  185. package/dist/labels/derive_distinct_labels.d.ts.map +1 -1
  186. package/dist/labels/derive_distinct_labels.js.map +1 -1
  187. package/dist/labels/derive_distinct_tooltips.cjs +1 -1
  188. package/dist/labels/derive_distinct_tooltips.cjs.map +1 -1
  189. package/dist/labels/derive_distinct_tooltips.d.ts +6 -3
  190. package/dist/labels/derive_distinct_tooltips.d.ts.map +1 -1
  191. package/dist/labels/derive_distinct_tooltips.js +1 -1
  192. package/dist/labels/derive_distinct_tooltips.js.map +1 -1
  193. package/dist/package.cjs +1 -1
  194. package/dist/package.js +1 -1
  195. package/dist/pframe_utils/axes.cjs.map +1 -1
  196. package/dist/pframe_utils/axes.d.ts +2 -2
  197. package/dist/pframe_utils/axes.d.ts.map +1 -1
  198. package/dist/pframe_utils/axes.js.map +1 -1
  199. package/dist/pframe_utils/columns.cjs +6 -10
  200. package/dist/pframe_utils/columns.cjs.map +1 -1
  201. package/dist/pframe_utils/columns.d.ts +4 -4
  202. package/dist/pframe_utils/columns.d.ts.map +1 -1
  203. package/dist/pframe_utils/columns.js +7 -11
  204. package/dist/pframe_utils/columns.js.map +1 -1
  205. package/dist/pframe_utils/index.cjs.map +1 -1
  206. package/dist/pframe_utils/index.d.ts +1 -1
  207. package/dist/pframe_utils/index.d.ts.map +1 -1
  208. package/dist/pframe_utils/index.js.map +1 -1
  209. package/dist/render/accessor.cjs +15 -16
  210. package/dist/render/accessor.cjs.map +1 -1
  211. package/dist/render/accessor.d.ts +7 -10
  212. package/dist/render/accessor.d.ts.map +1 -1
  213. package/dist/render/accessor.js +15 -16
  214. package/dist/render/accessor.js.map +1 -1
  215. package/dist/render/api.cjs +34 -36
  216. package/dist/render/api.cjs.map +1 -1
  217. package/dist/render/api.d.ts +30 -20
  218. package/dist/render/api.d.ts.map +1 -1
  219. package/dist/render/api.js +35 -38
  220. package/dist/render/api.js.map +1 -1
  221. package/dist/render/index.cjs +4 -0
  222. package/dist/render/index.d.ts +4 -4
  223. package/dist/render/index.js +3 -2
  224. package/dist/render/internal.cjs +3 -2
  225. package/dist/render/internal.cjs.map +1 -1
  226. package/dist/render/internal.d.ts +17 -9
  227. package/dist/render/internal.d.ts.map +1 -1
  228. package/dist/render/internal.js +3 -2
  229. package/dist/render/internal.js.map +1 -1
  230. package/dist/render/util/axis_filtering.cjs.map +1 -1
  231. package/dist/render/util/axis_filtering.js.map +1 -1
  232. package/dist/render/util/column_collection.cjs +6 -4
  233. package/dist/render/util/column_collection.cjs.map +1 -1
  234. package/dist/render/util/column_collection.d.ts +9 -9
  235. package/dist/render/util/column_collection.d.ts.map +1 -1
  236. package/dist/render/util/column_collection.js +6 -4
  237. package/dist/render/util/column_collection.js.map +1 -1
  238. package/dist/render/util/index.d.ts +2 -2
  239. package/dist/render/util/pcolumn_data.cjs +1 -1
  240. package/dist/render/util/pcolumn_data.cjs.map +1 -1
  241. package/dist/render/util/pcolumn_data.d.ts +3 -3
  242. package/dist/render/util/pcolumn_data.d.ts.map +1 -1
  243. package/dist/render/util/pcolumn_data.js +1 -1
  244. package/dist/render/util/pcolumn_data.js.map +1 -1
  245. package/dist/services/block_services.cjs +2 -1
  246. package/dist/services/block_services.cjs.map +1 -1
  247. package/dist/services/block_services.d.ts +1 -0
  248. package/dist/services/block_services.d.ts.map +1 -1
  249. package/dist/services/block_services.js +2 -1
  250. package/dist/services/block_services.js.map +1 -1
  251. package/dist/services/get_services.cjs +2 -2
  252. package/dist/services/get_services.cjs.map +1 -1
  253. package/dist/services/get_services.d.ts +4 -1
  254. package/dist/services/get_services.d.ts.map +1 -1
  255. package/dist/services/get_services.js +2 -2
  256. package/dist/services/get_services.js.map +1 -1
  257. package/package.json +10 -8
  258. package/src/columns/__test_helpers__/collection_driver.ts +197 -0
  259. package/src/columns/__test_helpers__/stub_registry.ts +134 -0
  260. package/src/columns/column.ts +46 -0
  261. package/src/columns/column_lazy.test.ts +201 -0
  262. package/src/columns/column_lazy.ts +311 -0
  263. package/src/columns/column_providers/index.ts +78 -0
  264. package/src/columns/column_providers/providers.ts +193 -0
  265. package/src/columns/column_providers/types.ts +24 -0
  266. package/src/columns/column_recipes/column_discovered_recipe.ts +231 -0
  267. package/src/columns/column_recipes/column_filtered_recipe.ts +184 -0
  268. package/src/columns/column_recipes/column_overrided_recipe.ts +146 -0
  269. package/src/columns/column_recipes/column_recipes.test.ts +681 -0
  270. package/src/columns/column_recipes/index.ts +127 -0
  271. package/src/columns/column_recipes/leaf_rebrand.ts +28 -0
  272. package/src/columns/column_recipes/types.ts +113 -0
  273. package/src/columns/columns_collection.test.ts +164 -0
  274. package/src/columns/columns_collection.ts +170 -0
  275. package/src/columns/derive_axis_values_labels.ts +98 -0
  276. package/src/columns/expand_by_partition.test.ts +146 -110
  277. package/src/columns/expand_by_partition.ts +72 -84
  278. package/src/columns/index.ts +7 -5
  279. package/src/columns/utils.test.ts +249 -0
  280. package/src/columns/utils.ts +226 -0
  281. package/src/components/PFrameForGraphs.ts +3 -1
  282. package/src/components/PlAnnotations/filters_ui.test.ts +46 -47
  283. package/src/components/PlDataTable/columnResolver.test.ts +122 -0
  284. package/src/components/PlDataTable/columnResolver.ts +57 -0
  285. package/src/components/PlDataTable/createPlDataTable/createPTableDefV2.ts +9 -9
  286. package/src/components/PlDataTable/createPlDataTable/createPTableDefV3.ts +31 -63
  287. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +85 -58
  288. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +316 -354
  289. package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +48 -144
  290. package/src/components/PlDataTable/createPlDataTable/index.ts +2 -2
  291. package/src/components/PlDataTable/createPlDataTable/utils.test.ts +60 -69
  292. package/src/components/PlDataTable/createPlDataTable/utils.ts +65 -173
  293. package/src/components/PlDataTable/createPlDataTableSheet.ts +1 -1
  294. package/src/components/PlDataTable/index.ts +4 -2
  295. package/src/components/PlDataTable/labels.ts +4 -33
  296. package/src/components/PlDataTable/state-migration.ts +151 -22
  297. package/src/components/PlDataTable/typesV8.ts +188 -0
  298. package/src/components/PlDatasetSelector/build_dataset_options.ts +35 -60
  299. package/src/components/PlDatasetSelector/enrichment_discovery.ts +65 -61
  300. package/src/components/PlDatasetSelector/filter_discovery.test.ts +110 -72
  301. package/src/components/PlDatasetSelector/filter_discovery.ts +51 -31
  302. package/src/filters/converters/filterToQuery.test.ts +15 -8
  303. package/src/filters/converters/filterToQuery.ts +22 -9
  304. package/src/filters/converters/filterUiToExpressionImpl.test.ts +35 -36
  305. package/src/labels/derive_distinct_labels.ts +1 -1
  306. package/src/labels/derive_distinct_tooltips.test.ts +7 -4
  307. package/src/labels/derive_distinct_tooltips.ts +3 -3
  308. package/src/pframe_utils/axes.ts +2 -2
  309. package/src/pframe_utils/columns.ts +14 -23
  310. package/src/pframe_utils/index.ts +1 -1
  311. package/src/render/accessor.ts +35 -38
  312. package/src/render/api.ts +45 -61
  313. package/src/render/index.ts +2 -1
  314. package/src/render/internal.ts +43 -10
  315. package/src/render/util/axis_filtering.ts +0 -1
  316. package/src/render/util/column_collection.ts +17 -17
  317. package/src/render/util/pcolumn_data.ts +5 -9
  318. package/src/services/block_services.ts +1 -0
  319. package/src/services/get_services.ts +5 -2
  320. package/dist/columns/column_collection_builder.cjs +0 -241
  321. package/dist/columns/column_collection_builder.cjs.map +0 -1
  322. package/dist/columns/column_collection_builder.d.ts +0 -119
  323. package/dist/columns/column_collection_builder.d.ts.map +0 -1
  324. package/dist/columns/column_collection_builder.js +0 -241
  325. package/dist/columns/column_collection_builder.js.map +0 -1
  326. package/dist/columns/column_selector.cjs +0 -49
  327. package/dist/columns/column_selector.cjs.map +0 -1
  328. package/dist/columns/column_selector.d.ts +0 -33
  329. package/dist/columns/column_selector.d.ts.map +0 -1
  330. package/dist/columns/column_selector.js +0 -47
  331. package/dist/columns/column_selector.js.map +0 -1
  332. package/dist/columns/column_snapshot.cjs +0 -19
  333. package/dist/columns/column_snapshot.cjs.map +0 -1
  334. package/dist/columns/column_snapshot.d.ts +0 -39
  335. package/dist/columns/column_snapshot.d.ts.map +0 -1
  336. package/dist/columns/column_snapshot.js +0 -18
  337. package/dist/columns/column_snapshot.js.map +0 -1
  338. package/dist/columns/column_snapshot_provider.cjs +0 -137
  339. package/dist/columns/column_snapshot_provider.cjs.map +0 -1
  340. package/dist/columns/column_snapshot_provider.d.ts +0 -74
  341. package/dist/columns/column_snapshot_provider.d.ts.map +0 -1
  342. package/dist/columns/column_snapshot_provider.js +0 -133
  343. package/dist/columns/column_snapshot_provider.js.map +0 -1
  344. package/dist/columns/ctx_column_sources.cjs +0 -80
  345. package/dist/columns/ctx_column_sources.cjs.map +0 -1
  346. package/dist/columns/ctx_column_sources.d.ts +0 -30
  347. package/dist/columns/ctx_column_sources.d.ts.map +0 -1
  348. package/dist/columns/ctx_column_sources.js +0 -79
  349. package/dist/columns/ctx_column_sources.js.map +0 -1
  350. package/src/columns/column_collection_builder.test.ts +0 -484
  351. package/src/columns/column_collection_builder.ts +0 -485
  352. package/src/columns/column_selector.test.ts +0 -90
  353. package/src/columns/column_selector.ts +0 -100
  354. package/src/columns/column_snapshot.ts +0 -58
  355. package/src/columns/column_snapshot_provider.ts +0 -194
  356. package/src/columns/ctx_column_sources.ts +0 -99
@@ -1,41 +1,41 @@
1
- import { Annotation, createEnrichmentRef } from "@milaboratories/pl-model-common";
1
+ import {
2
+ Annotation,
3
+ createEnrichmentRef,
4
+ extractPObjectId,
5
+ isGlobalPObjectId,
6
+ } from "@milaboratories/pl-model-common";
2
7
  import type {
8
+ ColumnsCollectionDriverModel,
3
9
  EnrichmentStep,
4
10
  LabeledEnrichmentRef,
5
11
  LabeledEnrichmentRefs,
6
12
  MultiColumnSelector,
7
- PObjectId,
13
+ PColumnSpec,
8
14
  PObjectSpec,
9
15
  } from "@milaboratories/pl-model-common";
10
- import type {
11
- AnchoredColumnCollection,
12
- ColumnVariant,
13
- } from "../../columns/column_collection_builder";
16
+ import type { ColumnRecipe, ColumnsSource } from "../../columns";
17
+ import {
18
+ isLeafColumn,
19
+ ColumnsCollection,
20
+ collectLinkerIds,
21
+ hitQualifications,
22
+ collectLinkerColumns,
23
+ queriesQualifications,
24
+ } from "../../columns";
14
25
  import {
15
26
  deriveDistinctLabels,
16
27
  type DeriveLabelsOptions,
17
28
  type Entry,
18
29
  } from "../../labels/derive_distinct_labels";
19
30
 
20
- /**
21
- * True for global-form ids — `canonicalize({__isRef: true, blockId, name})` —
22
- * which the workflow can resolve via bquery. Local-form ids (`resolvePath`)
23
- * fail this check and are excluded from auto-discovery; prerun/outputs hops
24
- * must be supplied as resolved `{spec, data}` instead.
25
- */
26
- function isGloballyAddressable(id: PObjectId): boolean {
27
- try {
28
- const decoded = JSON.parse(id);
29
- return (
30
- typeof decoded === "object" &&
31
- decoded !== null &&
32
- decoded.__isRef === true &&
33
- typeof decoded.blockId === "string" &&
34
- typeof decoded.name === "string"
35
- );
36
- } catch {
37
- return false;
38
- }
31
+ export interface FindEnrichmentColumnsOptions {
32
+ sources: ReadonlyArray<ColumnsSource>;
33
+ anchorSpec: PColumnSpec;
34
+ maxHops?: number;
35
+ include?: MultiColumnSelector | MultiColumnSelector[];
36
+ predicate?: (spec: PObjectSpec) => boolean;
37
+ /** Override the resolved `columnsCollection` service (primarily for tests). */
38
+ driver?: ColumnsCollectionDriverModel;
39
39
  }
40
40
 
41
41
  /**
@@ -43,36 +43,34 @@ function isGloballyAddressable(id: PObjectId): boolean {
43
43
  * (filters / the primary itself) and structural hits (subset, linker, label
44
44
  * columns). Narrow further with `include` selectors or a `predicate`.
45
45
  */
46
- export function findEnrichmentColumns(
47
- collection: AnchoredColumnCollection,
48
- options?: {
49
- maxHops?: number;
50
- include?: MultiColumnSelector | MultiColumnSelector[];
51
- predicate?: (spec: PObjectSpec) => boolean;
52
- },
53
- ): ColumnVariant[] {
46
+ export function findEnrichmentColumns(options: FindEnrichmentColumnsOptions): ColumnRecipe[] {
54
47
  const include =
55
- options?.include === undefined
48
+ options.include === undefined
56
49
  ? undefined
57
50
  : Array.isArray(options.include)
58
51
  ? options.include
59
52
  : [options.include];
60
- const variants = collection.findColumnVariants({
61
- mode: "enrichment",
62
- maxHops: options?.maxHops ?? 4,
63
- include,
64
- exclude: [
65
- { annotations: { [Annotation.IsSubset]: "true" } },
66
- { annotations: { [Annotation.IsLinkerColumn]: "true" } },
67
- { name: Annotation.Label },
68
- ],
69
- });
70
- const predicate = options?.predicate;
71
- return variants.filter((v) => {
72
- if ((v.path?.length ?? 0) === 0) return false;
73
- if (predicate !== undefined && !predicate(v.column.spec)) return false;
74
- if (!isGloballyAddressable(v.column.id)) return false;
75
- if (v.path?.some((p) => !isGloballyAddressable(p.linker.id))) return false;
53
+
54
+ const columns = ColumnsCollection([...options.sources], { driver: options.driver })
55
+ .discover({
56
+ anchors: { main: options.anchorSpec },
57
+ mode: "enrichment",
58
+ maxHops: options.maxHops ?? 4,
59
+ include,
60
+ exclude: [
61
+ { annotations: { [Annotation.IsSubset]: "true" } },
62
+ { annotations: { [Annotation.IsLinkerColumn]: "true" } },
63
+ { name: Annotation.Label },
64
+ ],
65
+ })
66
+ .getColumns();
67
+
68
+ const predicate = options.predicate;
69
+ return columns.filter((v) => {
70
+ if (isLeafColumn(v)) return false;
71
+ if (predicate !== undefined && !predicate(v.getSpec())) return false;
72
+ if (!isGlobalPObjectId(extractPObjectId(v.id))) return false;
73
+ if (collectLinkerIds(v).some((id) => !isGlobalPObjectId(id))) return false;
76
74
  return true;
77
75
  });
78
76
  }
@@ -83,27 +81,33 @@ export function findEnrichmentColumns(
83
81
  * `qualifications.forHit`; `forQueries` is re-derived by the table builder.
84
82
  */
85
83
  export function enrichmentVariantsToRefs(
86
- variants: ColumnVariant[],
84
+ variants: ColumnRecipe[],
87
85
  labelOptions?: DeriveLabelsOptions,
88
86
  ): LabeledEnrichmentRefs {
89
87
  if (variants.length === 0) return [];
90
88
 
91
- const entries: Entry[] = variants.map((variant) => ({
92
- spec: variant.column.spec,
93
- linkerPath: variant.path?.map((p) => ({ spec: p.linker.spec })),
94
- qualifications: variant.qualifications,
89
+ const linkerIdsByVariant = variants.map((v) => collectLinkerIds(v));
90
+ const hitQualsByVariant = variants.map((v) => [...hitQualifications(v)]);
91
+
92
+ const entries: Entry[] = variants.map((variant, i) => ({
93
+ spec: variant.getSpec(),
94
+ linkerPath: collectLinkerColumns(variant).map((linker) => ({ spec: linker.getSpec() })),
95
+ qualifications: {
96
+ forHit: hitQualsByVariant[i],
97
+ forQueries: queriesQualifications(variant),
98
+ },
95
99
  }));
96
100
  const labels = deriveDistinctLabels(entries, labelOptions);
97
101
 
98
102
  return variants.map((variant, i): LabeledEnrichmentRef => {
99
- const path: undefined | EnrichmentStep[] = variant.path?.map((step) => ({
100
- type: "linker",
101
- linker: step.linker.id,
102
- }));
103
+ const path: undefined | EnrichmentStep[] =
104
+ linkerIdsByVariant[i].length === 0
105
+ ? undefined
106
+ : linkerIdsByVariant[i].map((id) => ({ type: "linker", linker: id }));
103
107
  return {
104
- ref: createEnrichmentRef(variant.column.id, {
108
+ ref: createEnrichmentRef(extractPObjectId(variant.id), {
105
109
  path,
106
- qualifications: variant.qualifications?.forHit,
110
+ qualifications: hitQualsByVariant[i],
107
111
  }),
108
112
  label: labels[i],
109
113
  };
@@ -1,25 +1,36 @@
1
- import { Annotation, createPlRef } from "@milaboratories/pl-model-common";
2
- import type { AxisSpec, PColumnSpec, PObjectId } from "@milaboratories/pl-model-common";
3
- import { SpecDriver } from "@milaboratories/pf-spec-driver";
1
+ import { Annotation, createGlobalPObjectId, createPlRef } from "@milaboratories/pl-model-common";
2
+ import type {
3
+ AxisSpec,
4
+ PColumn,
5
+ PColumnSpec,
6
+ PlRef,
7
+ PObjectId,
8
+ } from "@milaboratories/pl-model-common";
4
9
  import canonicalize from "canonicalize";
5
- import { afterEach, describe, expect, test } from "vitest";
6
- import type { ColumnSnapshot } from "../../columns/column_snapshot";
7
- import { ColumnCollectionBuilder } from "../../columns/column_collection_builder";
10
+ import { afterEach, beforeEach, describe, expect, test } from "vitest";
11
+ import type { PColumnDataUniversal } from "../../render/internal";
8
12
  import { buildRefMap, filterMatchesToOptions, findFilterColumns } from "./filter_discovery";
13
+ import {
14
+ createTestCollectionDriver,
15
+ type TestCollectionDriverHandle,
16
+ } from "../../columns/__test_helpers__/collection_driver";
9
17
 
10
- const drivers: SpecDriver[] = [];
18
+ let driverHandle: TestCollectionDriverHandle;
11
19
 
12
- function createSpecFrameCtx() {
13
- const driver = new SpecDriver();
14
- drivers.push(driver);
15
- return driver;
16
- }
20
+ beforeEach(() => {
21
+ driverHandle = createTestCollectionDriver();
22
+ driverHandle.installAmbientCtx();
23
+ });
17
24
 
18
25
  afterEach(async () => {
19
- for (const driver of drivers) await driver.dispose();
20
- drivers.length = 0;
26
+ driverHandle.uninstallAmbientCtx();
27
+ await driverHandle.dispose();
21
28
  });
22
29
 
30
+ function registerCols(cols: PColumn<PColumnDataUniversal | undefined>[]): void {
31
+ driverHandle.register(cols.map((c) => ({ id: c.id, spec: c.spec })));
32
+ }
33
+
23
34
  function axis(name: string): AxisSpec {
24
35
  return { name, type: "String" } as AxisSpec;
25
36
  }
@@ -32,52 +43,68 @@ function spec(
32
43
  return { kind: "PColumn", name, valueType: "Int", axesSpec, annotations } as PColumnSpec;
33
44
  }
34
45
 
35
- function snap(id: string, s: PColumnSpec): ColumnSnapshot<PObjectId> {
36
- return { id: id as PObjectId, spec: s, dataStatus: "ready", data: { get: () => ({}) as never } };
46
+ function col(id: PObjectId, s: PColumnSpec): PColumn<PColumnDataUniversal | undefined> {
47
+ return {
48
+ id,
49
+ spec: s,
50
+ data: {} as never,
51
+ };
52
+ }
53
+
54
+ /** Canonical global PObjectId — required so downstream `extractPObjectId` accepts it. */
55
+ function gid(name: string): PObjectId {
56
+ return createGlobalPObjectId("test-block", name);
37
57
  }
38
58
 
39
59
  // anchor defines the key space: [sample, gene]
40
60
  const anchorAxes = [axis("sample"), axis("gene")];
41
61
  const anchorSpec = spec("anchor", anchorAxes);
42
- const anchorSnap = snap("anchor-id", anchorSpec);
62
+ const anchorSnap = col(gid("anchor"), anchorSpec);
43
63
 
44
64
  describe("findFilterColumns", () => {
45
65
  test("returns columns with pl7.app/isSubset annotation", () => {
46
- const filter = snap("f1", spec("filter1", [axis("sample")], { [Annotation.IsSubset]: "true" }));
47
- const regular = snap("r1", spec("regular1", [axis("sample")]));
48
-
49
- const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
50
- builder.addSource([filter, regular, anchorSnap]);
51
- const collection = builder.build({ anchors: { main: anchorSpec } })!;
66
+ const filter = col(
67
+ gid("f1"),
68
+ spec("filter1", [axis("sample")], { [Annotation.IsSubset]: "true" }),
69
+ );
70
+ const regular = col(gid("r1"), spec("regular1", [axis("sample")]));
71
+ registerCols([filter, regular, anchorSnap]);
52
72
 
53
- const results = findFilterColumns(collection);
54
- expect(results.every((m) => m.column.spec.name !== "regular1")).toBe(true);
55
- expect(results.some((m) => m.column.spec.name === "filter1")).toBe(true);
73
+ const results = findFilterColumns({
74
+ sources: [{ columns: [filter, regular, anchorSnap], isFinal: true }],
75
+ anchorSpec,
76
+ driver: driverHandle.driver,
77
+ });
78
+ expect(results.every((m) => m.getSpec().name !== "regular1")).toBe(true);
79
+ expect(results.some((m) => m.getSpec().name === "filter1")).toBe(true);
56
80
  });
57
81
 
58
82
  test("axes subset: excludes filter whose axes are not a subset of anchor axes", () => {
59
83
  // filter with axis "other" — not a subset of anchor axes [sample, gene]
60
- const badFilter = snap(
61
- "f2",
84
+ const badFilter = col(
85
+ gid("f2"),
62
86
  spec("bad-filter", [axis("other")], { [Annotation.IsSubset]: "true" }),
63
87
  );
88
+ registerCols([badFilter, anchorSnap]);
64
89
 
65
- const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
66
- builder.addSource([badFilter, anchorSnap]);
67
- const collection = builder.build({ anchors: { main: anchorSpec } })!;
68
-
69
- const results = findFilterColumns(collection);
70
- expect(results.every((m) => m.column.spec.name !== "bad-filter")).toBe(true);
90
+ const results = findFilterColumns({
91
+ sources: [{ columns: [badFilter, anchorSnap], isFinal: true }],
92
+ anchorSpec,
93
+ driver: driverHandle.driver,
94
+ });
95
+ expect(results.every((m) => m.getSpec().name !== "bad-filter")).toBe(true);
71
96
  });
72
97
 
73
98
  test("empty result when no filters exist", () => {
74
- const regular = snap("r1", spec("regular1", [axis("sample")]));
75
-
76
- const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
77
- builder.addSource([regular, anchorSnap]);
78
- const collection = builder.build({ anchors: { main: anchorSpec } })!;
99
+ const regular = col(gid("r1"), spec("regular1", [axis("sample")]));
100
+ registerCols([regular, anchorSnap]);
79
101
 
80
- expect(findFilterColumns(collection)).toHaveLength(0);
102
+ const results = findFilterColumns({
103
+ sources: [{ columns: [regular, anchorSnap], isFinal: true }],
104
+ anchorSpec,
105
+ driver: driverHandle.driver,
106
+ });
107
+ expect(results).toHaveLength(0);
81
108
  });
82
109
  });
83
110
 
@@ -101,18 +128,25 @@ describe("filterMatchesToOptions", () => {
101
128
  const filterRef1 = createPlRef("b1", "filter-top1000");
102
129
  const filterRef2 = createPlRef("b1", "filter-highconf");
103
130
 
104
- const refMap = buildRefMap([{ ref: filterRef1 }, { ref: filterRef2 }]);
131
+ // Build ref map from entries (simulating result pool)
132
+ const refMap = buildRefMap([
133
+ { ref: anchorSnap.id as unknown as PlRef },
134
+ { ref: filterRef1 },
135
+ { ref: filterRef2 },
136
+ ]);
137
+
105
138
  const filterSpec1 = spec("filter1", [axis("sample")], { [Annotation.IsSubset]: "true" });
106
139
  const filterSpec2 = spec("filter2", [axis("sample")], { [Annotation.IsSubset]: "true" });
107
140
 
108
- const f1Snap = snap(canonicalize(filterRef1)! as string, filterSpec1);
109
- const f2Snap = snap(canonicalize(filterRef2)! as string, filterSpec2);
110
-
111
- const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
112
- builder.addSource([f1Snap, f2Snap, anchorSnap]);
113
- const collection = builder.build({ anchors: { main: anchorSpec } })!;
141
+ const f1Snap = col(canonicalize(filterRef1)! as PObjectId, filterSpec1);
142
+ const f2Snap = col(canonicalize(filterRef2)! as PObjectId, filterSpec2);
143
+ registerCols([f1Snap, f2Snap, anchorSnap]);
114
144
 
115
- const matches = findFilterColumns(collection);
145
+ const matches = findFilterColumns({
146
+ sources: [{ columns: [f1Snap, f2Snap, anchorSnap], isFinal: true }],
147
+ anchorSpec,
148
+ driver: driverHandle.driver,
149
+ });
116
150
  expect(matches.length).toBe(2);
117
151
 
118
152
  const options = filterMatchesToOptions(matches, {
@@ -120,7 +154,6 @@ describe("filterMatchesToOptions", () => {
120
154
  datasetSpec: anchorSpec,
121
155
  });
122
156
  expect(options).toHaveLength(2);
123
- // Each option has a ref and label
124
157
  for (const opt of options) {
125
158
  expect(opt.ref).toBeDefined();
126
159
  expect(opt.label).toBeDefined();
@@ -153,13 +186,15 @@ describe("filterMatchesToOptions", () => {
153
186
  { type: "milaboratories.antibody-tcr-lead-selection", label: "Top 10", importance: 30 },
154
187
  ]),
155
188
  });
156
- const fSnap = snap(canonicalize(filterRef)! as string, filterSpec);
157
-
158
- const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
159
- builder.addSource([fSnap, anchorSnap]);
160
- const collection = builder.build({ anchors: { main: anchorSpec } })!;
161
-
162
- const matches = findFilterColumns(collection);
189
+ const fSnap = col(canonicalize(filterRef)! as PObjectId, filterSpec);
190
+ const dsSnap = col(gid("dataset"), datasetSpec);
191
+ registerCols([fSnap, dsSnap]);
192
+
193
+ const matches = findFilterColumns({
194
+ sources: [{ columns: [fSnap, dsSnap], isFinal: true }],
195
+ anchorSpec: datasetSpec,
196
+ driver: driverHandle.driver,
197
+ });
163
198
  expect(matches).toHaveLength(1);
164
199
 
165
200
  const options = filterMatchesToOptions(matches, { refsByObjectId: refMap, datasetSpec });
@@ -215,14 +250,16 @@ describe("filterMatchesToOptions", () => {
215
250
  { type: "milaboratories.antibody-tcr-lead-selection", label: "Top 11", importance: 30 },
216
251
  ]),
217
252
  });
218
- const f1Snap = snap(canonicalize(ref1)! as string, filterSpec1);
219
- const f2Snap = snap(canonicalize(ref2)! as string, filterSpec2);
220
-
221
- const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
222
- builder.addSource([f1Snap, f2Snap, anchorSnap]);
223
- const collection = builder.build({ anchors: { main: anchorSpec } })!;
224
-
225
- const matches = findFilterColumns(collection);
253
+ const f1Snap = col(canonicalize(ref1)! as PObjectId, filterSpec1);
254
+ const f2Snap = col(canonicalize(ref2)! as PObjectId, filterSpec2);
255
+ const dsSnap = col(gid("dataset"), datasetSpec);
256
+ registerCols([f1Snap, f2Snap, dsSnap]);
257
+
258
+ const matches = findFilterColumns({
259
+ sources: [{ columns: [f1Snap, f2Snap, dsSnap], isFinal: true }],
260
+ anchorSpec: datasetSpec,
261
+ driver: driverHandle.driver,
262
+ });
226
263
  expect(matches).toHaveLength(2);
227
264
 
228
265
  const options = filterMatchesToOptions(matches, { refsByObjectId: refMap, datasetSpec });
@@ -239,14 +276,15 @@ describe("filterMatchesToOptions", () => {
239
276
  const knownRef = createPlRef("b1", "known");
240
277
  const knownSpec = spec("known", [axis("sample")], { [Annotation.IsSubset]: "true" });
241
278
  const orphanSpec = spec("orphan", [axis("sample")], { [Annotation.IsSubset]: "true" });
242
- const knownSnap = snap(canonicalize(knownRef)! as string, knownSpec);
243
- const orphanSnap = snap("orphan-id", orphanSpec);
244
-
245
- const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
246
- builder.addSource([knownSnap, orphanSnap, anchorSnap]);
247
- const collection = builder.build({ anchors: { main: anchorSpec } })!;
248
-
249
- const matches = findFilterColumns(collection);
279
+ const knownSnap = col(canonicalize(knownRef)! as PObjectId, knownSpec);
280
+ const orphanSnap = col(gid("orphan"), orphanSpec);
281
+ registerCols([knownSnap, orphanSnap, anchorSnap]);
282
+
283
+ const matches = findFilterColumns({
284
+ sources: [{ columns: [knownSnap, orphanSnap, anchorSnap], isFinal: true }],
285
+ anchorSpec,
286
+ driver: driverHandle.driver,
287
+ });
250
288
  expect(matches.length).toBe(2);
251
289
  const refMap = buildRefMap([{ ref: knownRef }]);
252
290
  const options = filterMatchesToOptions(matches, {
@@ -1,27 +1,45 @@
1
- import { Annotation } from "@milaboratories/pl-model-common";
2
- import type { Option, PlRef, PObjectId, PObjectSpec } from "@milaboratories/pl-model-common";
3
- import canonicalize from "canonicalize";
1
+ import { Annotation, extractPObjectId } from "@milaboratories/pl-model-common";
4
2
  import type {
5
- AnchoredColumnCollection,
6
- ColumnMatch,
7
- } from "../../columns/column_collection_builder";
3
+ ColumnsCollectionDriverModel,
4
+ Option,
5
+ PColumnSpec,
6
+ PlRef,
7
+ PObjectId,
8
+ PObjectSpec,
9
+ } from "@milaboratories/pl-model-common";
10
+ import canonicalize from "canonicalize";
11
+ import type { ColumnRecipe, ColumnsSource } from "../../columns";
12
+ import { ColumnsCollection, collectLinkerColumns } from "../../columns";
8
13
  import {
9
14
  deriveDistinctLabels,
10
15
  type DeriveLabelsOptions,
11
16
  type Entry,
12
17
  } from "../../labels/derive_distinct_labels";
13
18
 
19
+ export interface FindFilterColumnsOptions {
20
+ sources: ReadonlyArray<ColumnsSource>;
21
+ anchorSpec: PColumnSpec;
22
+ /** Override the resolved `columnsCollection` service (primarily for tests). */
23
+ driver?: ColumnsCollectionDriverModel;
24
+ }
25
+
14
26
  /**
15
- * Columns annotated `pl7.app/isSubset: "true"` whose axes ⊆ anchor axes.
16
- * The axes-subset constraint comes from `mode: "enrichment"`.
27
+ * Matches columns annotated `pl7.app/isSubset: "true"` whose axes ⊆ anchor axes.
28
+ *
29
+ * Filter-intent: only the dataset's own direct subset columns, no linker
30
+ * traversal — so this uses `.filter()` (pins `maxHops: 0`), not `.discover()`
31
+ * (which would default to 4 hops and surface subset columns from other,
32
+ * linker-reachable datasets). `.filter()` still applies the default
33
+ * `enrichment` matching mode (`allowFloatingHitAxes: false`), which enforces
34
+ * the axes-subset constraint. See `matchingModeToConstraints()`.
17
35
  */
18
- export function findFilterColumns(collection: AnchoredColumnCollection): ColumnMatch[] {
19
- return collection.findColumns({
20
- mode: "enrichment",
21
- include: {
22
- annotations: { [Annotation.IsSubset]: "true" },
23
- },
24
- });
36
+ export function findFilterColumns(options: FindFilterColumnsOptions): ColumnRecipe[] {
37
+ return ColumnsCollection([...options.sources], { driver: options.driver })
38
+ .filter({
39
+ anchors: { main: options.anchorSpec },
40
+ include: { annotations: { [Annotation.IsSubset]: "true" } },
41
+ })
42
+ .getColumns();
25
43
  }
26
44
 
27
45
  export type FilterMatchOptions = {
@@ -39,30 +57,32 @@ export type FilterMatchOptions = {
39
57
  };
40
58
 
41
59
  /**
42
- * Derive labels for filter column matches (for `DatasetOption.filters`).
43
- * Matches whose column id is missing from `refsByObjectId` are silently
44
- * dropped — they cannot be exposed as selectable options.
60
+ * Derive labeled options from filter column variants, for use in DatasetOption.filters.
61
+ *
62
+ * Entries whose column id has no PlRef in `refsByObjectId` are silently
63
+ * skipped — they cannot be exposed as user-selectable options.
45
64
  */
46
65
  export function filterMatchesToOptions(
47
- matches: ColumnMatch[],
66
+ variants: ColumnRecipe[],
48
67
  options: FilterMatchOptions,
49
68
  ): Option[] {
50
- if (matches.length === 0) return [];
69
+ if (variants.length === 0) return [];
51
70
 
52
71
  const { refsByObjectId, datasetSpec, labelOptions } = options;
53
72
 
54
- // One entry per match-variant (different paths to the same column are
55
- // exposed as separate Options). The `ref` field rides along on the
56
- // Entry-shaped objects via structural typing; `deriveDistinctLabels`
57
- // ignores extra fields.
58
- const entries = matches.flatMap((match): (Entry & { ref: PlRef })[] => {
59
- const ref = refsByObjectId.get(match.column.id);
73
+ // One Option per variant — `deriveDistinctLabels` disambiguates labels by
74
+ // path. All variants of the same column share a terminal PObjectId, so the
75
+ // ref lookup happens once per variant.
76
+ const entries: (Entry & { ref: PlRef })[] = variants.flatMap((variant) => {
77
+ const ref = refsByObjectId.get(extractPObjectId(variant.id));
60
78
  if (ref === undefined) return [];
61
- return match.variants.map((variant) => ({
62
- ref,
63
- spec: match.column.spec,
64
- linkerPath: variant.path.map((p) => ({ spec: p.linker.spec })),
65
- }));
79
+ return [
80
+ {
81
+ ref,
82
+ spec: variant.getSpec(),
83
+ linkerPath: collectLinkerColumns(variant).map((linker) => ({ spec: linker.getSpec() })),
84
+ },
85
+ ];
66
86
  });
67
87
 
68
88
  // Appending the dataset forces a discriminating trace step into every
@@ -1,17 +1,24 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import type { FilterSpec, FilterSpecLeaf } from "@milaboratories/pl-model-common";
2
+ import type {
3
+ AxisId,
4
+ FilterSpec,
5
+ FilterSpecLeaf,
6
+ PObjectId,
7
+ PTableColumnId,
8
+ } from "@milaboratories/pl-model-common";
3
9
  import { filterSpecToSpecQueryExpr } from "./filterToQuery";
4
10
 
5
- type QFilterSpec = FilterSpec<FilterSpecLeaf<string>>;
11
+ type QFilterSpec = FilterSpec<FilterSpecLeaf<PTableColumnId>>;
6
12
 
7
- /** Helper: creates a CanonicalizedJson<PTableColumnId> for a regular column. */
8
- function colRef(id: string): string {
9
- return JSON.stringify({ type: "column", id });
13
+ /** Helper: creates a PTableColumnId for a regular column. */
14
+ function colRef(id: string): PTableColumnId {
15
+ return { type: "column", id: id as PObjectId };
10
16
  }
11
17
 
12
- /** Helper: creates a CanonicalizedJson<PTableColumnId> for an axis. */
13
- function axisRef(id: string): string {
14
- return JSON.stringify({ type: "axis", id });
18
+ /** Helper: creates a PTableColumnId for an axis. AxisId stays as a string-shaped
19
+ * value here because the converter passes `id` through to SingleAxisSelector. */
20
+ function axisRef(id: string): PTableColumnId {
21
+ return { type: "axis", id: id as unknown as AxisId };
15
22
  }
16
23
 
17
24
  describe("filterSpecToSpecQueryExpr", () => {
@@ -1,23 +1,36 @@
1
1
  import { assertNever } from "@milaboratories/pl-model-common";
2
2
  import type {
3
+ AxisId,
4
+ ColumnUniversalId,
3
5
  FilterSpec,
4
6
  FilterSpecLeaf,
5
- PTableColumnId,
6
7
  SingleAxisSelector,
7
8
  SpecQueryExpression,
8
9
  } from "@milaboratories/pl-model-common";
9
10
  import { traverseFilterSpec } from "../traverse";
10
11
 
11
- /** Parses a CanonicalizedJson<PTableColumnId> string into a SpecQueryExpression reference. */
12
- function resolveColumnRef(columnStr: string): SpecQueryExpression {
13
- const parsed = JSON.parse(columnStr) as PTableColumnId;
14
- return parsed.type === "axis"
15
- ? { type: "axisRef", value: parsed.id as SingleAxisSelector }
16
- : { type: "columnRef", value: parsed.id };
12
+ export type QueryColumnIdAxis = {
13
+ type: "axis";
14
+ id: AxisId;
15
+ };
16
+
17
+ export type QueryColumnIdColumn = {
18
+ type: "column";
19
+ /** May be a rich {@link ColumnUniversalId} (Discovered / Overridden / Filtered) or bare PObjectId. */
20
+ id: ColumnUniversalId;
21
+ };
22
+
23
+ export type QueryColumnId = QueryColumnIdAxis | QueryColumnIdColumn;
24
+
25
+ /** Converts a QueryColumnId object into a SpecQueryExpression reference. */
26
+ function resolveColumnRef(col: QueryColumnId): SpecQueryExpression {
27
+ return col.type === "axis"
28
+ ? { type: "axisRef", value: col.id as SingleAxisSelector }
29
+ : { type: "columnRef", value: col.id };
17
30
  }
18
31
 
19
32
  /** Converts a FilterSpec tree into a SpecQueryExpression. */
20
- export function filterSpecToSpecQueryExpr<Leaf extends FilterSpecLeaf<string>>(
33
+ export function filterSpecToSpecQueryExpr<Leaf extends FilterSpecLeaf<QueryColumnId>>(
21
34
  filter: FilterSpec<Leaf>,
22
35
  ): SpecQueryExpression {
23
36
  return traverseFilterSpec(filter, {
@@ -38,7 +51,7 @@ export function filterSpecToSpecQueryExpr<Leaf extends FilterSpecLeaf<string>>(
38
51
  });
39
52
  }
40
53
 
41
- function leafToSpecQueryExpr<Leaf extends FilterSpecLeaf<string>>(
54
+ function leafToSpecQueryExpr<Leaf extends FilterSpecLeaf<QueryColumnId>>(
42
55
  filter: Leaf,
43
56
  ): SpecQueryExpression {
44
57
  switch (filter.type) {