@platforma-sdk/model 1.79.17 → 1.79.24

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 (326) hide show
  1. package/dist/annotations/converter.cjs +0 -1
  2. package/dist/annotations/converter.cjs.map +1 -1
  3. package/dist/annotations/converter.d.ts.map +1 -1
  4. package/dist/annotations/converter.js.map +1 -1
  5. package/dist/annotations/index.cjs +2 -1
  6. package/dist/annotations/index.d.ts +2 -1
  7. package/dist/annotations/index.js +2 -1
  8. package/dist/bconfig/index.cjs +5 -2
  9. package/dist/bconfig/index.d.ts +2 -1
  10. package/dist/bconfig/index.js +3 -2
  11. package/dist/bconfig/lambdas.d.ts.map +1 -1
  12. package/dist/bconfig/normalization.cjs +0 -1
  13. package/dist/bconfig/normalization.cjs.map +1 -1
  14. package/dist/bconfig/normalization.d.ts.map +1 -1
  15. package/dist/bconfig/normalization.js.map +1 -1
  16. package/dist/bconfig/types.cjs.map +1 -1
  17. package/dist/bconfig/types.d.ts.map +1 -1
  18. package/dist/bconfig/types.js.map +1 -1
  19. package/dist/bconfig/util.d.ts.map +1 -1
  20. package/dist/bconfig/v3.d.ts.map +1 -1
  21. package/dist/block_api_v1.d.ts.map +1 -1
  22. package/dist/block_migrations.cjs +3 -0
  23. package/dist/block_migrations.cjs.map +1 -1
  24. package/dist/block_migrations.d.ts +1 -1
  25. package/dist/block_migrations.d.ts.map +1 -1
  26. package/dist/block_migrations.js +1 -1
  27. package/dist/block_migrations.js.map +1 -1
  28. package/dist/block_model.cjs +1 -1
  29. package/dist/block_model.cjs.map +1 -1
  30. package/dist/block_model.d.ts.map +1 -1
  31. package/dist/block_model.js +1 -0
  32. package/dist/block_model.js.map +1 -1
  33. package/dist/block_model_legacy.cjs +1 -1
  34. package/dist/block_model_legacy.cjs.map +1 -1
  35. package/dist/block_model_legacy.d.ts.map +1 -1
  36. package/dist/block_model_legacy.js +1 -0
  37. package/dist/block_model_legacy.js.map +1 -1
  38. package/dist/block_state_patch.d.ts.map +1 -1
  39. package/dist/block_state_util.cjs +2 -0
  40. package/dist/block_state_util.cjs.map +1 -1
  41. package/dist/block_state_util.d.ts.map +1 -1
  42. package/dist/block_state_util.js +2 -0
  43. package/dist/block_state_util.js.map +1 -1
  44. package/dist/block_storage.cjs.map +1 -1
  45. package/dist/block_storage.d.ts +1 -1
  46. package/dist/block_storage.d.ts.map +1 -1
  47. package/dist/block_storage.js.map +1 -1
  48. package/dist/block_storage_callbacks.cjs +1 -1
  49. package/dist/block_storage_callbacks.cjs.map +1 -1
  50. package/dist/block_storage_callbacks.js +1 -1
  51. package/dist/block_storage_callbacks.js.map +1 -1
  52. package/dist/block_storage_facade.cjs.map +1 -1
  53. package/dist/block_storage_facade.d.ts.map +1 -1
  54. package/dist/block_storage_facade.js.map +1 -1
  55. package/dist/columns/column_collection_builder.cjs +3 -1
  56. package/dist/columns/column_collection_builder.cjs.map +1 -1
  57. package/dist/columns/column_collection_builder.d.ts.map +1 -1
  58. package/dist/columns/column_collection_builder.js +3 -0
  59. package/dist/columns/column_collection_builder.js.map +1 -1
  60. package/dist/columns/column_selector.cjs.map +1 -1
  61. package/dist/columns/column_selector.d.ts.map +1 -1
  62. package/dist/columns/column_selector.js.map +1 -1
  63. package/dist/columns/column_snapshot.cjs.map +1 -1
  64. package/dist/columns/column_snapshot.d.ts.map +1 -1
  65. package/dist/columns/column_snapshot.js.map +1 -1
  66. package/dist/columns/column_snapshot_provider.cjs +3 -1
  67. package/dist/columns/column_snapshot_provider.cjs.map +1 -1
  68. package/dist/columns/column_snapshot_provider.d.ts.map +1 -1
  69. package/dist/columns/column_snapshot_provider.js +3 -0
  70. package/dist/columns/column_snapshot_provider.js.map +1 -1
  71. package/dist/columns/ctx_column_sources.cjs +1 -1
  72. package/dist/columns/ctx_column_sources.cjs.map +1 -1
  73. package/dist/columns/ctx_column_sources.d.ts.map +1 -1
  74. package/dist/columns/ctx_column_sources.js +1 -0
  75. package/dist/columns/ctx_column_sources.js.map +1 -1
  76. package/dist/columns/expand_by_partition.cjs +0 -1
  77. package/dist/columns/expand_by_partition.cjs.map +1 -1
  78. package/dist/columns/expand_by_partition.d.ts.map +1 -1
  79. package/dist/columns/expand_by_partition.js.map +1 -1
  80. package/dist/columns/index.cjs +20 -6
  81. package/dist/columns/index.d.ts +2 -1
  82. package/dist/columns/index.js +7 -6
  83. package/dist/components/PFrameForGraphs.cjs +3 -2
  84. package/dist/components/PFrameForGraphs.cjs.map +1 -1
  85. package/dist/components/PFrameForGraphs.d.ts +1 -1
  86. package/dist/components/PFrameForGraphs.d.ts.map +1 -1
  87. package/dist/components/PFrameForGraphs.js +2 -2
  88. package/dist/components/PFrameForGraphs.js.map +1 -1
  89. package/dist/components/PlAnnotations/filter.d.ts.map +1 -1
  90. package/dist/components/PlAnnotations/filters_ui.cjs.map +1 -1
  91. package/dist/components/PlAnnotations/filters_ui.d.ts.map +1 -1
  92. package/dist/components/PlAnnotations/filters_ui.js.map +1 -1
  93. package/dist/components/PlAnnotations/index.d.ts +2 -1
  94. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +0 -1
  95. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -1
  96. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -1
  97. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs +0 -1
  98. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs.map +1 -1
  99. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js.map +1 -1
  100. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +0 -1
  101. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
  102. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts.map +1 -1
  103. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
  104. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +1 -2
  105. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  106. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -1
  107. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +1 -1
  108. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  109. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +0 -1
  110. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -1
  111. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -1
  112. package/dist/components/PlDataTable/createPlDataTable/index.cjs +2 -1
  113. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
  114. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +1 -1
  115. package/dist/components/PlDataTable/createPlDataTable/index.d.ts.map +1 -1
  116. package/dist/components/PlDataTable/createPlDataTable/index.js +2 -2
  117. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
  118. package/dist/components/PlDataTable/createPlDataTable/utils.cjs +0 -1
  119. package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -1
  120. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts +1 -1
  121. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts.map +1 -1
  122. package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -1
  123. package/dist/components/PlDataTable/createPlDataTableSheet.cjs.map +1 -1
  124. package/dist/components/PlDataTable/createPlDataTableSheet.d.ts.map +1 -1
  125. package/dist/components/PlDataTable/createPlDataTableSheet.js.map +1 -1
  126. package/dist/components/PlDataTable/index.cjs +19 -7
  127. package/dist/components/PlDataTable/index.d.ts +2 -1
  128. package/dist/components/PlDataTable/index.js +8 -7
  129. package/dist/components/PlDataTable/labels.cjs +0 -1
  130. package/dist/components/PlDataTable/labels.cjs.map +1 -1
  131. package/dist/components/PlDataTable/labels.js.map +1 -1
  132. package/dist/components/PlDataTable/state-migration.cjs +0 -1
  133. package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
  134. package/dist/components/PlDataTable/state-migration.d.ts.map +1 -1
  135. package/dist/components/PlDataTable/state-migration.js.map +1 -1
  136. package/dist/components/PlDataTable/typesV4.d.ts +1 -1
  137. package/dist/components/PlDataTable/typesV4.d.ts.map +1 -1
  138. package/dist/components/PlDataTable/typesV5.d.ts +1 -1
  139. package/dist/components/PlDataTable/typesV5.d.ts.map +1 -1
  140. package/dist/components/PlDataTable/typesV6.d.ts +1 -1
  141. package/dist/components/PlDataTable/typesV6.d.ts.map +1 -1
  142. package/dist/components/PlDataTable/typesV7.d.ts.map +1 -1
  143. package/dist/components/PlDatasetSelector/build_dataset_options.cjs +0 -1
  144. package/dist/components/PlDatasetSelector/build_dataset_options.cjs.map +1 -1
  145. package/dist/components/PlDatasetSelector/build_dataset_options.js.map +1 -1
  146. package/dist/components/PlDatasetSelector/dataset_selection.cjs.map +1 -1
  147. package/dist/components/PlDatasetSelector/dataset_selection.d.ts.map +1 -1
  148. package/dist/components/PlDatasetSelector/dataset_selection.js.map +1 -1
  149. package/dist/components/PlDatasetSelector/enrichment_discovery.cjs +0 -1
  150. package/dist/components/PlDatasetSelector/enrichment_discovery.cjs.map +1 -1
  151. package/dist/components/PlDatasetSelector/enrichment_discovery.js.map +1 -1
  152. package/dist/components/PlDatasetSelector/filter_discovery.cjs +1 -1
  153. package/dist/components/PlDatasetSelector/filter_discovery.cjs.map +1 -1
  154. package/dist/components/PlDatasetSelector/filter_discovery.d.ts.map +1 -1
  155. package/dist/components/PlDatasetSelector/filter_discovery.js.map +1 -1
  156. package/dist/components/PlDatasetSelector/index.cjs +9 -3
  157. package/dist/components/PlDatasetSelector/index.d.ts +2 -1
  158. package/dist/components/PlDatasetSelector/index.js +4 -3
  159. package/dist/components/PlMultiSequenceAlignment.cjs +0 -1
  160. package/dist/components/PlMultiSequenceAlignment.cjs.map +1 -1
  161. package/dist/components/PlMultiSequenceAlignment.d.ts.map +1 -1
  162. package/dist/components/PlMultiSequenceAlignment.js.map +1 -1
  163. package/dist/components/PlSelectionModel.cjs.map +1 -1
  164. package/dist/components/PlSelectionModel.d.ts.map +1 -1
  165. package/dist/components/PlSelectionModel.js.map +1 -1
  166. package/dist/components/index.cjs +44 -15
  167. package/dist/components/index.d.ts +2 -1
  168. package/dist/components/index.js +16 -15
  169. package/dist/config/actions.cjs.map +1 -1
  170. package/dist/config/actions.d.ts.map +1 -1
  171. package/dist/config/actions.js.map +1 -1
  172. package/dist/config/actions_kinds.d.ts.map +1 -1
  173. package/dist/config/index.cjs +33 -1
  174. package/dist/config/index.d.ts +2 -1
  175. package/dist/config/index.js +2 -1
  176. package/dist/config/model.d.ts.map +1 -1
  177. package/dist/config/type_engine.d.ts.map +1 -1
  178. package/dist/config/type_util.d.ts +1 -1
  179. package/dist/config/type_util.d.ts.map +1 -1
  180. package/dist/env_value.cjs.map +1 -1
  181. package/dist/env_value.d.ts.map +1 -1
  182. package/dist/env_value.js.map +1 -1
  183. package/dist/filters/converters/filterToQuery.cjs +0 -1
  184. package/dist/filters/converters/filterToQuery.cjs.map +1 -1
  185. package/dist/filters/converters/filterToQuery.d.ts.map +1 -1
  186. package/dist/filters/converters/filterToQuery.js.map +1 -1
  187. package/dist/filters/converters/filterUiToExpressionImpl.cjs +0 -1
  188. package/dist/filters/converters/filterUiToExpressionImpl.cjs.map +1 -1
  189. package/dist/filters/converters/filterUiToExpressionImpl.d.ts.map +1 -1
  190. package/dist/filters/converters/filterUiToExpressionImpl.js.map +1 -1
  191. package/dist/filters/converters/index.cjs +5 -2
  192. package/dist/filters/converters/index.d.ts +2 -1
  193. package/dist/filters/converters/index.js +3 -2
  194. package/dist/filters/distill.cjs +1 -2
  195. package/dist/filters/distill.cjs.map +1 -1
  196. package/dist/filters/distill.d.ts.map +1 -1
  197. package/dist/filters/distill.js +1 -1
  198. package/dist/filters/distill.js.map +1 -1
  199. package/dist/filters/index.cjs +7 -3
  200. package/dist/filters/index.d.ts +2 -1
  201. package/dist/filters/index.js +4 -3
  202. package/dist/filters/traverse.cjs.map +1 -1
  203. package/dist/filters/traverse.js.map +1 -1
  204. package/dist/filters/types.d.ts.map +1 -1
  205. package/dist/index.d.ts +1 -1
  206. package/dist/internal.cjs +2 -0
  207. package/dist/internal.cjs.map +1 -1
  208. package/dist/internal.js +1 -1
  209. package/dist/internal.js.map +1 -1
  210. package/dist/labels/derive_distinct_labels.cjs +2 -3
  211. package/dist/labels/derive_distinct_labels.cjs.map +1 -1
  212. package/dist/labels/derive_distinct_labels.d.ts.map +1 -1
  213. package/dist/labels/derive_distinct_labels.js +2 -2
  214. package/dist/labels/derive_distinct_labels.js.map +1 -1
  215. package/dist/labels/derive_distinct_tooltips.cjs +0 -1
  216. package/dist/labels/derive_distinct_tooltips.cjs.map +1 -1
  217. package/dist/labels/derive_distinct_tooltips.d.ts.map +1 -1
  218. package/dist/labels/derive_distinct_tooltips.js.map +1 -1
  219. package/dist/labels/index.cjs +4 -2
  220. package/dist/labels/index.d.ts +2 -1
  221. package/dist/labels/index.js +3 -2
  222. package/dist/package.cjs +1 -1
  223. package/dist/package.js +1 -1
  224. package/dist/pframe.cjs +1 -0
  225. package/dist/pframe.cjs.map +1 -1
  226. package/dist/pframe.d.ts.map +1 -1
  227. package/dist/pframe.js +1 -0
  228. package/dist/pframe.js.map +1 -1
  229. package/dist/pframe_utils/axes.cjs +0 -1
  230. package/dist/pframe_utils/axes.cjs.map +1 -1
  231. package/dist/pframe_utils/axes.d.ts.map +1 -1
  232. package/dist/pframe_utils/axes.js.map +1 -1
  233. package/dist/pframe_utils/columns.cjs +0 -1
  234. package/dist/pframe_utils/columns.cjs.map +1 -1
  235. package/dist/pframe_utils/columns.d.ts.map +1 -1
  236. package/dist/pframe_utils/columns.js.map +1 -1
  237. package/dist/pframe_utils/index.cjs +3 -2
  238. package/dist/pframe_utils/index.cjs.map +1 -1
  239. package/dist/pframe_utils/index.d.ts +1 -1
  240. package/dist/pframe_utils/index.d.ts.map +1 -1
  241. package/dist/pframe_utils/index.js +2 -2
  242. package/dist/pframe_utils/index.js.map +1 -1
  243. package/dist/platforma.d.ts.map +1 -1
  244. package/dist/plugin_handle.cjs.map +1 -1
  245. package/dist/plugin_handle.d.ts.map +1 -1
  246. package/dist/plugin_handle.js.map +1 -1
  247. package/dist/plugin_model.cjs +5 -0
  248. package/dist/plugin_model.cjs.map +1 -1
  249. package/dist/plugin_model.d.ts +1 -1
  250. package/dist/plugin_model.d.ts.map +1 -1
  251. package/dist/plugin_model.js +3 -1
  252. package/dist/plugin_model.js.map +1 -1
  253. package/dist/raw_globals.cjs.map +1 -1
  254. package/dist/raw_globals.d.ts.map +1 -1
  255. package/dist/raw_globals.js.map +1 -1
  256. package/dist/ref_util.cjs.map +1 -1
  257. package/dist/ref_util.d.ts.map +1 -1
  258. package/dist/ref_util.js.map +1 -1
  259. package/dist/render/accessor.cjs +2 -1
  260. package/dist/render/accessor.cjs.map +1 -1
  261. package/dist/render/accessor.d.ts.map +1 -1
  262. package/dist/render/accessor.js +2 -0
  263. package/dist/render/accessor.js.map +1 -1
  264. package/dist/render/api.cjs +5 -2
  265. package/dist/render/api.cjs.map +1 -1
  266. package/dist/render/api.d.ts.map +1 -1
  267. package/dist/render/api.js +4 -1
  268. package/dist/render/api.js.map +1 -1
  269. package/dist/render/future.cjs +2 -0
  270. package/dist/render/future.cjs.map +1 -1
  271. package/dist/render/future.d.ts.map +1 -1
  272. package/dist/render/future.js +2 -0
  273. package/dist/render/future.js.map +1 -1
  274. package/dist/render/index.cjs +34 -7
  275. package/dist/render/index.d.ts +2 -1
  276. package/dist/render/index.js +8 -7
  277. package/dist/render/internal.cjs +3 -0
  278. package/dist/render/internal.cjs.map +1 -1
  279. package/dist/render/internal.d.ts +1 -1
  280. package/dist/render/internal.d.ts.map +1 -1
  281. package/dist/render/internal.js +1 -1
  282. package/dist/render/internal.js.map +1 -1
  283. package/dist/render/traversal_ops.d.ts.map +1 -1
  284. package/dist/render/util/axis_filtering.cjs.map +1 -1
  285. package/dist/render/util/axis_filtering.d.ts.map +1 -1
  286. package/dist/render/util/axis_filtering.js.map +1 -1
  287. package/dist/render/util/column_collection.cjs +2 -1
  288. package/dist/render/util/column_collection.cjs.map +1 -1
  289. package/dist/render/util/column_collection.d.ts.map +1 -1
  290. package/dist/render/util/column_collection.js +1 -0
  291. package/dist/render/util/column_collection.js.map +1 -1
  292. package/dist/render/util/index.cjs +23 -4
  293. package/dist/render/util/index.d.ts +2 -1
  294. package/dist/render/util/index.js +5 -4
  295. package/dist/render/util/label.cjs.map +1 -1
  296. package/dist/render/util/label.d.ts +1 -1
  297. package/dist/render/util/label.d.ts.map +1 -1
  298. package/dist/render/util/label.js.map +1 -1
  299. package/dist/render/util/pcolumn_data.cjs +8 -11
  300. package/dist/render/util/pcolumn_data.cjs.map +1 -1
  301. package/dist/render/util/pcolumn_data.d.ts.map +1 -1
  302. package/dist/render/util/pcolumn_data.js +8 -10
  303. package/dist/render/util/pcolumn_data.js.map +1 -1
  304. package/dist/render/util/pframe_upgraders.cjs.map +1 -1
  305. package/dist/render/util/pframe_upgraders.js.map +1 -1
  306. package/dist/render/util/split_selectors.d.ts +1 -1
  307. package/dist/render/util/split_selectors.d.ts.map +1 -1
  308. package/dist/services/block_services.cjs +0 -1
  309. package/dist/services/block_services.cjs.map +1 -1
  310. package/dist/services/block_services.d.ts +1 -3
  311. package/dist/services/block_services.d.ts.map +1 -1
  312. package/dist/services/block_services.js.map +1 -1
  313. package/dist/services/get_services.cjs.map +1 -1
  314. package/dist/services/get_services.d.ts.map +1 -1
  315. package/dist/services/get_services.js.map +1 -1
  316. package/dist/services/index.cjs +8 -3
  317. package/dist/services/index.d.ts +2 -1
  318. package/dist/services/index.js +4 -3
  319. package/dist/services/service_bridge.cjs.map +1 -1
  320. package/dist/services/service_bridge.d.ts.map +1 -1
  321. package/dist/services/service_bridge.js.map +1 -1
  322. package/dist/services/service_resolve.d.ts.map +1 -1
  323. package/dist/version.cjs.map +1 -1
  324. package/dist/version.d.ts.map +1 -1
  325. package/dist/version.js.map +1 -1
  326. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"derive_distinct_labels.cjs","names":["Annotation"],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type AxisQualification,\n type PObjectId,\n type PObjectSpec,\n type StringifiedJson,\n type Trace,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport type { MatchQualifications } from \"../columns/column_collection_builder\";\n\nexport type { Trace, TraceEntry } from \"@milaboratories/pl-model-common\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\nconst LINKER_TYPE = \"__LINKER__\";\nconst LINKER_TYPE_FULL = \"__LINKER__@1\";\nconst HIT_QUAL_TYPE = \"__HIT_QUAL__\";\nconst ANCHOR_QUAL_TYPE_PREFIX = \"__ANCHOR_QUAL__:\";\n\nfunction isAnchorQualType(t: string): boolean {\n return t.startsWith(ANCHOR_QUAL_TYPE_PREFIX);\n}\n\nfunction isSyntheticType(t: string): boolean {\n return t === LINKER_TYPE || t === HIT_QUAL_TYPE || isAnchorQualType(t);\n}\n\n/** SDK-internal trace shape — adds fields used by this algorithm only, not part of the on-disk contract. */\ntype ExtendedTraceEntry = Trace[number] & {\n importance?: number;\n position?: \"prefix\" | \"suffix\";\n};\n\nexport type LinkerStep = {\n spec: PObjectSpec;\n qualifications?: AxisQualification[];\n};\n\nexport type Entry =\n | PObjectSpec\n | {\n spec: PObjectSpec;\n /** Extra trace entries merged with the base trace from annotations. */\n extraTrace?: ExtendedTraceEntry[];\n /** Linker steps traversed to discover this column; rendered as \"via …\" only when needed for uniqueness. */\n linkerPath?: LinkerStep[];\n /** Axis qualifications applied to the hit column / already-bound anchors; rendered as \"[…]\" suffixes. */\n qualifications?: MatchQualifications;\n };\n\n/**\n * Per-zone formatters. Each one receives raw inputs and returns the rendered text for that zone,\n * or `undefined` to suppress the zone entirely (no synthetic injection → no minimization, no render).\n */\nexport type DeriveLabelsFormatters = {\n /** Native column label. Default: identity. `undefined` → label entry not added (treated as if spec had no label). */\n native?: (label: string, spec: PObjectSpec, index: number) => string | undefined;\n /** Linker zone (whole \"via …\" piece). Receives step labels with step-quals already inlined.\n * Default: `via ${steps.join(\" > \")}`. */\n linker?: (linkerLabels: string[], spec: PObjectSpec, index: number) => string | undefined;\n /** Per-step linker qualifications inlined into the step base label.\n * Default: `[${formatQualifications(qs)}]`. `undefined` → step rendered without quals. */\n linkerStepQualification?: (\n qualifications: AxisQualification[],\n stepIndex: number,\n stepSpec: PObjectSpec,\n ) => string | undefined;\n /** Hit-axis qualifications block. Default: `[${formatQualifications(qs)}]`. */\n hitQualification?: (\n qualifications: AxisQualification[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n /** Per-anchor qualifications block. Default: `[${anchorId}: ${formatQualifications(qs)}]`. */\n anchorQualification?: (\n anchorId: PObjectId,\n qualifications: AxisQualification[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n};\n\nexport type DeriveLabelsOptions = {\n /** Separator to use between label parts (\" / \" by default). */\n separator?: string;\n /** If true, native label is appended at the end of the trace zone. By default it is prepended (label is the most important name). */\n addLabelAsSuffix?: boolean;\n /** Force inclusion of native column label even when not needed for uniqueness. */\n includeNativeLabel?: boolean;\n /** Trace types that must be included in the label. */\n forceTraceElements?: string[];\n /** Per-zone custom formatters. Returning `undefined` from any formatter suppresses the corresponding zone. */\n formatters?: DeriveLabelsFormatters;\n};\n\nexport function deriveDistinctLabels(values: Entry[], options: DeriveLabelsOptions = {}): string[] {\n const forceTraceElements =\n options.forceTraceElements !== undefined && options.forceTraceElements.length > 0\n ? new Set(options.forceTraceElements)\n : undefined;\n const separator = options.separator ?? \" / \";\n\n const records = values.map((v, i) => enrichRecord(v, i, options));\n const stats = collectTypeStats(records);\n\n const hasAnySynthetic = records.some((r) => r.fullTrace.some((ft) => isSyntheticType(ft.type)));\n const labelForced =\n (options.includeNativeLabel === true || hasAnySynthetic) &&\n stats.countByType.has(LABEL_TYPE_FULL);\n // Tied to labeled-step presence, not path presence: entries with a non-empty linkerPath\n // but no labeled steps contribute no LINKER_TYPE trace entry, so they do not count here.\n const linkerForced = stats.countByType.get(LINKER_TYPE_FULL) === values.length;\n\n const forcedSet = new Set<string>();\n if (labelForced) forcedSet.add(LABEL_TYPE_FULL);\n if (linkerForced) forcedSet.add(LINKER_TYPE_FULL);\n\n const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);\n\n const build = (typeSet: Set<string>, force: boolean) =>\n buildLabels(records, typeSet, forceTraceElements, separator, force);\n\n if (mainTypes.length === 0) {\n if (secondaryTypes.length !== 0)\n throw new Error(\"Non-empty secondary types list while main types list is empty.\");\n\n return (\n build(new Set([LABEL_TYPE_FULL]), true) ??\n throwError(\"Failed to derive labels using native column labels\")\n );\n }\n\n let includedCount = 0;\n let additionalType = -1;\n while (includedCount < mainTypes.length) {\n const currentSet = new Set<string>(forcedSet);\n for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);\n if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);\n\n const candidateResult = build(currentSet, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {\n const minimized = minimizeTypeSet(\n currentSet,\n records,\n stats,\n forceTraceElements,\n forcedSet,\n separator,\n );\n const minimizedLabels =\n build(minimized, false) ?? throwError(\"Failed to derive unique labels\");\n return dropRedundantLinkerSuffix(\n records,\n minimized,\n forceTraceElements,\n forcedSet,\n separator,\n minimizedLabels,\n );\n }\n\n additionalType++;\n if (additionalType >= mainTypes.length) {\n includedCount++;\n additionalType = includedCount;\n }\n }\n\n const fallbackSet = new Set([...forcedSet, ...mainTypes, ...secondaryTypes]);\n const minimized = minimizeTypeSet(\n fallbackSet,\n records,\n stats,\n forceTraceElements,\n forcedSet,\n separator,\n );\n const minimizedLabels = build(minimized, true) ?? throwError(\"Failed to derive unique labels\");\n return dropRedundantLinkerSuffix(\n records,\n minimized,\n forceTraceElements,\n forcedSet,\n separator,\n minimizedLabels,\n );\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = ExtendedTraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord = {\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractEntryParts(entry: Entry): {\n spec: PObjectSpec;\n extraTrace: ExtendedTraceEntry[] | undefined;\n linkerPath: LinkerStep[] | undefined;\n qualifications: MatchQualifications | undefined;\n} {\n const isEnriched = \"spec\" in entry && typeof entry.spec === \"object\";\n if (!isEnriched) {\n return {\n spec: entry as PObjectSpec,\n extraTrace: undefined,\n linkerPath: undefined,\n qualifications: undefined,\n };\n }\n return {\n spec: entry.spec,\n extraTrace: entry.extraTrace,\n linkerPath: entry.linkerPath,\n qualifications: entry.qualifications,\n };\n}\n\nfunction formatQualification(q: AxisQualification): string {\n const ctx = q.contextDomain ?? {};\n const keys = Object.keys(ctx);\n if (keys.length === 0) return q.axis.name;\n const pairs = keys.map((k) => `${k}=${ctx[k]}`).join(\", \");\n return Object.prototype.hasOwnProperty.call(ctx, q.axis.name) ? pairs : `${q.axis.name} ${pairs}`;\n}\n\nfunction formatQualifications(qs: AxisQualification[]): string {\n return qs.map(formatQualification).join(\"; \");\n}\n\nfunction computeStepLabel(\n step: LinkerStep,\n stepIndex: number,\n formatters: DeriveLabelsFormatters | undefined,\n): string | undefined {\n const base = (\n readAnnotation(step.spec, Annotation.LinkLabel) ?? readAnnotation(step.spec, Annotation.Label)\n )?.trim();\n if (isNil(base) || base.length === 0) return undefined;\n if (step.qualifications === undefined || step.qualifications.length === 0) return base;\n const qualText = isFunction(formatters?.linkerStepQualification)\n ? formatters.linkerStepQualification(step.qualifications, stepIndex, step.spec)\n : `[${formatQualifications(step.qualifications)}]`;\n return isNil(qualText) ? base : `${base} ${qualText}`;\n}\n\nfunction buildFullTrace(trace: ExtendedTraceEntry[]): FullTraceEntry[] {\n const result: FullTraceEntry[] = [];\n const occurrences = new Map<string, number>();\n\n for (let i = trace.length - 1; i >= 0; --i) {\n const entry = trace[i];\n const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;\n occurrences.set(entry.type, occurrenceIndex);\n result.push({\n ...entry,\n fullType: `${entry.type}@${occurrenceIndex}`,\n occurrenceIndex,\n });\n }\n\n result.reverse();\n return result;\n}\n\nfunction enrichRecord(value: Entry, index: number, options: DeriveLabelsOptions): EnrichedRecord {\n const { spec, extraTrace, linkerPath, qualifications } = extractEntryParts(value);\n const formatters = options.formatters;\n\n const rawLabel = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace);\n const baseTrace = traceStr\n ? (parseJson(traceStr as StringifiedJson<ExtendedTraceEntry[]>) ?? [])\n : [];\n const prefixExtra = extraTrace?.filter((e) => e.position === \"prefix\") ?? [];\n const suffixExtra = extraTrace?.filter((e) => e.position !== \"prefix\") ?? [];\n const trace: ExtendedTraceEntry[] = [...prefixExtra, ...baseTrace, ...suffixExtra];\n\n if (!isNil(rawLabel)) {\n const label = isFunction(formatters?.native)\n ? formatters.native(rawLabel, spec, index)\n : rawLabel;\n if (!isNil(label)) {\n const labelEntry = { label, type: LABEL_TYPE, importance: -2 };\n if (options.addLabelAsSuffix === true) trace.push(labelEntry);\n else trace.splice(0, 0, labelEntry);\n }\n }\n\n if (linkerPath !== undefined && linkerPath.length > 0) {\n const stepLabels = linkerPath\n .map((step, i) => computeStepLabel(step, i, formatters))\n .filter((s): s is string => !isNil(s));\n if (stepLabels.length > 0) {\n const linkerText = isFunction(formatters?.linker)\n ? formatters.linker(stepLabels, spec, index)\n : `via ${stepLabels.join(\" > \")}`;\n if (!isNil(linkerText)) {\n trace.push({ type: LINKER_TYPE, label: linkerText, importance: -10 });\n }\n }\n }\n\n if (qualifications !== undefined && qualifications.forQueries !== undefined) {\n for (const [anchorId, qs] of Object.entries(qualifications.forQueries)) {\n if (qs.length === 0) continue;\n const anchorText = isFunction(formatters?.anchorQualification)\n ? formatters.anchorQualification(anchorId as PObjectId, qs, spec, index)\n : `[${anchorId}: ${formatQualifications(qs)}]`;\n if (isNil(anchorText)) continue;\n trace.push({\n type: `${ANCHOR_QUAL_TYPE_PREFIX}${anchorId}`,\n label: anchorText,\n importance: -11,\n });\n }\n if (qualifications.forHit !== undefined && qualifications.forHit.length > 0) {\n const hitText = isFunction(formatters?.hitQualification)\n ? formatters.hitQualification(qualifications.forHit, spec, index)\n : `[${formatQualifications(qualifications.forHit)}]`;\n if (!isNil(hitText)) {\n trace.push({ type: HIT_QUAL_TYPE, label: hitText, importance: -12 });\n }\n }\n }\n\n return { fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats(records: EnrichedRecord[]): TypeStats {\n const importances = new Map<string, number>();\n const countByType = new Map<string, number>();\n\n for (const record of records) {\n for (let i = 0; i < record.fullTrace.length; i++) {\n const { fullType, importance: rawImportance } = record.fullTrace[i];\n const importance = rawImportance ?? 0;\n const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;\n\n countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);\n importances.set(\n fullType,\n Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),\n );\n }\n }\n\n return { importances, countByType };\n}\n\nfunction classifyTypes(\n stats: TypeStats,\n totalRecords: number,\n): { mainTypes: string[]; secondaryTypes: string[] } {\n const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);\n\n const mainTypes: string[] = [];\n const secondaryTypes: string[] = [];\n\n for (const [typeName] of sorted) {\n if (typeName.endsWith(\"@1\") || stats.countByType.get(typeName) === totalRecords)\n mainTypes.push(typeName);\n else secondaryTypes.push(typeName);\n }\n\n return { mainTypes, secondaryTypes };\n}\n\nfunction renderRecordLabel(\n record: EnrichedRecord,\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n): string | undefined {\n const traceParts: string[] = [];\n const anchorParts: string[] = [];\n let linkerLabel: string | undefined;\n let hitLabel: string | undefined;\n\n for (const ft of record.fullTrace) {\n if (!(includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type))) continue;\n if (ft.type === LINKER_TYPE) linkerLabel = ft.label;\n else if (ft.type === HIT_QUAL_TYPE) hitLabel = ft.label;\n else if (isAnchorQualType(ft.type)) anchorParts.push(ft.label);\n else traceParts.push(ft.label);\n }\n\n const isEmpty =\n traceParts.length === 0 &&\n anchorParts.length === 0 &&\n linkerLabel === undefined &&\n hitLabel === undefined;\n\n if (isEmpty) return undefined;\n\n let label = traceParts.join(separator);\n const append = (part: string) => {\n label = label.length === 0 ? part : `${label} ${part}`;\n };\n if (linkerLabel !== undefined) append(linkerLabel);\n for (const a of anchorParts) append(a);\n if (hitLabel !== undefined) append(hitLabel);\n\n return label;\n}\n\nfunction buildLabels(\n records: EnrichedRecord[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): string[] | undefined {\n const result: string[] = [];\n\n for (const r of records) {\n const rendered = renderRecordLabel(r, includedTypes, forceTraceElements, separator);\n if (rendered === undefined) {\n if (!force) return undefined;\n result.push(\"Unlabeled\");\n continue;\n }\n result.push(rendered);\n }\n\n return result;\n}\n\n/**\n * Drop the \"via …\" linker suffix from records whose label is already unique without it.\n *\n * Global minimization may include `LINKER_TYPE_FULL` solely to resolve a collision between a\n * subset of records — but `buildLabels` then renders the suffix on every record that carries a\n * linker trace entry, including ones whose stem is already unique. We strip the suffix where it\n * isn't load-bearing while keeping the symmetric rendering required by `linkerForced` /\n * `forceTraceElements`.\n *\n * Rule: a record's linker suffix is redundant iff its stem (label rendered without LINKER) does\n * not appear anywhere else in the set.\n */\nfunction dropRedundantLinkerSuffix(\n records: EnrichedRecord[],\n globalTypeSet: Set<string>,\n forceTraceElements: Set<string> | undefined,\n forcedSet: Set<string>,\n separator: string,\n labels: string[],\n): string[] {\n if (!globalTypeSet.has(LINKER_TYPE_FULL)) return labels;\n if (forcedSet.has(LINKER_TYPE_FULL) || forceTraceElements?.has(LINKER_TYPE)) return labels;\n\n const setWithoutLinker = new Set(globalTypeSet);\n setWithoutLinker.delete(LINKER_TYPE_FULL);\n\n const stems = records.map((r) =>\n renderRecordLabel(r, setWithoutLinker, forceTraceElements, separator),\n );\n\n const stemOccurrences = new Map<string, number>();\n for (const s of stems) {\n if (s !== undefined) stemOccurrences.set(s, (stemOccurrences.get(s) ?? 0) + 1);\n }\n\n return labels.map((label, i) => {\n const stem = stems[i];\n if (stem === undefined) return label;\n return stemOccurrences.get(stem) === 1 ? stem : label;\n });\n}\n\nfunction countUniqueLabels(result: string[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result).size;\n}\n\nfunction minimizeTypeSet(\n typeSet: Set<string>,\n records: EnrichedRecord[],\n stats: TypeStats,\n forceTraceElements: Set<string> | undefined,\n forcedSet: Set<string>,\n separator: string,\n): Set<string> {\n const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);\n if (initialResult === undefined) return typeSet;\n\n const targetCardinality = countUniqueLabels(initialResult);\n const result = new Set(typeSet);\n\n const removable = [...result]\n .filter((t) => !forceTraceElements?.has(t.split(\"@\")[0]) && !forcedSet.has(t))\n .sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));\n\n for (const typeToRemove of removable) {\n const candidate = new Set(result);\n candidate.delete(typeToRemove);\n const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {\n result.delete(typeToRemove);\n }\n }\n\n return result;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"derive_distinct_labels.cjs","names":["Annotation"],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type AxisQualification,\n type PObjectId,\n type PObjectSpec,\n type StringifiedJson,\n type Trace,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport type { MatchQualifications } from \"../columns/column_collection_builder\";\n\nexport type { Trace, TraceEntry } from \"@milaboratories/pl-model-common\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\nconst LINKER_TYPE = \"__LINKER__\";\nconst LINKER_TYPE_FULL = \"__LINKER__@1\";\nconst HIT_QUAL_TYPE = \"__HIT_QUAL__\";\nconst ANCHOR_QUAL_TYPE_PREFIX = \"__ANCHOR_QUAL__:\";\n\nfunction isAnchorQualType(t: string): boolean {\n return t.startsWith(ANCHOR_QUAL_TYPE_PREFIX);\n}\n\nfunction isSyntheticType(t: string): boolean {\n return t === LINKER_TYPE || t === HIT_QUAL_TYPE || isAnchorQualType(t);\n}\n\n/** SDK-internal trace shape — adds fields used by this algorithm only, not part of the on-disk contract. */\ntype ExtendedTraceEntry = Trace[number] & {\n importance?: number;\n position?: \"prefix\" | \"suffix\";\n};\n\nexport type LinkerStep = {\n spec: PObjectSpec;\n qualifications?: AxisQualification[];\n};\n\nexport type Entry =\n | PObjectSpec\n | {\n spec: PObjectSpec;\n /** Extra trace entries merged with the base trace from annotations. */\n extraTrace?: ExtendedTraceEntry[];\n /** Linker steps traversed to discover this column; rendered as \"via …\" only when needed for uniqueness. */\n linkerPath?: LinkerStep[];\n /** Axis qualifications applied to the hit column / already-bound anchors; rendered as \"[…]\" suffixes. */\n qualifications?: MatchQualifications;\n };\n\n/**\n * Per-zone formatters. Each one receives raw inputs and returns the rendered text for that zone,\n * or `undefined` to suppress the zone entirely (no synthetic injection → no minimization, no render).\n */\nexport type DeriveLabelsFormatters = {\n /** Native column label. Default: identity. `undefined` → label entry not added (treated as if spec had no label). */\n native?: (label: string, spec: PObjectSpec, index: number) => string | undefined;\n /** Linker zone (whole \"via …\" piece). Receives step labels with step-quals already inlined.\n * Default: `via ${steps.join(\" > \")}`. */\n linker?: (linkerLabels: string[], spec: PObjectSpec, index: number) => string | undefined;\n /** Per-step linker qualifications inlined into the step base label.\n * Default: `[${formatQualifications(qs)}]`. `undefined` → step rendered without quals. */\n linkerStepQualification?: (\n qualifications: AxisQualification[],\n stepIndex: number,\n stepSpec: PObjectSpec,\n ) => string | undefined;\n /** Hit-axis qualifications block. Default: `[${formatQualifications(qs)}]`. */\n hitQualification?: (\n qualifications: AxisQualification[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n /** Per-anchor qualifications block. Default: `[${anchorId}: ${formatQualifications(qs)}]`. */\n anchorQualification?: (\n anchorId: PObjectId,\n qualifications: AxisQualification[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n};\n\nexport type DeriveLabelsOptions = {\n /** Separator to use between label parts (\" / \" by default). */\n separator?: string;\n /** If true, native label is appended at the end of the trace zone. By default it is prepended (label is the most important name). */\n addLabelAsSuffix?: boolean;\n /** Force inclusion of native column label even when not needed for uniqueness. */\n includeNativeLabel?: boolean;\n /** Trace types that must be included in the label. */\n forceTraceElements?: string[];\n /** Per-zone custom formatters. Returning `undefined` from any formatter suppresses the corresponding zone. */\n formatters?: DeriveLabelsFormatters;\n};\n\nexport function deriveDistinctLabels(values: Entry[], options: DeriveLabelsOptions = {}): string[] {\n const forceTraceElements =\n options.forceTraceElements !== undefined && options.forceTraceElements.length > 0\n ? new Set(options.forceTraceElements)\n : undefined;\n const separator = options.separator ?? \" / \";\n\n const records = values.map((v, i) => enrichRecord(v, i, options));\n const stats = collectTypeStats(records);\n\n const hasAnySynthetic = records.some((r) => r.fullTrace.some((ft) => isSyntheticType(ft.type)));\n const labelForced =\n (options.includeNativeLabel === true || hasAnySynthetic) &&\n stats.countByType.has(LABEL_TYPE_FULL);\n // Tied to labeled-step presence, not path presence: entries with a non-empty linkerPath\n // but no labeled steps contribute no LINKER_TYPE trace entry, so they do not count here.\n const linkerForced = stats.countByType.get(LINKER_TYPE_FULL) === values.length;\n\n const forcedSet = new Set<string>();\n if (labelForced) forcedSet.add(LABEL_TYPE_FULL);\n if (linkerForced) forcedSet.add(LINKER_TYPE_FULL);\n\n const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);\n\n const build = (typeSet: Set<string>, force: boolean) =>\n buildLabels(records, typeSet, forceTraceElements, separator, force);\n\n if (mainTypes.length === 0) {\n if (secondaryTypes.length !== 0)\n throw new Error(\"Non-empty secondary types list while main types list is empty.\");\n\n return (\n build(new Set([LABEL_TYPE_FULL]), true) ??\n throwError(\"Failed to derive labels using native column labels\")\n );\n }\n\n let includedCount = 0;\n let additionalType = -1;\n while (includedCount < mainTypes.length) {\n const currentSet = new Set<string>(forcedSet);\n for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);\n if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);\n\n const candidateResult = build(currentSet, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {\n const minimized = minimizeTypeSet(\n currentSet,\n records,\n stats,\n forceTraceElements,\n forcedSet,\n separator,\n );\n const minimizedLabels =\n build(minimized, false) ?? throwError(\"Failed to derive unique labels\");\n return dropRedundantLinkerSuffix(\n records,\n minimized,\n forceTraceElements,\n forcedSet,\n separator,\n minimizedLabels,\n );\n }\n\n additionalType++;\n if (additionalType >= mainTypes.length) {\n includedCount++;\n additionalType = includedCount;\n }\n }\n\n const fallbackSet = new Set([...forcedSet, ...mainTypes, ...secondaryTypes]);\n const minimized = minimizeTypeSet(\n fallbackSet,\n records,\n stats,\n forceTraceElements,\n forcedSet,\n separator,\n );\n const minimizedLabels = build(minimized, true) ?? throwError(\"Failed to derive unique labels\");\n return dropRedundantLinkerSuffix(\n records,\n minimized,\n forceTraceElements,\n forcedSet,\n separator,\n minimizedLabels,\n );\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = ExtendedTraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord = {\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractEntryParts(entry: Entry): {\n spec: PObjectSpec;\n extraTrace: ExtendedTraceEntry[] | undefined;\n linkerPath: LinkerStep[] | undefined;\n qualifications: MatchQualifications | undefined;\n} {\n const isEnriched = \"spec\" in entry && typeof entry.spec === \"object\";\n if (!isEnriched) {\n return {\n spec: entry as PObjectSpec,\n extraTrace: undefined,\n linkerPath: undefined,\n qualifications: undefined,\n };\n }\n return {\n spec: entry.spec,\n extraTrace: entry.extraTrace,\n linkerPath: entry.linkerPath,\n qualifications: entry.qualifications,\n };\n}\n\nfunction formatQualification(q: AxisQualification): string {\n const ctx = q.contextDomain ?? {};\n const keys = Object.keys(ctx);\n if (keys.length === 0) return q.axis.name;\n const pairs = keys.map((k) => `${k}=${ctx[k]}`).join(\", \");\n return Object.prototype.hasOwnProperty.call(ctx, q.axis.name) ? pairs : `${q.axis.name} ${pairs}`;\n}\n\nfunction formatQualifications(qs: AxisQualification[]): string {\n return qs.map(formatQualification).join(\"; \");\n}\n\nfunction computeStepLabel(\n step: LinkerStep,\n stepIndex: number,\n formatters: DeriveLabelsFormatters | undefined,\n): string | undefined {\n const base = (\n readAnnotation(step.spec, Annotation.LinkLabel) ?? readAnnotation(step.spec, Annotation.Label)\n )?.trim();\n if (isNil(base) || base.length === 0) return undefined;\n if (step.qualifications === undefined || step.qualifications.length === 0) return base;\n const qualText = isFunction(formatters?.linkerStepQualification)\n ? formatters.linkerStepQualification(step.qualifications, stepIndex, step.spec)\n : `[${formatQualifications(step.qualifications)}]`;\n return isNil(qualText) ? base : `${base} ${qualText}`;\n}\n\nfunction buildFullTrace(trace: ExtendedTraceEntry[]): FullTraceEntry[] {\n const result: FullTraceEntry[] = [];\n const occurrences = new Map<string, number>();\n\n for (let i = trace.length - 1; i >= 0; --i) {\n const entry = trace[i];\n const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;\n occurrences.set(entry.type, occurrenceIndex);\n result.push({\n ...entry,\n fullType: `${entry.type}@${occurrenceIndex}`,\n occurrenceIndex,\n });\n }\n\n result.reverse();\n return result;\n}\n\nfunction enrichRecord(value: Entry, index: number, options: DeriveLabelsOptions): EnrichedRecord {\n const { spec, extraTrace, linkerPath, qualifications } = extractEntryParts(value);\n const formatters = options.formatters;\n\n const rawLabel = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace);\n const baseTrace = traceStr\n ? (parseJson(traceStr as StringifiedJson<ExtendedTraceEntry[]>) ?? [])\n : [];\n const prefixExtra = extraTrace?.filter((e) => e.position === \"prefix\") ?? [];\n const suffixExtra = extraTrace?.filter((e) => e.position !== \"prefix\") ?? [];\n const trace: ExtendedTraceEntry[] = [...prefixExtra, ...baseTrace, ...suffixExtra];\n\n if (!isNil(rawLabel)) {\n const label = isFunction(formatters?.native)\n ? formatters.native(rawLabel, spec, index)\n : rawLabel;\n if (!isNil(label)) {\n const labelEntry = { label, type: LABEL_TYPE, importance: -2 };\n if (options.addLabelAsSuffix === true) trace.push(labelEntry);\n else trace.splice(0, 0, labelEntry);\n }\n }\n\n if (linkerPath !== undefined && linkerPath.length > 0) {\n const stepLabels = linkerPath\n .map((step, i) => computeStepLabel(step, i, formatters))\n .filter((s): s is string => !isNil(s));\n if (stepLabels.length > 0) {\n const linkerText = isFunction(formatters?.linker)\n ? formatters.linker(stepLabels, spec, index)\n : `via ${stepLabels.join(\" > \")}`;\n if (!isNil(linkerText)) {\n trace.push({ type: LINKER_TYPE, label: linkerText, importance: -10 });\n }\n }\n }\n\n if (qualifications !== undefined && qualifications.forQueries !== undefined) {\n for (const [anchorId, qs] of Object.entries(qualifications.forQueries)) {\n if (qs.length === 0) continue;\n const anchorText = isFunction(formatters?.anchorQualification)\n ? formatters.anchorQualification(anchorId as PObjectId, qs, spec, index)\n : `[${anchorId}: ${formatQualifications(qs)}]`;\n if (isNil(anchorText)) continue;\n trace.push({\n type: `${ANCHOR_QUAL_TYPE_PREFIX}${anchorId}`,\n label: anchorText,\n importance: -11,\n });\n }\n if (qualifications.forHit !== undefined && qualifications.forHit.length > 0) {\n const hitText = isFunction(formatters?.hitQualification)\n ? formatters.hitQualification(qualifications.forHit, spec, index)\n : `[${formatQualifications(qualifications.forHit)}]`;\n if (!isNil(hitText)) {\n trace.push({ type: HIT_QUAL_TYPE, label: hitText, importance: -12 });\n }\n }\n }\n\n return { fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats(records: EnrichedRecord[]): TypeStats {\n const importances = new Map<string, number>();\n const countByType = new Map<string, number>();\n\n for (const record of records) {\n for (let i = 0; i < record.fullTrace.length; i++) {\n const { fullType, importance: rawImportance } = record.fullTrace[i];\n const importance = rawImportance ?? 0;\n const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;\n\n countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);\n importances.set(\n fullType,\n Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),\n );\n }\n }\n\n return { importances, countByType };\n}\n\nfunction classifyTypes(\n stats: TypeStats,\n totalRecords: number,\n): { mainTypes: string[]; secondaryTypes: string[] } {\n const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);\n\n const mainTypes: string[] = [];\n const secondaryTypes: string[] = [];\n\n for (const [typeName] of sorted) {\n if (typeName.endsWith(\"@1\") || stats.countByType.get(typeName) === totalRecords)\n mainTypes.push(typeName);\n else secondaryTypes.push(typeName);\n }\n\n return { mainTypes, secondaryTypes };\n}\n\nfunction renderRecordLabel(\n record: EnrichedRecord,\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n): string | undefined {\n const traceParts: string[] = [];\n const anchorParts: string[] = [];\n let linkerLabel: string | undefined;\n let hitLabel: string | undefined;\n\n for (const ft of record.fullTrace) {\n if (!(includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type))) continue;\n if (ft.type === LINKER_TYPE) linkerLabel = ft.label;\n else if (ft.type === HIT_QUAL_TYPE) hitLabel = ft.label;\n else if (isAnchorQualType(ft.type)) anchorParts.push(ft.label);\n else traceParts.push(ft.label);\n }\n\n const isEmpty =\n traceParts.length === 0 &&\n anchorParts.length === 0 &&\n linkerLabel === undefined &&\n hitLabel === undefined;\n\n if (isEmpty) return undefined;\n\n let label = traceParts.join(separator);\n const append = (part: string) => {\n label = label.length === 0 ? part : `${label} ${part}`;\n };\n if (linkerLabel !== undefined) append(linkerLabel);\n for (const a of anchorParts) append(a);\n if (hitLabel !== undefined) append(hitLabel);\n\n return label;\n}\n\nfunction buildLabels(\n records: EnrichedRecord[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): string[] | undefined {\n const result: string[] = [];\n\n for (const r of records) {\n const rendered = renderRecordLabel(r, includedTypes, forceTraceElements, separator);\n if (rendered === undefined) {\n if (!force) return undefined;\n result.push(\"Unlabeled\");\n continue;\n }\n result.push(rendered);\n }\n\n return result;\n}\n\n/**\n * Drop the \"via …\" linker suffix from records whose label is already unique without it.\n *\n * Global minimization may include `LINKER_TYPE_FULL` solely to resolve a collision between a\n * subset of records — but `buildLabels` then renders the suffix on every record that carries a\n * linker trace entry, including ones whose stem is already unique. We strip the suffix where it\n * isn't load-bearing while keeping the symmetric rendering required by `linkerForced` /\n * `forceTraceElements`.\n *\n * Rule: a record's linker suffix is redundant iff its stem (label rendered without LINKER) does\n * not appear anywhere else in the set.\n */\nfunction dropRedundantLinkerSuffix(\n records: EnrichedRecord[],\n globalTypeSet: Set<string>,\n forceTraceElements: Set<string> | undefined,\n forcedSet: Set<string>,\n separator: string,\n labels: string[],\n): string[] {\n if (!globalTypeSet.has(LINKER_TYPE_FULL)) return labels;\n if (forcedSet.has(LINKER_TYPE_FULL) || forceTraceElements?.has(LINKER_TYPE)) return labels;\n\n const setWithoutLinker = new Set(globalTypeSet);\n setWithoutLinker.delete(LINKER_TYPE_FULL);\n\n const stems = records.map((r) =>\n renderRecordLabel(r, setWithoutLinker, forceTraceElements, separator),\n );\n\n const stemOccurrences = new Map<string, number>();\n for (const s of stems) {\n if (s !== undefined) stemOccurrences.set(s, (stemOccurrences.get(s) ?? 0) + 1);\n }\n\n return labels.map((label, i) => {\n const stem = stems[i];\n if (stem === undefined) return label;\n return stemOccurrences.get(stem) === 1 ? stem : label;\n });\n}\n\nfunction countUniqueLabels(result: string[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result).size;\n}\n\nfunction minimizeTypeSet(\n typeSet: Set<string>,\n records: EnrichedRecord[],\n stats: TypeStats,\n forceTraceElements: Set<string> | undefined,\n forcedSet: Set<string>,\n separator: string,\n): Set<string> {\n const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);\n if (initialResult === undefined) return typeSet;\n\n const targetCardinality = countUniqueLabels(initialResult);\n const result = new Set(typeSet);\n\n const removable = [...result]\n .filter((t) => !forceTraceElements?.has(t.split(\"@\")[0]) && !forcedSet.has(t))\n .sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));\n\n for (const typeToRemove of removable) {\n const candidate = new Set(result);\n candidate.delete(typeToRemove);\n const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {\n result.delete(typeToRemove);\n }\n }\n\n return result;\n}\n"],"mappings":";;;;AAgBA,MAAM,mBAAmB;AACzB,MAAM,aAAa;AACnB,MAAM,kBAAkB;AACxB,MAAM,cAAc;AACpB,MAAM,mBAAmB;AACzB,MAAM,gBAAgB;AACtB,MAAM,0BAA0B;AAEhC,SAAS,iBAAiB,GAAoB;CAC5C,OAAO,EAAE,WAAW,uBAAuB;AAC7C;AAEA,SAAS,gBAAgB,GAAoB;CAC3C,OAAO,MAAM,eAAe,MAAM,iBAAiB,iBAAiB,CAAC;AACvE;AAsEA,SAAgB,qBAAqB,QAAiB,UAA+B,CAAC,GAAa;CACjG,MAAM,qBACJ,QAAQ,uBAAuB,KAAA,KAAa,QAAQ,mBAAmB,SAAS,IAC5E,IAAI,IAAI,QAAQ,kBAAkB,IAClC,KAAA;CACN,MAAM,YAAY,QAAQ,aAAa;CAEvC,MAAM,UAAU,OAAO,KAAK,GAAG,MAAM,aAAa,GAAG,GAAG,OAAO,CAAC;CAChE,MAAM,QAAQ,iBAAiB,OAAO;CAEtC,MAAM,kBAAkB,QAAQ,MAAM,MAAM,EAAE,UAAU,MAAM,OAAO,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAC9F,MAAM,eACH,QAAQ,uBAAuB,QAAQ,oBACxC,MAAM,YAAY,IAAI,eAAe;CAGvC,MAAM,eAAe,MAAM,YAAY,IAAI,gBAAgB,MAAM,OAAO;CAExE,MAAM,4BAAY,IAAI,IAAY;CAClC,IAAI,aAAa,UAAU,IAAI,eAAe;CAC9C,IAAI,cAAc,UAAU,IAAI,gBAAgB;CAEhD,MAAM,EAAE,WAAW,mBAAmB,cAAc,OAAO,OAAO,MAAM;CAExE,MAAM,SAAS,SAAsB,UACnC,YAAY,SAAS,SAAS,oBAAoB,WAAW,KAAK;CAEpE,IAAI,UAAU,WAAW,GAAG;EAC1B,IAAI,eAAe,WAAW,GAC5B,MAAM,IAAI,MAAM,gEAAgE;EAElF,OACE,sBAAM,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,IAAI,MAAA,GAAA,wBAAA,WAAA,CAC3B,oDAAoD;CAEnE;CAEA,IAAI,gBAAgB;CACpB,IAAI,iBAAiB;CACrB,OAAO,gBAAgB,UAAU,QAAQ;EACvC,MAAM,aAAa,IAAI,IAAY,SAAS;EAC5C,KAAK,IAAI,IAAI,GAAG,IAAI,eAAe,EAAE,GAAG,WAAW,IAAI,UAAU,EAAE;EACnE,IAAI,kBAAkB,GAAG,WAAW,IAAI,UAAU,eAAe;EAEjE,MAAM,kBAAkB,MAAM,YAAY,KAAK;EAC/C,IAAI,oBAAoB,KAAA,KAAa,kBAAkB,eAAe,MAAM,OAAO,QAAQ;GACzF,MAAM,YAAY,gBAChB,YACA,SACA,OACA,oBACA,WACA,SACF;GAGA,OAAO,0BACL,SACA,WACA,oBACA,WACA,WANA,MAAM,WAAW,KAAK,MAAA,GAAA,wBAAA,WAAA,CAAgB,gCAAgC,CAQxE;EACF;EAEA;EACA,IAAI,kBAAkB,UAAU,QAAQ;GACtC;GACA,iBAAiB;EACnB;CACF;CAGA,MAAM,YAAY,gCAChB,IAFsB,IAAI;EAAC,GAAG;EAAW,GAAG;EAAW,GAAG;CAAc,CAE9D,GACV,SACA,OACA,oBACA,WACA,SACF;CAEA,OAAO,0BACL,SACA,WACA,oBACA,WACA,WANsB,MAAM,WAAW,IAAI,MAAA,GAAA,wBAAA,WAAA,CAAgB,gCAAgC,CAQ7F;AACF;AASA,SAAS,kBAAkB,OAKzB;CAEA,IAAI,EADe,UAAU,SAAS,OAAO,MAAM,SAAS,WAE1D,OAAO;EACL,MAAM;EACN,YAAY,KAAA;EACZ,YAAY,KAAA;EACZ,gBAAgB,KAAA;CAClB;CAEF,OAAO;EACL,MAAM,MAAM;EACZ,YAAY,MAAM;EAClB,YAAY,MAAM;EAClB,gBAAgB,MAAM;CACxB;AACF;AAEA,SAAS,oBAAoB,GAA8B;CACzD,MAAM,MAAM,EAAE,iBAAiB,CAAC;CAChC,MAAM,OAAO,OAAO,KAAK,GAAG;CAC5B,IAAI,KAAK,WAAW,GAAG,OAAO,EAAE,KAAK;CACrC,MAAM,QAAQ,KAAK,KAAK,MAAM,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI;CACzD,OAAO,OAAO,UAAU,eAAe,KAAK,KAAK,EAAE,KAAK,IAAI,IAAI,QAAQ,GAAG,EAAE,KAAK,KAAK,GAAG;AAC5F;AAEA,SAAS,qBAAqB,IAAiC;CAC7D,OAAO,GAAG,IAAI,mBAAmB,CAAC,CAAC,KAAK,IAAI;AAC9C;AAEA,SAAS,iBACP,MACA,WACA,YACoB;CACpB,MAAM,SAAA,GAAA,gCAAA,eAAA,CACW,KAAK,MAAMA,gCAAAA,WAAW,SAAS,MAAA,GAAA,gCAAA,eAAA,CAAoB,KAAK,MAAMA,gCAAAA,WAAW,KAAK,EAAA,EAC5F,KAAK;CACR,KAAA,GAAA,WAAA,MAAA,CAAU,IAAI,KAAK,KAAK,WAAW,GAAG,OAAO,KAAA;CAC7C,IAAI,KAAK,mBAAmB,KAAA,KAAa,KAAK,eAAe,WAAW,GAAG,OAAO;CAClF,MAAM,YAAA,GAAA,WAAA,WAAA,CAAsB,YAAY,uBAAuB,IAC3D,WAAW,wBAAwB,KAAK,gBAAgB,WAAW,KAAK,IAAI,IAC5E,IAAI,qBAAqB,KAAK,cAAc,EAAE;CAClD,QAAA,GAAA,WAAA,MAAA,CAAa,QAAQ,IAAI,OAAO,GAAG,KAAK,GAAG;AAC7C;AAEA,SAAS,eAAe,OAA+C;CACrE,MAAM,SAA2B,CAAC;CAClC,MAAM,8BAAc,IAAI,IAAoB;CAE5C,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,EAAE,GAAG;EAC1C,MAAM,QAAQ,MAAM;EACpB,MAAM,mBAAmB,YAAY,IAAI,MAAM,IAAI,KAAK,KAAK;EAC7D,YAAY,IAAI,MAAM,MAAM,eAAe;EAC3C,OAAO,KAAK;GACV,GAAG;GACH,UAAU,GAAG,MAAM,KAAK,GAAG;GAC3B;EACF,CAAC;CACH;CAEA,OAAO,QAAQ;CACf,OAAO;AACT;AAEA,SAAS,aAAa,OAAc,OAAe,SAA8C;CAC/F,MAAM,EAAE,MAAM,YAAY,YAAY,mBAAmB,kBAAkB,KAAK;CAChF,MAAM,aAAa,QAAQ;CAE3B,MAAM,YAAA,GAAA,gCAAA,eAAA,CAA0B,MAAMA,gCAAAA,WAAW,KAAK;CACtD,MAAM,YAAA,GAAA,gCAAA,eAAA,CAA0B,MAAMA,gCAAAA,WAAW,KAAK;CACtD,MAAM,YAAY,YAAA,GAAA,gCAAA,UAAA,CACH,QAAiD,KAAK,CAAC,IAClE,CAAC;CACL,MAAM,cAAc,YAAY,QAAQ,MAAM,EAAE,aAAa,QAAQ,KAAK,CAAC;CAC3E,MAAM,cAAc,YAAY,QAAQ,MAAM,EAAE,aAAa,QAAQ,KAAK,CAAC;CAC3E,MAAM,QAA8B;EAAC,GAAG;EAAa,GAAG;EAAW,GAAG;CAAW;CAEjF,IAAI,EAAA,GAAA,WAAA,MAAA,CAAO,QAAQ,GAAG;EACpB,MAAM,SAAA,GAAA,WAAA,WAAA,CAAmB,YAAY,MAAM,IACvC,WAAW,OAAO,UAAU,MAAM,KAAK,IACvC;EACJ,IAAI,EAAA,GAAA,WAAA,MAAA,CAAO,KAAK,GAAG;GACjB,MAAM,aAAa;IAAE;IAAO,MAAM;IAAY,YAAY;GAAG;GAC7D,IAAI,QAAQ,qBAAqB,MAAM,MAAM,KAAK,UAAU;QACvD,MAAM,OAAO,GAAG,GAAG,UAAU;EACpC;CACF;CAEA,IAAI,eAAe,KAAA,KAAa,WAAW,SAAS,GAAG;EACrD,MAAM,aAAa,WAChB,KAAK,MAAM,MAAM,iBAAiB,MAAM,GAAG,UAAU,CAAC,CAAC,CACvD,QAAQ,MAAmB,EAAA,GAAA,WAAA,MAAA,CAAO,CAAC,CAAC;EACvC,IAAI,WAAW,SAAS,GAAG;GACzB,MAAM,cAAA,GAAA,WAAA,WAAA,CAAwB,YAAY,MAAM,IAC5C,WAAW,OAAO,YAAY,MAAM,KAAK,IACzC,OAAO,WAAW,KAAK,KAAK;GAChC,IAAI,EAAA,GAAA,WAAA,MAAA,CAAO,UAAU,GACnB,MAAM,KAAK;IAAE,MAAM;IAAa,OAAO;IAAY,YAAY;GAAI,CAAC;EAExE;CACF;CAEA,IAAI,mBAAmB,KAAA,KAAa,eAAe,eAAe,KAAA,GAAW;EAC3E,KAAK,MAAM,CAAC,UAAU,OAAO,OAAO,QAAQ,eAAe,UAAU,GAAG;GACtE,IAAI,GAAG,WAAW,GAAG;GACrB,MAAM,cAAA,GAAA,WAAA,WAAA,CAAwB,YAAY,mBAAmB,IACzD,WAAW,oBAAoB,UAAuB,IAAI,MAAM,KAAK,IACrE,IAAI,SAAS,IAAI,qBAAqB,EAAE,EAAE;GAC9C,KAAA,GAAA,WAAA,MAAA,CAAU,UAAU,GAAG;GACvB,MAAM,KAAK;IACT,MAAM,GAAG,0BAA0B;IACnC,OAAO;IACP,YAAY;GACd,CAAC;EACH;EACA,IAAI,eAAe,WAAW,KAAA,KAAa,eAAe,OAAO,SAAS,GAAG;GAC3E,MAAM,WAAA,GAAA,WAAA,WAAA,CAAqB,YAAY,gBAAgB,IACnD,WAAW,iBAAiB,eAAe,QAAQ,MAAM,KAAK,IAC9D,IAAI,qBAAqB,eAAe,MAAM,EAAE;GACpD,IAAI,EAAA,GAAA,WAAA,MAAA,CAAO,OAAO,GAChB,MAAM,KAAK;IAAE,MAAM;IAAe,OAAO;IAAS,YAAY;GAAI,CAAC;EAEvE;CACF;CAEA,OAAO,EAAE,WAAW,eAAe,KAAK,EAAE;AAC5C;AAOA,SAAS,iBAAiB,SAAsC;CAC9D,MAAM,8BAAc,IAAI,IAAoB;CAC5C,MAAM,8BAAc,IAAI,IAAoB;CAE5C,KAAK,MAAM,UAAU,SACnB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,UAAU,QAAQ,KAAK;EAChD,MAAM,EAAE,UAAU,YAAY,kBAAkB,OAAO,UAAU;EACjE,MAAM,aAAa,iBAAiB;EACpC,MAAM,YAAY,OAAO,UAAU,SAAS,KAAK;EAEjD,YAAY,IAAI,WAAW,YAAY,IAAI,QAAQ,KAAK,KAAK,CAAC;EAC9D,YAAY,IACV,UACA,KAAK,IAAI,YAAY,IAAI,QAAQ,KAAK,OAAO,mBAAmB,aAAa,QAAQ,CACvF;CACF;CAGF,OAAO;EAAE;EAAa;CAAY;AACpC;AAEA,SAAS,cACP,OACA,cACmD;CACnD,MAAM,SAAS,CAAC,GAAG,MAAM,WAAW,CAAC,CAAC,MAAM,GAAG,KAAK,GAAG,QAAQ,KAAK,EAAE;CAEtE,MAAM,YAAsB,CAAC;CAC7B,MAAM,iBAA2B,CAAC;CAElC,KAAK,MAAM,CAAC,aAAa,QACvB,IAAI,SAAS,SAAS,IAAI,KAAK,MAAM,YAAY,IAAI,QAAQ,MAAM,cACjE,UAAU,KAAK,QAAQ;MACpB,eAAe,KAAK,QAAQ;CAGnC,OAAO;EAAE;EAAW;CAAe;AACrC;AAEA,SAAS,kBACP,QACA,eACA,oBACA,WACoB;CACpB,MAAM,aAAuB,CAAC;CAC9B,MAAM,cAAwB,CAAC;CAC/B,IAAI;CACJ,IAAI;CAEJ,KAAK,MAAM,MAAM,OAAO,WAAW;EACjC,IAAI,EAAE,cAAc,IAAI,GAAG,QAAQ,KAAK,oBAAoB,IAAI,GAAG,IAAI,IAAI;EAC3E,IAAI,GAAG,SAAS,aAAa,cAAc,GAAG;OACzC,IAAI,GAAG,SAAS,eAAe,WAAW,GAAG;OAC7C,IAAI,iBAAiB,GAAG,IAAI,GAAG,YAAY,KAAK,GAAG,KAAK;OACxD,WAAW,KAAK,GAAG,KAAK;CAC/B;CAQA,IALE,WAAW,WAAW,KACtB,YAAY,WAAW,KACvB,gBAAgB,KAAA,KAChB,aAAa,KAAA,GAEF,OAAO,KAAA;CAEpB,IAAI,QAAQ,WAAW,KAAK,SAAS;CACrC,MAAM,UAAU,SAAiB;EAC/B,QAAQ,MAAM,WAAW,IAAI,OAAO,GAAG,MAAM,GAAG;CAClD;CACA,IAAI,gBAAgB,KAAA,GAAW,OAAO,WAAW;CACjD,KAAK,MAAM,KAAK,aAAa,OAAO,CAAC;CACrC,IAAI,aAAa,KAAA,GAAW,OAAO,QAAQ;CAE3C,OAAO;AACT;AAEA,SAAS,YACP,SACA,eACA,oBACA,WACA,OACsB;CACtB,MAAM,SAAmB,CAAC;CAE1B,KAAK,MAAM,KAAK,SAAS;EACvB,MAAM,WAAW,kBAAkB,GAAG,eAAe,oBAAoB,SAAS;EAClF,IAAI,aAAa,KAAA,GAAW;GAC1B,IAAI,CAAC,OAAO,OAAO,KAAA;GACnB,OAAO,KAAK,WAAW;GACvB;EACF;EACA,OAAO,KAAK,QAAQ;CACtB;CAEA,OAAO;AACT;;;;;;;;;;;;;AAcA,SAAS,0BACP,SACA,eACA,oBACA,WACA,WACA,QACU;CACV,IAAI,CAAC,cAAc,IAAI,gBAAgB,GAAG,OAAO;CACjD,IAAI,UAAU,IAAI,gBAAgB,KAAK,oBAAoB,IAAI,WAAW,GAAG,OAAO;CAEpF,MAAM,mBAAmB,IAAI,IAAI,aAAa;CAC9C,iBAAiB,OAAO,gBAAgB;CAExC,MAAM,QAAQ,QAAQ,KAAK,MACzB,kBAAkB,GAAG,kBAAkB,oBAAoB,SAAS,CACtE;CAEA,MAAM,kCAAkB,IAAI,IAAoB;CAChD,KAAK,MAAM,KAAK,OACd,IAAI,MAAM,KAAA,GAAW,gBAAgB,IAAI,IAAI,gBAAgB,IAAI,CAAC,KAAK,KAAK,CAAC;CAG/E,OAAO,OAAO,KAAK,OAAO,MAAM;EAC9B,MAAM,OAAO,MAAM;EACnB,IAAI,SAAS,KAAA,GAAW,OAAO;EAC/B,OAAO,gBAAgB,IAAI,IAAI,MAAM,IAAI,OAAO;CAClD,CAAC;AACH;AAEA,SAAS,kBAAkB,QAAsC;CAC/D,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,OAAO,IAAI,IAAI,MAAM,CAAC,CAAC;AACzB;AAEA,SAAS,gBACP,SACA,SACA,OACA,oBACA,WACA,WACa;CACb,MAAM,gBAAgB,YAAY,SAAS,SAAS,oBAAoB,WAAW,KAAK;CACxF,IAAI,kBAAkB,KAAA,GAAW,OAAO;CAExC,MAAM,oBAAoB,kBAAkB,aAAa;CACzD,MAAM,SAAS,IAAI,IAAI,OAAO;CAE9B,MAAM,YAAY,CAAC,GAAG,MAAM,CAAC,CAC1B,QAAQ,MAAM,CAAC,oBAAoB,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAC7E,MAAM,GAAG,OAAO,MAAM,YAAY,IAAI,CAAC,KAAK,MAAM,MAAM,YAAY,IAAI,CAAC,KAAK,EAAE;CAEnF,KAAK,MAAM,gBAAgB,WAAW;EACpC,MAAM,YAAY,IAAI,IAAI,MAAM;EAChC,UAAU,OAAO,YAAY;EAC7B,MAAM,kBAAkB,YAAY,SAAS,WAAW,oBAAoB,WAAW,KAAK;EAC5F,IAAI,oBAAoB,KAAA,KAAa,kBAAkB,eAAe,KAAK,mBACzE,OAAO,OAAO,YAAY;CAE9B;CAEA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"derive_distinct_labels.d.ts","names":[],"sources":["../../src/labels/derive_distinct_labels.ts"],"mappings":";;;;;KAiCK,kBAAA,GAAqB,KAAA;EACxB,UAAA;EACA,QAAA;AAAA;AAAA,KAGU,UAAA;EACV,IAAA,EAAM,WAAA;EACN,cAAA,GAAiB,iBAAA;AAAA;AAAA,KAGP,KAAA,GACR,WAAA;EAEE,IAAA,EAAM,WAAA,EARU;EAUhB,UAAA,GAAa,kBAAA,IARiB;EAU9B,UAAA,GAAa,UAAA,IAXX;EAaF,cAAA,GAAiB,mBAAA;AAAA;;;AATvB;;KAgBY,sBAAA;EAfR,qHAiBF,MAAA,IAAU,KAAA,UAAe,IAAA,EAAM,WAAA,EAAa,KAAA;EAb3B;;EAgBjB,MAAA,IAAU,YAAA,YAAwB,IAAA,EAAM,WAAA,EAAa,KAAA;EAZb;;EAexC,uBAAA,IACE,cAAA,EAAgB,iBAAA,IAChB,SAAA,UACA,QAAA,EAAU,WAAA,yBAxBR;EA2BJ,gBAAA,IACE,cAAA,EAAgB,iBAAA,IAChB,IAAA,EAAM,WAAA,EACN,KAAA,iCA5BE;EA+BJ,mBAAA,IACE,QAAA,EAAU,SAAA,EACV,cAAA,EAAgB,iBAAA,IAChB,IAAA,EAAM,WAAA,EACN,KAAA;AAAA;AAAA,KAIQ,mBAAA;EAnCN,+DAqCJ,SAAA,WArCwC;EAuCxC,gBAAA,YAhCU;EAkCV,kBAAA;EAEA,kBAAA,aA/BwC;EAiCxC,UAAA,GAAa,sBAAA;AAAA;AAAA,iBAGC,oBAAA,CAAqB,MAAA,EAAQ,KAAA,IAAS,OAAA,GAAS,mBAAA"}
1
+ {"version":3,"file":"derive_distinct_labels.d.ts","names":[],"sources":["../../src/labels/derive_distinct_labels.ts"],"mappings":";;;;;KAiCK,kBAAA,GAAqB,KAAK;EAC7B,UAAA;EACA,QAAA;AAAA;AAAA,KAGU,UAAA;EACV,IAAA,EAAM,WAAA;EACN,cAAA,GAAiB,iBAAiB;AAAA;AAAA,KAGxB,KAAA,GACR,WAAA;EAEE,IAAA,EAAM,WAAA,EARU;EAUhB,UAAA,GAAa,kBAAA,IARiB;EAU9B,UAAA,GAAa,UAAA,IAXX;EAaF,cAAA,GAAiB,mBAAA;AAAA;;AAZa;AAGpC;;KAgBY,sBAAA;EAfR,qHAiBF,MAAA,IAAU,KAAA,UAAe,IAAA,EAAM,WAAA,EAAa,KAAA;EAb3B;;EAgBjB,MAAA,IAAU,YAAA,YAAwB,IAAA,EAAM,WAAA,EAAa,KAAA;EAZb;;EAexC,uBAAA,IACE,cAAA,EAAgB,iBAAA,IAChB,SAAA,UACA,QAAA,EAAU,WAAA,yBAxBR;EA2BJ,gBAAA,IACE,cAAA,EAAgB,iBAAA,IAChB,IAAA,EAAM,WAAA,EACN,KAAA,iCA5BE;EA+BJ,mBAAA,IACE,QAAA,EAAU,SAAA,EACV,cAAA,EAAgB,iBAAA,IAChB,IAAA,EAAM,WAAA,EACN,KAAA;AAAA;AAAA,KAIQ,mBAAA;EAnCN,+DAqCJ,SAAA,WArCwC;EAuCxC,gBAAA,YAhCU;EAkCV,kBAAA;EAEA,kBAAA,aA/BwC;EAiCxC,UAAA,GAAa,sBAAsB;AAAA;AAAA,iBAGrB,oBAAA,CAAqB,MAAA,EAAQ,KAAA,IAAS,OAAA,GAAS,mBAAwB"}
@@ -30,7 +30,7 @@ function deriveDistinctLabels(values, options = {}) {
30
30
  const build = (typeSet, force) => buildLabels(records, typeSet, forceTraceElements, separator, force);
31
31
  if (mainTypes.length === 0) {
32
32
  if (secondaryTypes.length !== 0) throw new Error("Non-empty secondary types list while main types list is empty.");
33
- return build(new Set([LABEL_TYPE_FULL]), true) ?? throwError("Failed to derive labels using native column labels");
33
+ return build(/* @__PURE__ */ new Set([LABEL_TYPE_FULL]), true) ?? throwError("Failed to derive labels using native column labels");
34
34
  }
35
35
  let includedCount = 0;
36
36
  let additionalType = -1;
@@ -49,7 +49,7 @@ function deriveDistinctLabels(values, options = {}) {
49
49
  additionalType = includedCount;
50
50
  }
51
51
  }
52
- const minimized = minimizeTypeSet(new Set([
52
+ const minimized = minimizeTypeSet(/* @__PURE__ */ new Set([
53
53
  ...forcedSet,
54
54
  ...mainTypes,
55
55
  ...secondaryTypes
@@ -1 +1 @@
1
- {"version":3,"file":"derive_distinct_labels.js","names":["isNil"],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type AxisQualification,\n type PObjectId,\n type PObjectSpec,\n type StringifiedJson,\n type Trace,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport type { MatchQualifications } from \"../columns/column_collection_builder\";\n\nexport type { Trace, TraceEntry } from \"@milaboratories/pl-model-common\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\nconst LINKER_TYPE = \"__LINKER__\";\nconst LINKER_TYPE_FULL = \"__LINKER__@1\";\nconst HIT_QUAL_TYPE = \"__HIT_QUAL__\";\nconst ANCHOR_QUAL_TYPE_PREFIX = \"__ANCHOR_QUAL__:\";\n\nfunction isAnchorQualType(t: string): boolean {\n return t.startsWith(ANCHOR_QUAL_TYPE_PREFIX);\n}\n\nfunction isSyntheticType(t: string): boolean {\n return t === LINKER_TYPE || t === HIT_QUAL_TYPE || isAnchorQualType(t);\n}\n\n/** SDK-internal trace shape — adds fields used by this algorithm only, not part of the on-disk contract. */\ntype ExtendedTraceEntry = Trace[number] & {\n importance?: number;\n position?: \"prefix\" | \"suffix\";\n};\n\nexport type LinkerStep = {\n spec: PObjectSpec;\n qualifications?: AxisQualification[];\n};\n\nexport type Entry =\n | PObjectSpec\n | {\n spec: PObjectSpec;\n /** Extra trace entries merged with the base trace from annotations. */\n extraTrace?: ExtendedTraceEntry[];\n /** Linker steps traversed to discover this column; rendered as \"via …\" only when needed for uniqueness. */\n linkerPath?: LinkerStep[];\n /** Axis qualifications applied to the hit column / already-bound anchors; rendered as \"[…]\" suffixes. */\n qualifications?: MatchQualifications;\n };\n\n/**\n * Per-zone formatters. Each one receives raw inputs and returns the rendered text for that zone,\n * or `undefined` to suppress the zone entirely (no synthetic injection → no minimization, no render).\n */\nexport type DeriveLabelsFormatters = {\n /** Native column label. Default: identity. `undefined` → label entry not added (treated as if spec had no label). */\n native?: (label: string, spec: PObjectSpec, index: number) => string | undefined;\n /** Linker zone (whole \"via …\" piece). Receives step labels with step-quals already inlined.\n * Default: `via ${steps.join(\" > \")}`. */\n linker?: (linkerLabels: string[], spec: PObjectSpec, index: number) => string | undefined;\n /** Per-step linker qualifications inlined into the step base label.\n * Default: `[${formatQualifications(qs)}]`. `undefined` → step rendered without quals. */\n linkerStepQualification?: (\n qualifications: AxisQualification[],\n stepIndex: number,\n stepSpec: PObjectSpec,\n ) => string | undefined;\n /** Hit-axis qualifications block. Default: `[${formatQualifications(qs)}]`. */\n hitQualification?: (\n qualifications: AxisQualification[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n /** Per-anchor qualifications block. Default: `[${anchorId}: ${formatQualifications(qs)}]`. */\n anchorQualification?: (\n anchorId: PObjectId,\n qualifications: AxisQualification[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n};\n\nexport type DeriveLabelsOptions = {\n /** Separator to use between label parts (\" / \" by default). */\n separator?: string;\n /** If true, native label is appended at the end of the trace zone. By default it is prepended (label is the most important name). */\n addLabelAsSuffix?: boolean;\n /** Force inclusion of native column label even when not needed for uniqueness. */\n includeNativeLabel?: boolean;\n /** Trace types that must be included in the label. */\n forceTraceElements?: string[];\n /** Per-zone custom formatters. Returning `undefined` from any formatter suppresses the corresponding zone. */\n formatters?: DeriveLabelsFormatters;\n};\n\nexport function deriveDistinctLabels(values: Entry[], options: DeriveLabelsOptions = {}): string[] {\n const forceTraceElements =\n options.forceTraceElements !== undefined && options.forceTraceElements.length > 0\n ? new Set(options.forceTraceElements)\n : undefined;\n const separator = options.separator ?? \" / \";\n\n const records = values.map((v, i) => enrichRecord(v, i, options));\n const stats = collectTypeStats(records);\n\n const hasAnySynthetic = records.some((r) => r.fullTrace.some((ft) => isSyntheticType(ft.type)));\n const labelForced =\n (options.includeNativeLabel === true || hasAnySynthetic) &&\n stats.countByType.has(LABEL_TYPE_FULL);\n // Tied to labeled-step presence, not path presence: entries with a non-empty linkerPath\n // but no labeled steps contribute no LINKER_TYPE trace entry, so they do not count here.\n const linkerForced = stats.countByType.get(LINKER_TYPE_FULL) === values.length;\n\n const forcedSet = new Set<string>();\n if (labelForced) forcedSet.add(LABEL_TYPE_FULL);\n if (linkerForced) forcedSet.add(LINKER_TYPE_FULL);\n\n const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);\n\n const build = (typeSet: Set<string>, force: boolean) =>\n buildLabels(records, typeSet, forceTraceElements, separator, force);\n\n if (mainTypes.length === 0) {\n if (secondaryTypes.length !== 0)\n throw new Error(\"Non-empty secondary types list while main types list is empty.\");\n\n return (\n build(new Set([LABEL_TYPE_FULL]), true) ??\n throwError(\"Failed to derive labels using native column labels\")\n );\n }\n\n let includedCount = 0;\n let additionalType = -1;\n while (includedCount < mainTypes.length) {\n const currentSet = new Set<string>(forcedSet);\n for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);\n if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);\n\n const candidateResult = build(currentSet, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {\n const minimized = minimizeTypeSet(\n currentSet,\n records,\n stats,\n forceTraceElements,\n forcedSet,\n separator,\n );\n const minimizedLabels =\n build(minimized, false) ?? throwError(\"Failed to derive unique labels\");\n return dropRedundantLinkerSuffix(\n records,\n minimized,\n forceTraceElements,\n forcedSet,\n separator,\n minimizedLabels,\n );\n }\n\n additionalType++;\n if (additionalType >= mainTypes.length) {\n includedCount++;\n additionalType = includedCount;\n }\n }\n\n const fallbackSet = new Set([...forcedSet, ...mainTypes, ...secondaryTypes]);\n const minimized = minimizeTypeSet(\n fallbackSet,\n records,\n stats,\n forceTraceElements,\n forcedSet,\n separator,\n );\n const minimizedLabels = build(minimized, true) ?? throwError(\"Failed to derive unique labels\");\n return dropRedundantLinkerSuffix(\n records,\n minimized,\n forceTraceElements,\n forcedSet,\n separator,\n minimizedLabels,\n );\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = ExtendedTraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord = {\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractEntryParts(entry: Entry): {\n spec: PObjectSpec;\n extraTrace: ExtendedTraceEntry[] | undefined;\n linkerPath: LinkerStep[] | undefined;\n qualifications: MatchQualifications | undefined;\n} {\n const isEnriched = \"spec\" in entry && typeof entry.spec === \"object\";\n if (!isEnriched) {\n return {\n spec: entry as PObjectSpec,\n extraTrace: undefined,\n linkerPath: undefined,\n qualifications: undefined,\n };\n }\n return {\n spec: entry.spec,\n extraTrace: entry.extraTrace,\n linkerPath: entry.linkerPath,\n qualifications: entry.qualifications,\n };\n}\n\nfunction formatQualification(q: AxisQualification): string {\n const ctx = q.contextDomain ?? {};\n const keys = Object.keys(ctx);\n if (keys.length === 0) return q.axis.name;\n const pairs = keys.map((k) => `${k}=${ctx[k]}`).join(\", \");\n return Object.prototype.hasOwnProperty.call(ctx, q.axis.name) ? pairs : `${q.axis.name} ${pairs}`;\n}\n\nfunction formatQualifications(qs: AxisQualification[]): string {\n return qs.map(formatQualification).join(\"; \");\n}\n\nfunction computeStepLabel(\n step: LinkerStep,\n stepIndex: number,\n formatters: DeriveLabelsFormatters | undefined,\n): string | undefined {\n const base = (\n readAnnotation(step.spec, Annotation.LinkLabel) ?? readAnnotation(step.spec, Annotation.Label)\n )?.trim();\n if (isNil(base) || base.length === 0) return undefined;\n if (step.qualifications === undefined || step.qualifications.length === 0) return base;\n const qualText = isFunction(formatters?.linkerStepQualification)\n ? formatters.linkerStepQualification(step.qualifications, stepIndex, step.spec)\n : `[${formatQualifications(step.qualifications)}]`;\n return isNil(qualText) ? base : `${base} ${qualText}`;\n}\n\nfunction buildFullTrace(trace: ExtendedTraceEntry[]): FullTraceEntry[] {\n const result: FullTraceEntry[] = [];\n const occurrences = new Map<string, number>();\n\n for (let i = trace.length - 1; i >= 0; --i) {\n const entry = trace[i];\n const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;\n occurrences.set(entry.type, occurrenceIndex);\n result.push({\n ...entry,\n fullType: `${entry.type}@${occurrenceIndex}`,\n occurrenceIndex,\n });\n }\n\n result.reverse();\n return result;\n}\n\nfunction enrichRecord(value: Entry, index: number, options: DeriveLabelsOptions): EnrichedRecord {\n const { spec, extraTrace, linkerPath, qualifications } = extractEntryParts(value);\n const formatters = options.formatters;\n\n const rawLabel = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace);\n const baseTrace = traceStr\n ? (parseJson(traceStr as StringifiedJson<ExtendedTraceEntry[]>) ?? [])\n : [];\n const prefixExtra = extraTrace?.filter((e) => e.position === \"prefix\") ?? [];\n const suffixExtra = extraTrace?.filter((e) => e.position !== \"prefix\") ?? [];\n const trace: ExtendedTraceEntry[] = [...prefixExtra, ...baseTrace, ...suffixExtra];\n\n if (!isNil(rawLabel)) {\n const label = isFunction(formatters?.native)\n ? formatters.native(rawLabel, spec, index)\n : rawLabel;\n if (!isNil(label)) {\n const labelEntry = { label, type: LABEL_TYPE, importance: -2 };\n if (options.addLabelAsSuffix === true) trace.push(labelEntry);\n else trace.splice(0, 0, labelEntry);\n }\n }\n\n if (linkerPath !== undefined && linkerPath.length > 0) {\n const stepLabels = linkerPath\n .map((step, i) => computeStepLabel(step, i, formatters))\n .filter((s): s is string => !isNil(s));\n if (stepLabels.length > 0) {\n const linkerText = isFunction(formatters?.linker)\n ? formatters.linker(stepLabels, spec, index)\n : `via ${stepLabels.join(\" > \")}`;\n if (!isNil(linkerText)) {\n trace.push({ type: LINKER_TYPE, label: linkerText, importance: -10 });\n }\n }\n }\n\n if (qualifications !== undefined && qualifications.forQueries !== undefined) {\n for (const [anchorId, qs] of Object.entries(qualifications.forQueries)) {\n if (qs.length === 0) continue;\n const anchorText = isFunction(formatters?.anchorQualification)\n ? formatters.anchorQualification(anchorId as PObjectId, qs, spec, index)\n : `[${anchorId}: ${formatQualifications(qs)}]`;\n if (isNil(anchorText)) continue;\n trace.push({\n type: `${ANCHOR_QUAL_TYPE_PREFIX}${anchorId}`,\n label: anchorText,\n importance: -11,\n });\n }\n if (qualifications.forHit !== undefined && qualifications.forHit.length > 0) {\n const hitText = isFunction(formatters?.hitQualification)\n ? formatters.hitQualification(qualifications.forHit, spec, index)\n : `[${formatQualifications(qualifications.forHit)}]`;\n if (!isNil(hitText)) {\n trace.push({ type: HIT_QUAL_TYPE, label: hitText, importance: -12 });\n }\n }\n }\n\n return { fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats(records: EnrichedRecord[]): TypeStats {\n const importances = new Map<string, number>();\n const countByType = new Map<string, number>();\n\n for (const record of records) {\n for (let i = 0; i < record.fullTrace.length; i++) {\n const { fullType, importance: rawImportance } = record.fullTrace[i];\n const importance = rawImportance ?? 0;\n const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;\n\n countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);\n importances.set(\n fullType,\n Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),\n );\n }\n }\n\n return { importances, countByType };\n}\n\nfunction classifyTypes(\n stats: TypeStats,\n totalRecords: number,\n): { mainTypes: string[]; secondaryTypes: string[] } {\n const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);\n\n const mainTypes: string[] = [];\n const secondaryTypes: string[] = [];\n\n for (const [typeName] of sorted) {\n if (typeName.endsWith(\"@1\") || stats.countByType.get(typeName) === totalRecords)\n mainTypes.push(typeName);\n else secondaryTypes.push(typeName);\n }\n\n return { mainTypes, secondaryTypes };\n}\n\nfunction renderRecordLabel(\n record: EnrichedRecord,\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n): string | undefined {\n const traceParts: string[] = [];\n const anchorParts: string[] = [];\n let linkerLabel: string | undefined;\n let hitLabel: string | undefined;\n\n for (const ft of record.fullTrace) {\n if (!(includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type))) continue;\n if (ft.type === LINKER_TYPE) linkerLabel = ft.label;\n else if (ft.type === HIT_QUAL_TYPE) hitLabel = ft.label;\n else if (isAnchorQualType(ft.type)) anchorParts.push(ft.label);\n else traceParts.push(ft.label);\n }\n\n const isEmpty =\n traceParts.length === 0 &&\n anchorParts.length === 0 &&\n linkerLabel === undefined &&\n hitLabel === undefined;\n\n if (isEmpty) return undefined;\n\n let label = traceParts.join(separator);\n const append = (part: string) => {\n label = label.length === 0 ? part : `${label} ${part}`;\n };\n if (linkerLabel !== undefined) append(linkerLabel);\n for (const a of anchorParts) append(a);\n if (hitLabel !== undefined) append(hitLabel);\n\n return label;\n}\n\nfunction buildLabels(\n records: EnrichedRecord[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): string[] | undefined {\n const result: string[] = [];\n\n for (const r of records) {\n const rendered = renderRecordLabel(r, includedTypes, forceTraceElements, separator);\n if (rendered === undefined) {\n if (!force) return undefined;\n result.push(\"Unlabeled\");\n continue;\n }\n result.push(rendered);\n }\n\n return result;\n}\n\n/**\n * Drop the \"via …\" linker suffix from records whose label is already unique without it.\n *\n * Global minimization may include `LINKER_TYPE_FULL` solely to resolve a collision between a\n * subset of records — but `buildLabels` then renders the suffix on every record that carries a\n * linker trace entry, including ones whose stem is already unique. We strip the suffix where it\n * isn't load-bearing while keeping the symmetric rendering required by `linkerForced` /\n * `forceTraceElements`.\n *\n * Rule: a record's linker suffix is redundant iff its stem (label rendered without LINKER) does\n * not appear anywhere else in the set.\n */\nfunction dropRedundantLinkerSuffix(\n records: EnrichedRecord[],\n globalTypeSet: Set<string>,\n forceTraceElements: Set<string> | undefined,\n forcedSet: Set<string>,\n separator: string,\n labels: string[],\n): string[] {\n if (!globalTypeSet.has(LINKER_TYPE_FULL)) return labels;\n if (forcedSet.has(LINKER_TYPE_FULL) || forceTraceElements?.has(LINKER_TYPE)) return labels;\n\n const setWithoutLinker = new Set(globalTypeSet);\n setWithoutLinker.delete(LINKER_TYPE_FULL);\n\n const stems = records.map((r) =>\n renderRecordLabel(r, setWithoutLinker, forceTraceElements, separator),\n );\n\n const stemOccurrences = new Map<string, number>();\n for (const s of stems) {\n if (s !== undefined) stemOccurrences.set(s, (stemOccurrences.get(s) ?? 0) + 1);\n }\n\n return labels.map((label, i) => {\n const stem = stems[i];\n if (stem === undefined) return label;\n return stemOccurrences.get(stem) === 1 ? stem : label;\n });\n}\n\nfunction countUniqueLabels(result: string[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result).size;\n}\n\nfunction minimizeTypeSet(\n typeSet: Set<string>,\n records: EnrichedRecord[],\n stats: TypeStats,\n forceTraceElements: Set<string> | undefined,\n forcedSet: Set<string>,\n separator: string,\n): Set<string> {\n const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);\n if (initialResult === undefined) return typeSet;\n\n const targetCardinality = countUniqueLabels(initialResult);\n const result = new Set(typeSet);\n\n const removable = [...result]\n .filter((t) => !forceTraceElements?.has(t.split(\"@\")[0]) && !forcedSet.has(t))\n .sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));\n\n for (const typeToRemove of removable) {\n const candidate = new Set(result);\n candidate.delete(typeToRemove);\n const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {\n result.delete(typeToRemove);\n }\n }\n\n return result;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"derive_distinct_labels.js","names":["isNil"],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type AxisQualification,\n type PObjectId,\n type PObjectSpec,\n type StringifiedJson,\n type Trace,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport type { MatchQualifications } from \"../columns/column_collection_builder\";\n\nexport type { Trace, TraceEntry } from \"@milaboratories/pl-model-common\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\nconst LINKER_TYPE = \"__LINKER__\";\nconst LINKER_TYPE_FULL = \"__LINKER__@1\";\nconst HIT_QUAL_TYPE = \"__HIT_QUAL__\";\nconst ANCHOR_QUAL_TYPE_PREFIX = \"__ANCHOR_QUAL__:\";\n\nfunction isAnchorQualType(t: string): boolean {\n return t.startsWith(ANCHOR_QUAL_TYPE_PREFIX);\n}\n\nfunction isSyntheticType(t: string): boolean {\n return t === LINKER_TYPE || t === HIT_QUAL_TYPE || isAnchorQualType(t);\n}\n\n/** SDK-internal trace shape — adds fields used by this algorithm only, not part of the on-disk contract. */\ntype ExtendedTraceEntry = Trace[number] & {\n importance?: number;\n position?: \"prefix\" | \"suffix\";\n};\n\nexport type LinkerStep = {\n spec: PObjectSpec;\n qualifications?: AxisQualification[];\n};\n\nexport type Entry =\n | PObjectSpec\n | {\n spec: PObjectSpec;\n /** Extra trace entries merged with the base trace from annotations. */\n extraTrace?: ExtendedTraceEntry[];\n /** Linker steps traversed to discover this column; rendered as \"via …\" only when needed for uniqueness. */\n linkerPath?: LinkerStep[];\n /** Axis qualifications applied to the hit column / already-bound anchors; rendered as \"[…]\" suffixes. */\n qualifications?: MatchQualifications;\n };\n\n/**\n * Per-zone formatters. Each one receives raw inputs and returns the rendered text for that zone,\n * or `undefined` to suppress the zone entirely (no synthetic injection → no minimization, no render).\n */\nexport type DeriveLabelsFormatters = {\n /** Native column label. Default: identity. `undefined` → label entry not added (treated as if spec had no label). */\n native?: (label: string, spec: PObjectSpec, index: number) => string | undefined;\n /** Linker zone (whole \"via …\" piece). Receives step labels with step-quals already inlined.\n * Default: `via ${steps.join(\" > \")}`. */\n linker?: (linkerLabels: string[], spec: PObjectSpec, index: number) => string | undefined;\n /** Per-step linker qualifications inlined into the step base label.\n * Default: `[${formatQualifications(qs)}]`. `undefined` → step rendered without quals. */\n linkerStepQualification?: (\n qualifications: AxisQualification[],\n stepIndex: number,\n stepSpec: PObjectSpec,\n ) => string | undefined;\n /** Hit-axis qualifications block. Default: `[${formatQualifications(qs)}]`. */\n hitQualification?: (\n qualifications: AxisQualification[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n /** Per-anchor qualifications block. Default: `[${anchorId}: ${formatQualifications(qs)}]`. */\n anchorQualification?: (\n anchorId: PObjectId,\n qualifications: AxisQualification[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n};\n\nexport type DeriveLabelsOptions = {\n /** Separator to use between label parts (\" / \" by default). */\n separator?: string;\n /** If true, native label is appended at the end of the trace zone. By default it is prepended (label is the most important name). */\n addLabelAsSuffix?: boolean;\n /** Force inclusion of native column label even when not needed for uniqueness. */\n includeNativeLabel?: boolean;\n /** Trace types that must be included in the label. */\n forceTraceElements?: string[];\n /** Per-zone custom formatters. Returning `undefined` from any formatter suppresses the corresponding zone. */\n formatters?: DeriveLabelsFormatters;\n};\n\nexport function deriveDistinctLabels(values: Entry[], options: DeriveLabelsOptions = {}): string[] {\n const forceTraceElements =\n options.forceTraceElements !== undefined && options.forceTraceElements.length > 0\n ? new Set(options.forceTraceElements)\n : undefined;\n const separator = options.separator ?? \" / \";\n\n const records = values.map((v, i) => enrichRecord(v, i, options));\n const stats = collectTypeStats(records);\n\n const hasAnySynthetic = records.some((r) => r.fullTrace.some((ft) => isSyntheticType(ft.type)));\n const labelForced =\n (options.includeNativeLabel === true || hasAnySynthetic) &&\n stats.countByType.has(LABEL_TYPE_FULL);\n // Tied to labeled-step presence, not path presence: entries with a non-empty linkerPath\n // but no labeled steps contribute no LINKER_TYPE trace entry, so they do not count here.\n const linkerForced = stats.countByType.get(LINKER_TYPE_FULL) === values.length;\n\n const forcedSet = new Set<string>();\n if (labelForced) forcedSet.add(LABEL_TYPE_FULL);\n if (linkerForced) forcedSet.add(LINKER_TYPE_FULL);\n\n const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);\n\n const build = (typeSet: Set<string>, force: boolean) =>\n buildLabels(records, typeSet, forceTraceElements, separator, force);\n\n if (mainTypes.length === 0) {\n if (secondaryTypes.length !== 0)\n throw new Error(\"Non-empty secondary types list while main types list is empty.\");\n\n return (\n build(new Set([LABEL_TYPE_FULL]), true) ??\n throwError(\"Failed to derive labels using native column labels\")\n );\n }\n\n let includedCount = 0;\n let additionalType = -1;\n while (includedCount < mainTypes.length) {\n const currentSet = new Set<string>(forcedSet);\n for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);\n if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);\n\n const candidateResult = build(currentSet, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {\n const minimized = minimizeTypeSet(\n currentSet,\n records,\n stats,\n forceTraceElements,\n forcedSet,\n separator,\n );\n const minimizedLabels =\n build(minimized, false) ?? throwError(\"Failed to derive unique labels\");\n return dropRedundantLinkerSuffix(\n records,\n minimized,\n forceTraceElements,\n forcedSet,\n separator,\n minimizedLabels,\n );\n }\n\n additionalType++;\n if (additionalType >= mainTypes.length) {\n includedCount++;\n additionalType = includedCount;\n }\n }\n\n const fallbackSet = new Set([...forcedSet, ...mainTypes, ...secondaryTypes]);\n const minimized = minimizeTypeSet(\n fallbackSet,\n records,\n stats,\n forceTraceElements,\n forcedSet,\n separator,\n );\n const minimizedLabels = build(minimized, true) ?? throwError(\"Failed to derive unique labels\");\n return dropRedundantLinkerSuffix(\n records,\n minimized,\n forceTraceElements,\n forcedSet,\n separator,\n minimizedLabels,\n );\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = ExtendedTraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord = {\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractEntryParts(entry: Entry): {\n spec: PObjectSpec;\n extraTrace: ExtendedTraceEntry[] | undefined;\n linkerPath: LinkerStep[] | undefined;\n qualifications: MatchQualifications | undefined;\n} {\n const isEnriched = \"spec\" in entry && typeof entry.spec === \"object\";\n if (!isEnriched) {\n return {\n spec: entry as PObjectSpec,\n extraTrace: undefined,\n linkerPath: undefined,\n qualifications: undefined,\n };\n }\n return {\n spec: entry.spec,\n extraTrace: entry.extraTrace,\n linkerPath: entry.linkerPath,\n qualifications: entry.qualifications,\n };\n}\n\nfunction formatQualification(q: AxisQualification): string {\n const ctx = q.contextDomain ?? {};\n const keys = Object.keys(ctx);\n if (keys.length === 0) return q.axis.name;\n const pairs = keys.map((k) => `${k}=${ctx[k]}`).join(\", \");\n return Object.prototype.hasOwnProperty.call(ctx, q.axis.name) ? pairs : `${q.axis.name} ${pairs}`;\n}\n\nfunction formatQualifications(qs: AxisQualification[]): string {\n return qs.map(formatQualification).join(\"; \");\n}\n\nfunction computeStepLabel(\n step: LinkerStep,\n stepIndex: number,\n formatters: DeriveLabelsFormatters | undefined,\n): string | undefined {\n const base = (\n readAnnotation(step.spec, Annotation.LinkLabel) ?? readAnnotation(step.spec, Annotation.Label)\n )?.trim();\n if (isNil(base) || base.length === 0) return undefined;\n if (step.qualifications === undefined || step.qualifications.length === 0) return base;\n const qualText = isFunction(formatters?.linkerStepQualification)\n ? formatters.linkerStepQualification(step.qualifications, stepIndex, step.spec)\n : `[${formatQualifications(step.qualifications)}]`;\n return isNil(qualText) ? base : `${base} ${qualText}`;\n}\n\nfunction buildFullTrace(trace: ExtendedTraceEntry[]): FullTraceEntry[] {\n const result: FullTraceEntry[] = [];\n const occurrences = new Map<string, number>();\n\n for (let i = trace.length - 1; i >= 0; --i) {\n const entry = trace[i];\n const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;\n occurrences.set(entry.type, occurrenceIndex);\n result.push({\n ...entry,\n fullType: `${entry.type}@${occurrenceIndex}`,\n occurrenceIndex,\n });\n }\n\n result.reverse();\n return result;\n}\n\nfunction enrichRecord(value: Entry, index: number, options: DeriveLabelsOptions): EnrichedRecord {\n const { spec, extraTrace, linkerPath, qualifications } = extractEntryParts(value);\n const formatters = options.formatters;\n\n const rawLabel = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace);\n const baseTrace = traceStr\n ? (parseJson(traceStr as StringifiedJson<ExtendedTraceEntry[]>) ?? [])\n : [];\n const prefixExtra = extraTrace?.filter((e) => e.position === \"prefix\") ?? [];\n const suffixExtra = extraTrace?.filter((e) => e.position !== \"prefix\") ?? [];\n const trace: ExtendedTraceEntry[] = [...prefixExtra, ...baseTrace, ...suffixExtra];\n\n if (!isNil(rawLabel)) {\n const label = isFunction(formatters?.native)\n ? formatters.native(rawLabel, spec, index)\n : rawLabel;\n if (!isNil(label)) {\n const labelEntry = { label, type: LABEL_TYPE, importance: -2 };\n if (options.addLabelAsSuffix === true) trace.push(labelEntry);\n else trace.splice(0, 0, labelEntry);\n }\n }\n\n if (linkerPath !== undefined && linkerPath.length > 0) {\n const stepLabels = linkerPath\n .map((step, i) => computeStepLabel(step, i, formatters))\n .filter((s): s is string => !isNil(s));\n if (stepLabels.length > 0) {\n const linkerText = isFunction(formatters?.linker)\n ? formatters.linker(stepLabels, spec, index)\n : `via ${stepLabels.join(\" > \")}`;\n if (!isNil(linkerText)) {\n trace.push({ type: LINKER_TYPE, label: linkerText, importance: -10 });\n }\n }\n }\n\n if (qualifications !== undefined && qualifications.forQueries !== undefined) {\n for (const [anchorId, qs] of Object.entries(qualifications.forQueries)) {\n if (qs.length === 0) continue;\n const anchorText = isFunction(formatters?.anchorQualification)\n ? formatters.anchorQualification(anchorId as PObjectId, qs, spec, index)\n : `[${anchorId}: ${formatQualifications(qs)}]`;\n if (isNil(anchorText)) continue;\n trace.push({\n type: `${ANCHOR_QUAL_TYPE_PREFIX}${anchorId}`,\n label: anchorText,\n importance: -11,\n });\n }\n if (qualifications.forHit !== undefined && qualifications.forHit.length > 0) {\n const hitText = isFunction(formatters?.hitQualification)\n ? formatters.hitQualification(qualifications.forHit, spec, index)\n : `[${formatQualifications(qualifications.forHit)}]`;\n if (!isNil(hitText)) {\n trace.push({ type: HIT_QUAL_TYPE, label: hitText, importance: -12 });\n }\n }\n }\n\n return { fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats(records: EnrichedRecord[]): TypeStats {\n const importances = new Map<string, number>();\n const countByType = new Map<string, number>();\n\n for (const record of records) {\n for (let i = 0; i < record.fullTrace.length; i++) {\n const { fullType, importance: rawImportance } = record.fullTrace[i];\n const importance = rawImportance ?? 0;\n const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;\n\n countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);\n importances.set(\n fullType,\n Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),\n );\n }\n }\n\n return { importances, countByType };\n}\n\nfunction classifyTypes(\n stats: TypeStats,\n totalRecords: number,\n): { mainTypes: string[]; secondaryTypes: string[] } {\n const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);\n\n const mainTypes: string[] = [];\n const secondaryTypes: string[] = [];\n\n for (const [typeName] of sorted) {\n if (typeName.endsWith(\"@1\") || stats.countByType.get(typeName) === totalRecords)\n mainTypes.push(typeName);\n else secondaryTypes.push(typeName);\n }\n\n return { mainTypes, secondaryTypes };\n}\n\nfunction renderRecordLabel(\n record: EnrichedRecord,\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n): string | undefined {\n const traceParts: string[] = [];\n const anchorParts: string[] = [];\n let linkerLabel: string | undefined;\n let hitLabel: string | undefined;\n\n for (const ft of record.fullTrace) {\n if (!(includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type))) continue;\n if (ft.type === LINKER_TYPE) linkerLabel = ft.label;\n else if (ft.type === HIT_QUAL_TYPE) hitLabel = ft.label;\n else if (isAnchorQualType(ft.type)) anchorParts.push(ft.label);\n else traceParts.push(ft.label);\n }\n\n const isEmpty =\n traceParts.length === 0 &&\n anchorParts.length === 0 &&\n linkerLabel === undefined &&\n hitLabel === undefined;\n\n if (isEmpty) return undefined;\n\n let label = traceParts.join(separator);\n const append = (part: string) => {\n label = label.length === 0 ? part : `${label} ${part}`;\n };\n if (linkerLabel !== undefined) append(linkerLabel);\n for (const a of anchorParts) append(a);\n if (hitLabel !== undefined) append(hitLabel);\n\n return label;\n}\n\nfunction buildLabels(\n records: EnrichedRecord[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): string[] | undefined {\n const result: string[] = [];\n\n for (const r of records) {\n const rendered = renderRecordLabel(r, includedTypes, forceTraceElements, separator);\n if (rendered === undefined) {\n if (!force) return undefined;\n result.push(\"Unlabeled\");\n continue;\n }\n result.push(rendered);\n }\n\n return result;\n}\n\n/**\n * Drop the \"via …\" linker suffix from records whose label is already unique without it.\n *\n * Global minimization may include `LINKER_TYPE_FULL` solely to resolve a collision between a\n * subset of records — but `buildLabels` then renders the suffix on every record that carries a\n * linker trace entry, including ones whose stem is already unique. We strip the suffix where it\n * isn't load-bearing while keeping the symmetric rendering required by `linkerForced` /\n * `forceTraceElements`.\n *\n * Rule: a record's linker suffix is redundant iff its stem (label rendered without LINKER) does\n * not appear anywhere else in the set.\n */\nfunction dropRedundantLinkerSuffix(\n records: EnrichedRecord[],\n globalTypeSet: Set<string>,\n forceTraceElements: Set<string> | undefined,\n forcedSet: Set<string>,\n separator: string,\n labels: string[],\n): string[] {\n if (!globalTypeSet.has(LINKER_TYPE_FULL)) return labels;\n if (forcedSet.has(LINKER_TYPE_FULL) || forceTraceElements?.has(LINKER_TYPE)) return labels;\n\n const setWithoutLinker = new Set(globalTypeSet);\n setWithoutLinker.delete(LINKER_TYPE_FULL);\n\n const stems = records.map((r) =>\n renderRecordLabel(r, setWithoutLinker, forceTraceElements, separator),\n );\n\n const stemOccurrences = new Map<string, number>();\n for (const s of stems) {\n if (s !== undefined) stemOccurrences.set(s, (stemOccurrences.get(s) ?? 0) + 1);\n }\n\n return labels.map((label, i) => {\n const stem = stems[i];\n if (stem === undefined) return label;\n return stemOccurrences.get(stem) === 1 ? stem : label;\n });\n}\n\nfunction countUniqueLabels(result: string[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result).size;\n}\n\nfunction minimizeTypeSet(\n typeSet: Set<string>,\n records: EnrichedRecord[],\n stats: TypeStats,\n forceTraceElements: Set<string> | undefined,\n forcedSet: Set<string>,\n separator: string,\n): Set<string> {\n const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);\n if (initialResult === undefined) return typeSet;\n\n const targetCardinality = countUniqueLabels(initialResult);\n const result = new Set(typeSet);\n\n const removable = [...result]\n .filter((t) => !forceTraceElements?.has(t.split(\"@\")[0]) && !forcedSet.has(t))\n .sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));\n\n for (const typeToRemove of removable) {\n const candidate = new Set(result);\n candidate.delete(typeToRemove);\n const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {\n result.delete(typeToRemove);\n }\n }\n\n return result;\n}\n"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- require("../_virtual/_rolldown/runtime.cjs");
2
1
  let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
3
2
  let es_toolkit = require("es-toolkit");
4
3
  //#region src/labels/derive_distinct_tooltips.ts
@@ -1 +1 @@
1
- {"version":3,"file":"derive_distinct_tooltips.cjs","names":["Annotation"],"sources":["../../src/labels/derive_distinct_tooltips.ts"],"sourcesContent":["import {\n Annotation,\n PObjectId,\n readAnnotation,\n type AxisQualification,\n type PColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport { isNil } from \"es-toolkit\";\nimport type { MatchQualifications, MatchVariant } from \"../columns\";\n\nexport type TooltipEntry = {\n /** Main column spec — used for column-name fallback when no label. */\n spec: PColumnSpec;\n /** Qualifications carried by this variant. */\n qualifications?: MatchQualifications;\n /** Linker steps traversed to reach the hit column. */\n linkerPath?: MatchVariant[\"path\"];\n /** Position of this variant within the same physical column (1-based). */\n variantIndex?: number;\n /** Total variants for the same physical column. */\n variantCount?: number;\n};\n\n/** Format tooltip strings for each entry. Returns `undefined` when nothing useful. */\nexport function deriveDistinctTooltips(entries: TooltipEntry[]): (undefined | string)[] {\n return entries.map(formatTooltip);\n}\n\nfunction formatTooltip(entry: TooltipEntry): undefined | string {\n const sections: string[] = [];\n\n const header = formatHeader(entry);\n if (header !== undefined) sections.push(header);\n\n const origin = formatOriginPath(entry);\n if (origin !== undefined) sections.push(origin);\n\n const anchors = formatAnchors(entry.qualifications);\n if (anchors !== undefined) sections.push(anchors);\n\n const hit = formatHit(entry.qualifications);\n if (hit !== undefined) sections.push(hit);\n\n if (sections.length <= 1) return undefined;\n return sections.join(\"\\n\\n\");\n}\n\nconst BULLET_1 = \" • \";\n\nfunction formatHeader(entry: TooltipEntry): undefined | string {\n const lines: string[] = [];\n if (entry.variantCount !== undefined && entry.variantCount > 1) {\n lines.push(`Variant: ${entry.variantIndex ?? \"?\"} of ${entry.variantCount}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatOriginPath(entry: TooltipEntry): undefined | string {\n const path = entry.linkerPath ?? [];\n if (path.length === 0) return undefined;\n\n const lines = [\"Origin path\"];\n path.forEach((step, i) => {\n const label =\n readAnnotation(step.linker.spec, Annotation.LinkLabel) ??\n readAnnotation(step.linker.spec, Annotation.Label) ??\n step.linker.spec.name;\n lines.push(`${BULLET_1}linker ${i + 1}: ${label}`);\n });\n const hitName = readAnnotation(entry.spec, Annotation.Label) ?? entry.spec.name;\n lines.push(`${BULLET_1}hit column: ${hitName}`);\n return lines.join(\"\\n\");\n}\n\nfunction formatAnchors(q: undefined | MatchQualifications): undefined | string {\n if (isNil(q)) return undefined;\n if (isNil(q.forQueries)) return undefined;\n const ids = Object.keys(q.forQueries);\n if (ids.length === 0) return undefined;\n\n const lines = [];\n for (const id of ids) {\n const item = q.forQueries[id as PObjectId];\n if (item.length === 0) continue;\n const rendered = formatAxisQualifications(item);\n lines.push(`${BULLET_1}${id}${rendered !== undefined ? ` ${rendered}` : \"\"}`);\n }\n return lines.length > 0\n ? [\"Anchors (bound via this variant)\"].concat(lines).join(\"\\n\")\n : undefined;\n}\n\nfunction formatHit(q: undefined | MatchQualifications): undefined | string {\n if (isNil(q) || isNil(q.forHit) || q.forHit.length === 0) return undefined;\n const rendered = formatAxisQualifications(q.forHit);\n if (rendered === undefined) return undefined;\n return [\"Hit column qualifications\", `${BULLET_1}${rendered}`].join(\"\\n\");\n}\n\nfunction formatAxisQualifications(qs: AxisQualification[]): undefined | string {\n if (qs.length === 0) return undefined;\n return qs.map(formatQualification).join(\"; \");\n}\n\nfunction formatQualification(q: AxisQualification): string {\n const axisName = typeof q.axis === \"string\" ? q.axis : (q.axis.name ?? JSON.stringify(q.axis));\n const entries = Object.entries(q.contextDomain);\n if (entries.length === 0) return axisName;\n const kv = entries.map(([k, v]) => `${k}=${v}`).join(\", \");\n return `${axisName} context: ${kv}`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"derive_distinct_tooltips.cjs","names":["Annotation"],"sources":["../../src/labels/derive_distinct_tooltips.ts"],"sourcesContent":["import {\n Annotation,\n PObjectId,\n readAnnotation,\n type AxisQualification,\n type PColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport { isNil } from \"es-toolkit\";\nimport type { MatchQualifications, MatchVariant } from \"../columns\";\n\nexport type TooltipEntry = {\n /** Main column spec — used for column-name fallback when no label. */\n spec: PColumnSpec;\n /** Qualifications carried by this variant. */\n qualifications?: MatchQualifications;\n /** Linker steps traversed to reach the hit column. */\n linkerPath?: MatchVariant[\"path\"];\n /** Position of this variant within the same physical column (1-based). */\n variantIndex?: number;\n /** Total variants for the same physical column. */\n variantCount?: number;\n};\n\n/** Format tooltip strings for each entry. Returns `undefined` when nothing useful. */\nexport function deriveDistinctTooltips(entries: TooltipEntry[]): (undefined | string)[] {\n return entries.map(formatTooltip);\n}\n\nfunction formatTooltip(entry: TooltipEntry): undefined | string {\n const sections: string[] = [];\n\n const header = formatHeader(entry);\n if (header !== undefined) sections.push(header);\n\n const origin = formatOriginPath(entry);\n if (origin !== undefined) sections.push(origin);\n\n const anchors = formatAnchors(entry.qualifications);\n if (anchors !== undefined) sections.push(anchors);\n\n const hit = formatHit(entry.qualifications);\n if (hit !== undefined) sections.push(hit);\n\n if (sections.length <= 1) return undefined;\n return sections.join(\"\\n\\n\");\n}\n\nconst BULLET_1 = \" • \";\n\nfunction formatHeader(entry: TooltipEntry): undefined | string {\n const lines: string[] = [];\n if (entry.variantCount !== undefined && entry.variantCount > 1) {\n lines.push(`Variant: ${entry.variantIndex ?? \"?\"} of ${entry.variantCount}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatOriginPath(entry: TooltipEntry): undefined | string {\n const path = entry.linkerPath ?? [];\n if (path.length === 0) return undefined;\n\n const lines = [\"Origin path\"];\n path.forEach((step, i) => {\n const label =\n readAnnotation(step.linker.spec, Annotation.LinkLabel) ??\n readAnnotation(step.linker.spec, Annotation.Label) ??\n step.linker.spec.name;\n lines.push(`${BULLET_1}linker ${i + 1}: ${label}`);\n });\n const hitName = readAnnotation(entry.spec, Annotation.Label) ?? entry.spec.name;\n lines.push(`${BULLET_1}hit column: ${hitName}`);\n return lines.join(\"\\n\");\n}\n\nfunction formatAnchors(q: undefined | MatchQualifications): undefined | string {\n if (isNil(q)) return undefined;\n if (isNil(q.forQueries)) return undefined;\n const ids = Object.keys(q.forQueries);\n if (ids.length === 0) return undefined;\n\n const lines = [];\n for (const id of ids) {\n const item = q.forQueries[id as PObjectId];\n if (item.length === 0) continue;\n const rendered = formatAxisQualifications(item);\n lines.push(`${BULLET_1}${id}${rendered !== undefined ? ` ${rendered}` : \"\"}`);\n }\n return lines.length > 0\n ? [\"Anchors (bound via this variant)\"].concat(lines).join(\"\\n\")\n : undefined;\n}\n\nfunction formatHit(q: undefined | MatchQualifications): undefined | string {\n if (isNil(q) || isNil(q.forHit) || q.forHit.length === 0) return undefined;\n const rendered = formatAxisQualifications(q.forHit);\n if (rendered === undefined) return undefined;\n return [\"Hit column qualifications\", `${BULLET_1}${rendered}`].join(\"\\n\");\n}\n\nfunction formatAxisQualifications(qs: AxisQualification[]): undefined | string {\n if (qs.length === 0) return undefined;\n return qs.map(formatQualification).join(\"; \");\n}\n\nfunction formatQualification(q: AxisQualification): string {\n const axisName = typeof q.axis === \"string\" ? q.axis : (q.axis.name ?? JSON.stringify(q.axis));\n const entries = Object.entries(q.contextDomain);\n if (entries.length === 0) return axisName;\n const kv = entries.map(([k, v]) => `${k}=${v}`).join(\", \");\n return `${axisName} context: ${kv}`;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"derive_distinct_tooltips.d.ts","names":[],"sources":["../../src/labels/derive_distinct_tooltips.ts"],"mappings":";;;;KAUY,YAAA;wEAEV,IAAA,EAAM,WAAA,EAFI;EAIV,cAAA,GAAiB,mBAAA;EAEjB,UAAA,GAAa,YAAA,UAFI;EAIjB,YAAA,WAFyB;EAIzB,YAAA;AAAA;;iBAIc,sBAAA,CAAuB,OAAA,EAAS,YAAA"}
1
+ {"version":3,"file":"derive_distinct_tooltips.d.ts","names":[],"sources":["../../src/labels/derive_distinct_tooltips.ts"],"mappings":";;;;KAUY,YAAA;wEAEV,IAAA,EAAM,WAAA,EAFI;EAIV,cAAA,GAAiB,mBAAA;EAEjB,UAAA,GAAa,YAAA,UAFI;EAIjB,YAAA,WAFyB;EAIzB,YAAA;AAAA;;iBAIc,sBAAA,CAAuB,OAAuB,EAAd,YAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"derive_distinct_tooltips.js","names":[],"sources":["../../src/labels/derive_distinct_tooltips.ts"],"sourcesContent":["import {\n Annotation,\n PObjectId,\n readAnnotation,\n type AxisQualification,\n type PColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport { isNil } from \"es-toolkit\";\nimport type { MatchQualifications, MatchVariant } from \"../columns\";\n\nexport type TooltipEntry = {\n /** Main column spec — used for column-name fallback when no label. */\n spec: PColumnSpec;\n /** Qualifications carried by this variant. */\n qualifications?: MatchQualifications;\n /** Linker steps traversed to reach the hit column. */\n linkerPath?: MatchVariant[\"path\"];\n /** Position of this variant within the same physical column (1-based). */\n variantIndex?: number;\n /** Total variants for the same physical column. */\n variantCount?: number;\n};\n\n/** Format tooltip strings for each entry. Returns `undefined` when nothing useful. */\nexport function deriveDistinctTooltips(entries: TooltipEntry[]): (undefined | string)[] {\n return entries.map(formatTooltip);\n}\n\nfunction formatTooltip(entry: TooltipEntry): undefined | string {\n const sections: string[] = [];\n\n const header = formatHeader(entry);\n if (header !== undefined) sections.push(header);\n\n const origin = formatOriginPath(entry);\n if (origin !== undefined) sections.push(origin);\n\n const anchors = formatAnchors(entry.qualifications);\n if (anchors !== undefined) sections.push(anchors);\n\n const hit = formatHit(entry.qualifications);\n if (hit !== undefined) sections.push(hit);\n\n if (sections.length <= 1) return undefined;\n return sections.join(\"\\n\\n\");\n}\n\nconst BULLET_1 = \" • \";\n\nfunction formatHeader(entry: TooltipEntry): undefined | string {\n const lines: string[] = [];\n if (entry.variantCount !== undefined && entry.variantCount > 1) {\n lines.push(`Variant: ${entry.variantIndex ?? \"?\"} of ${entry.variantCount}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatOriginPath(entry: TooltipEntry): undefined | string {\n const path = entry.linkerPath ?? [];\n if (path.length === 0) return undefined;\n\n const lines = [\"Origin path\"];\n path.forEach((step, i) => {\n const label =\n readAnnotation(step.linker.spec, Annotation.LinkLabel) ??\n readAnnotation(step.linker.spec, Annotation.Label) ??\n step.linker.spec.name;\n lines.push(`${BULLET_1}linker ${i + 1}: ${label}`);\n });\n const hitName = readAnnotation(entry.spec, Annotation.Label) ?? entry.spec.name;\n lines.push(`${BULLET_1}hit column: ${hitName}`);\n return lines.join(\"\\n\");\n}\n\nfunction formatAnchors(q: undefined | MatchQualifications): undefined | string {\n if (isNil(q)) return undefined;\n if (isNil(q.forQueries)) return undefined;\n const ids = Object.keys(q.forQueries);\n if (ids.length === 0) return undefined;\n\n const lines = [];\n for (const id of ids) {\n const item = q.forQueries[id as PObjectId];\n if (item.length === 0) continue;\n const rendered = formatAxisQualifications(item);\n lines.push(`${BULLET_1}${id}${rendered !== undefined ? ` ${rendered}` : \"\"}`);\n }\n return lines.length > 0\n ? [\"Anchors (bound via this variant)\"].concat(lines).join(\"\\n\")\n : undefined;\n}\n\nfunction formatHit(q: undefined | MatchQualifications): undefined | string {\n if (isNil(q) || isNil(q.forHit) || q.forHit.length === 0) return undefined;\n const rendered = formatAxisQualifications(q.forHit);\n if (rendered === undefined) return undefined;\n return [\"Hit column qualifications\", `${BULLET_1}${rendered}`].join(\"\\n\");\n}\n\nfunction formatAxisQualifications(qs: AxisQualification[]): undefined | string {\n if (qs.length === 0) return undefined;\n return qs.map(formatQualification).join(\"; \");\n}\n\nfunction formatQualification(q: AxisQualification): string {\n const axisName = typeof q.axis === \"string\" ? q.axis : (q.axis.name ?? JSON.stringify(q.axis));\n const entries = Object.entries(q.contextDomain);\n if (entries.length === 0) return axisName;\n const kv = entries.map(([k, v]) => `${k}=${v}`).join(\", \");\n return `${axisName} context: ${kv}`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"derive_distinct_tooltips.js","names":[],"sources":["../../src/labels/derive_distinct_tooltips.ts"],"sourcesContent":["import {\n Annotation,\n PObjectId,\n readAnnotation,\n type AxisQualification,\n type PColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport { isNil } from \"es-toolkit\";\nimport type { MatchQualifications, MatchVariant } from \"../columns\";\n\nexport type TooltipEntry = {\n /** Main column spec — used for column-name fallback when no label. */\n spec: PColumnSpec;\n /** Qualifications carried by this variant. */\n qualifications?: MatchQualifications;\n /** Linker steps traversed to reach the hit column. */\n linkerPath?: MatchVariant[\"path\"];\n /** Position of this variant within the same physical column (1-based). */\n variantIndex?: number;\n /** Total variants for the same physical column. */\n variantCount?: number;\n};\n\n/** Format tooltip strings for each entry. Returns `undefined` when nothing useful. */\nexport function deriveDistinctTooltips(entries: TooltipEntry[]): (undefined | string)[] {\n return entries.map(formatTooltip);\n}\n\nfunction formatTooltip(entry: TooltipEntry): undefined | string {\n const sections: string[] = [];\n\n const header = formatHeader(entry);\n if (header !== undefined) sections.push(header);\n\n const origin = formatOriginPath(entry);\n if (origin !== undefined) sections.push(origin);\n\n const anchors = formatAnchors(entry.qualifications);\n if (anchors !== undefined) sections.push(anchors);\n\n const hit = formatHit(entry.qualifications);\n if (hit !== undefined) sections.push(hit);\n\n if (sections.length <= 1) return undefined;\n return sections.join(\"\\n\\n\");\n}\n\nconst BULLET_1 = \" • \";\n\nfunction formatHeader(entry: TooltipEntry): undefined | string {\n const lines: string[] = [];\n if (entry.variantCount !== undefined && entry.variantCount > 1) {\n lines.push(`Variant: ${entry.variantIndex ?? \"?\"} of ${entry.variantCount}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatOriginPath(entry: TooltipEntry): undefined | string {\n const path = entry.linkerPath ?? [];\n if (path.length === 0) return undefined;\n\n const lines = [\"Origin path\"];\n path.forEach((step, i) => {\n const label =\n readAnnotation(step.linker.spec, Annotation.LinkLabel) ??\n readAnnotation(step.linker.spec, Annotation.Label) ??\n step.linker.spec.name;\n lines.push(`${BULLET_1}linker ${i + 1}: ${label}`);\n });\n const hitName = readAnnotation(entry.spec, Annotation.Label) ?? entry.spec.name;\n lines.push(`${BULLET_1}hit column: ${hitName}`);\n return lines.join(\"\\n\");\n}\n\nfunction formatAnchors(q: undefined | MatchQualifications): undefined | string {\n if (isNil(q)) return undefined;\n if (isNil(q.forQueries)) return undefined;\n const ids = Object.keys(q.forQueries);\n if (ids.length === 0) return undefined;\n\n const lines = [];\n for (const id of ids) {\n const item = q.forQueries[id as PObjectId];\n if (item.length === 0) continue;\n const rendered = formatAxisQualifications(item);\n lines.push(`${BULLET_1}${id}${rendered !== undefined ? ` ${rendered}` : \"\"}`);\n }\n return lines.length > 0\n ? [\"Anchors (bound via this variant)\"].concat(lines).join(\"\\n\")\n : undefined;\n}\n\nfunction formatHit(q: undefined | MatchQualifications): undefined | string {\n if (isNil(q) || isNil(q.forHit) || q.forHit.length === 0) return undefined;\n const rendered = formatAxisQualifications(q.forHit);\n if (rendered === undefined) return undefined;\n return [\"Hit column qualifications\", `${BULLET_1}${rendered}`].join(\"\\n\");\n}\n\nfunction formatAxisQualifications(qs: AxisQualification[]): undefined | string {\n if (qs.length === 0) return undefined;\n return qs.map(formatQualification).join(\"; \");\n}\n\nfunction formatQualification(q: AxisQualification): string {\n const axisName = typeof q.axis === \"string\" ? q.axis : (q.axis.name ?? JSON.stringify(q.axis));\n const entries = Object.entries(q.contextDomain);\n if (entries.length === 0) return axisName;\n const kv = entries.map(([k, v]) => `${k}=${v}`).join(\", \");\n return `${axisName} context: ${kv}`;\n}\n"],"mappings":"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"}
@@ -1,2 +1,4 @@
1
- require("./derive_distinct_labels.cjs");
2
- require("./derive_distinct_tooltips.cjs");
1
+ const require_derive_distinct_labels = require("./derive_distinct_labels.cjs");
2
+ const require_derive_distinct_tooltips = require("./derive_distinct_tooltips.cjs");
3
+ exports.deriveDistinctLabels = require_derive_distinct_labels.deriveDistinctLabels;
4
+ exports.deriveDistinctTooltips = require_derive_distinct_tooltips.deriveDistinctTooltips;
@@ -1,2 +1,3 @@
1
1
  import { DeriveLabelsFormatters, DeriveLabelsOptions, Entry, LinkerStep, Trace, TraceEntry, deriveDistinctLabels } from "./derive_distinct_labels.js";
2
- import { TooltipEntry, deriveDistinctTooltips } from "./derive_distinct_tooltips.js";
2
+ import { TooltipEntry, deriveDistinctTooltips } from "./derive_distinct_tooltips.js";
3
+ export { DeriveLabelsFormatters, DeriveLabelsOptions, Entry, LinkerStep, TooltipEntry, type Trace, type TraceEntry, deriveDistinctLabels, deriveDistinctTooltips };
@@ -1,2 +1,3 @@
1
- import "./derive_distinct_labels.js";
2
- import "./derive_distinct_tooltips.js";
1
+ import { deriveDistinctLabels } from "./derive_distinct_labels.js";
2
+ import { deriveDistinctTooltips } from "./derive_distinct_tooltips.js";
3
+ export { deriveDistinctLabels, deriveDistinctTooltips };
package/dist/package.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "1.79.17";
2
+ var version = "1.79.24";
3
3
  //#endregion
4
4
  Object.defineProperty(exports, "version", {
5
5
  enumerable: true,
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "1.79.17";
2
+ var version = "1.79.24";
3
3
  //#endregion
4
4
  export { version };
5
5
 
package/dist/pframe.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  const require_pframe_upgraders = require("./render/util/pframe_upgraders.cjs");
2
2
  //#region src/pframe.ts
3
3
  var PFrameImpl = class {
4
+ handle;
4
5
  constructor(handle) {
5
6
  this.handle = handle;
6
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pframe.cjs","names":["patchInSetFilters"],"sources":["../src/pframe.ts"],"sourcesContent":["import type {\n CalculateTableDataRequest,\n CalculateTableDataResponse,\n FindColumnsRequest,\n FindColumnsResponse,\n PColumnIdAndSpec,\n PColumnSpec,\n PFrame,\n PFrameHandle,\n PObjectId,\n TableRange,\n UniqueValuesRequest,\n UniqueValuesResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { patchInSetFilters } from \"./render/util/pframe_upgraders\";\n\nexport class PFrameImpl implements PFrame {\n constructor(private readonly handle: PFrameHandle) {}\n\n public async findColumns(request: FindColumnsRequest): Promise<FindColumnsResponse> {\n return await this.getPlatforma().pFrameDriver.findColumns(this.handle, request);\n }\n\n public async getColumnSpec(columnId: PObjectId): Promise<PColumnSpec | null> {\n return await this.getPlatforma().pFrameDriver.getColumnSpec(this.handle, columnId);\n }\n\n public async listColumns(): Promise<PColumnIdAndSpec[]> {\n return await this.getPlatforma().pFrameDriver.listColumns(this.handle);\n }\n\n public async calculateTableData(\n request: CalculateTableDataRequest<PObjectId>,\n range?: TableRange,\n ): Promise<CalculateTableDataResponse> {\n if (!cfgRenderCtx.featureFlags?.pFrameInSetFilterSupport) {\n request = {\n ...request,\n filters: patchInSetFilters(request.filters),\n };\n }\n return await this.getPlatforma().pFrameDriver.calculateTableData(this.handle, request, range);\n }\n\n public async getUniqueValues(request: UniqueValuesRequest): Promise<UniqueValuesResponse> {\n return await this.getPlatforma().pFrameDriver.getUniqueValues(this.handle, request);\n }\n\n private getPlatforma() {\n if (platforma === undefined) {\n throw new Error(\"Platforma instance is not available in the current context.\");\n }\n return platforma;\n }\n}\n"],"mappings":";;AAgBA,IAAa,aAAb,MAA0C;CACxC,YAAY,QAAuC;AAAtB,OAAA,SAAA;;CAE7B,MAAa,YAAY,SAA2D;AAClF,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,YAAY,KAAK,QAAQ,QAAQ;;CAGjF,MAAa,cAAc,UAAkD;AAC3E,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,cAAc,KAAK,QAAQ,SAAS;;CAGpF,MAAa,cAA2C;AACtD,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,YAAY,KAAK,OAAO;;CAGxE,MAAa,mBACX,SACA,OACqC;AACrC,MAAI,CAAC,aAAa,cAAc,yBAC9B,WAAU;GACR,GAAG;GACH,SAASA,yBAAAA,kBAAkB,QAAQ,QAAQ;GAC5C;AAEH,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,mBAAmB,KAAK,QAAQ,SAAS,MAAM;;CAG/F,MAAa,gBAAgB,SAA6D;AACxF,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,gBAAgB,KAAK,QAAQ,QAAQ;;CAGrF,eAAuB;AACrB,MAAI,cAAc,KAAA,EAChB,OAAM,IAAI,MAAM,8DAA8D;AAEhF,SAAO"}
1
+ {"version":3,"file":"pframe.cjs","names":["patchInSetFilters"],"sources":["../src/pframe.ts"],"sourcesContent":["import type {\n CalculateTableDataRequest,\n CalculateTableDataResponse,\n FindColumnsRequest,\n FindColumnsResponse,\n PColumnIdAndSpec,\n PColumnSpec,\n PFrame,\n PFrameHandle,\n PObjectId,\n TableRange,\n UniqueValuesRequest,\n UniqueValuesResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { patchInSetFilters } from \"./render/util/pframe_upgraders\";\n\nexport class PFrameImpl implements PFrame {\n constructor(private readonly handle: PFrameHandle) {}\n\n public async findColumns(request: FindColumnsRequest): Promise<FindColumnsResponse> {\n return await this.getPlatforma().pFrameDriver.findColumns(this.handle, request);\n }\n\n public async getColumnSpec(columnId: PObjectId): Promise<PColumnSpec | null> {\n return await this.getPlatforma().pFrameDriver.getColumnSpec(this.handle, columnId);\n }\n\n public async listColumns(): Promise<PColumnIdAndSpec[]> {\n return await this.getPlatforma().pFrameDriver.listColumns(this.handle);\n }\n\n public async calculateTableData(\n request: CalculateTableDataRequest<PObjectId>,\n range?: TableRange,\n ): Promise<CalculateTableDataResponse> {\n if (!cfgRenderCtx.featureFlags?.pFrameInSetFilterSupport) {\n request = {\n ...request,\n filters: patchInSetFilters(request.filters),\n };\n }\n return await this.getPlatforma().pFrameDriver.calculateTableData(this.handle, request, range);\n }\n\n public async getUniqueValues(request: UniqueValuesRequest): Promise<UniqueValuesResponse> {\n return await this.getPlatforma().pFrameDriver.getUniqueValues(this.handle, request);\n }\n\n private getPlatforma() {\n if (platforma === undefined) {\n throw new Error(\"Platforma instance is not available in the current context.\");\n }\n return platforma;\n }\n}\n"],"mappings":";;AAgBA,IAAa,aAAb,MAA0C;CACX;CAA7B,YAAY,QAAuC;EAAtB,KAAA,SAAA;CAAuB;CAEpD,MAAa,YAAY,SAA2D;EAClF,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,YAAY,KAAK,QAAQ,OAAO;CAChF;CAEA,MAAa,cAAc,UAAkD;EAC3E,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,cAAc,KAAK,QAAQ,QAAQ;CACnF;CAEA,MAAa,cAA2C;EACtD,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,YAAY,KAAK,MAAM;CACvE;CAEA,MAAa,mBACX,SACA,OACqC;EACrC,IAAI,CAAC,aAAa,cAAc,0BAC9B,UAAU;GACR,GAAG;GACH,SAASA,yBAAAA,kBAAkB,QAAQ,OAAO;EAC5C;EAEF,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,mBAAmB,KAAK,QAAQ,SAAS,KAAK;CAC9F;CAEA,MAAa,gBAAgB,SAA6D;EACxF,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,gBAAgB,KAAK,QAAQ,OAAO;CACpF;CAEA,eAAuB;EACrB,IAAI,cAAc,KAAA,GAChB,MAAM,IAAI,MAAM,6DAA6D;EAE/E,OAAO;CACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"pframe.d.ts","names":[],"sources":["../src/pframe.ts"],"mappings":";;;cAgBa,UAAA,YAAsB,MAAA;EAAA,iBACJ,MAAA;cAAA,MAAA,EAAQ,YAAA;EAExB,WAAA,CAAY,OAAA,EAAS,kBAAA,GAAqB,OAAA,CAAQ,mBAAA;EAIlD,aAAA,CAAc,QAAA,EAAU,SAAA,GAAY,OAAA,CAAQ,WAAA;EAI5C,WAAA,CAAA,GAAe,OAAA,CAAQ,gBAAA;EAIvB,kBAAA,CACX,OAAA,EAAS,yBAAA,CAA0B,SAAA,GACnC,KAAA,GAAQ,UAAA,GACP,OAAA,CAAQ,0BAAA;EAUE,eAAA,CAAgB,OAAA,EAAS,mBAAA,GAAsB,OAAA,CAAQ,oBAAA;EAAA,QAI5D,YAAA;AAAA"}
1
+ {"version":3,"file":"pframe.d.ts","names":[],"sources":["../src/pframe.ts"],"mappings":";;;cAgBa,UAAA,YAAsB,MAAA;EAAA,iBACJ,MAAA;cAAA,MAAA,EAAQ,YAAA;EAExB,WAAA,CAAY,OAAA,EAAS,kBAAA,GAAqB,OAAA,CAAQ,mBAAA;EAIlD,aAAA,CAAc,QAAA,EAAU,SAAA,GAAY,OAAA,CAAQ,WAAA;EAI5C,WAAA,IAAe,OAAA,CAAQ,gBAAA;EAIvB,kBAAA,CACX,OAAA,EAAS,yBAAA,CAA0B,SAAA,GACnC,KAAA,GAAQ,UAAA,GACP,OAAA,CAAQ,0BAAA;EAUE,eAAA,CAAgB,OAAA,EAAS,mBAAA,GAAsB,OAAA,CAAQ,oBAAA;EAAA,QAI5D,YAAA;AAAA"}
package/dist/pframe.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { patchInSetFilters } from "./render/util/pframe_upgraders.js";
2
2
  //#region src/pframe.ts
3
3
  var PFrameImpl = class {
4
+ handle;
4
5
  constructor(handle) {
5
6
  this.handle = handle;
6
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pframe.js","names":[],"sources":["../src/pframe.ts"],"sourcesContent":["import type {\n CalculateTableDataRequest,\n CalculateTableDataResponse,\n FindColumnsRequest,\n FindColumnsResponse,\n PColumnIdAndSpec,\n PColumnSpec,\n PFrame,\n PFrameHandle,\n PObjectId,\n TableRange,\n UniqueValuesRequest,\n UniqueValuesResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { patchInSetFilters } from \"./render/util/pframe_upgraders\";\n\nexport class PFrameImpl implements PFrame {\n constructor(private readonly handle: PFrameHandle) {}\n\n public async findColumns(request: FindColumnsRequest): Promise<FindColumnsResponse> {\n return await this.getPlatforma().pFrameDriver.findColumns(this.handle, request);\n }\n\n public async getColumnSpec(columnId: PObjectId): Promise<PColumnSpec | null> {\n return await this.getPlatforma().pFrameDriver.getColumnSpec(this.handle, columnId);\n }\n\n public async listColumns(): Promise<PColumnIdAndSpec[]> {\n return await this.getPlatforma().pFrameDriver.listColumns(this.handle);\n }\n\n public async calculateTableData(\n request: CalculateTableDataRequest<PObjectId>,\n range?: TableRange,\n ): Promise<CalculateTableDataResponse> {\n if (!cfgRenderCtx.featureFlags?.pFrameInSetFilterSupport) {\n request = {\n ...request,\n filters: patchInSetFilters(request.filters),\n };\n }\n return await this.getPlatforma().pFrameDriver.calculateTableData(this.handle, request, range);\n }\n\n public async getUniqueValues(request: UniqueValuesRequest): Promise<UniqueValuesResponse> {\n return await this.getPlatforma().pFrameDriver.getUniqueValues(this.handle, request);\n }\n\n private getPlatforma() {\n if (platforma === undefined) {\n throw new Error(\"Platforma instance is not available in the current context.\");\n }\n return platforma;\n }\n}\n"],"mappings":";;AAgBA,IAAa,aAAb,MAA0C;CACxC,YAAY,QAAuC;AAAtB,OAAA,SAAA;;CAE7B,MAAa,YAAY,SAA2D;AAClF,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,YAAY,KAAK,QAAQ,QAAQ;;CAGjF,MAAa,cAAc,UAAkD;AAC3E,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,cAAc,KAAK,QAAQ,SAAS;;CAGpF,MAAa,cAA2C;AACtD,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,YAAY,KAAK,OAAO;;CAGxE,MAAa,mBACX,SACA,OACqC;AACrC,MAAI,CAAC,aAAa,cAAc,yBAC9B,WAAU;GACR,GAAG;GACH,SAAS,kBAAkB,QAAQ,QAAQ;GAC5C;AAEH,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,mBAAmB,KAAK,QAAQ,SAAS,MAAM;;CAG/F,MAAa,gBAAgB,SAA6D;AACxF,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,gBAAgB,KAAK,QAAQ,QAAQ;;CAGrF,eAAuB;AACrB,MAAI,cAAc,KAAA,EAChB,OAAM,IAAI,MAAM,8DAA8D;AAEhF,SAAO"}
1
+ {"version":3,"file":"pframe.js","names":[],"sources":["../src/pframe.ts"],"sourcesContent":["import type {\n CalculateTableDataRequest,\n CalculateTableDataResponse,\n FindColumnsRequest,\n FindColumnsResponse,\n PColumnIdAndSpec,\n PColumnSpec,\n PFrame,\n PFrameHandle,\n PObjectId,\n TableRange,\n UniqueValuesRequest,\n UniqueValuesResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { patchInSetFilters } from \"./render/util/pframe_upgraders\";\n\nexport class PFrameImpl implements PFrame {\n constructor(private readonly handle: PFrameHandle) {}\n\n public async findColumns(request: FindColumnsRequest): Promise<FindColumnsResponse> {\n return await this.getPlatforma().pFrameDriver.findColumns(this.handle, request);\n }\n\n public async getColumnSpec(columnId: PObjectId): Promise<PColumnSpec | null> {\n return await this.getPlatforma().pFrameDriver.getColumnSpec(this.handle, columnId);\n }\n\n public async listColumns(): Promise<PColumnIdAndSpec[]> {\n return await this.getPlatforma().pFrameDriver.listColumns(this.handle);\n }\n\n public async calculateTableData(\n request: CalculateTableDataRequest<PObjectId>,\n range?: TableRange,\n ): Promise<CalculateTableDataResponse> {\n if (!cfgRenderCtx.featureFlags?.pFrameInSetFilterSupport) {\n request = {\n ...request,\n filters: patchInSetFilters(request.filters),\n };\n }\n return await this.getPlatforma().pFrameDriver.calculateTableData(this.handle, request, range);\n }\n\n public async getUniqueValues(request: UniqueValuesRequest): Promise<UniqueValuesResponse> {\n return await this.getPlatforma().pFrameDriver.getUniqueValues(this.handle, request);\n }\n\n private getPlatforma() {\n if (platforma === undefined) {\n throw new Error(\"Platforma instance is not available in the current context.\");\n }\n return platforma;\n }\n}\n"],"mappings":";;AAgBA,IAAa,aAAb,MAA0C;CACX;CAA7B,YAAY,QAAuC;EAAtB,KAAA,SAAA;CAAuB;CAEpD,MAAa,YAAY,SAA2D;EAClF,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,YAAY,KAAK,QAAQ,OAAO;CAChF;CAEA,MAAa,cAAc,UAAkD;EAC3E,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,cAAc,KAAK,QAAQ,QAAQ;CACnF;CAEA,MAAa,cAA2C;EACtD,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,YAAY,KAAK,MAAM;CACvE;CAEA,MAAa,mBACX,SACA,OACqC;EACrC,IAAI,CAAC,aAAa,cAAc,0BAC9B,UAAU;GACR,GAAG;GACH,SAAS,kBAAkB,QAAQ,OAAO;EAC5C;EAEF,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,mBAAmB,KAAK,QAAQ,SAAS,KAAK;CAC9F;CAEA,MAAa,gBAAgB,SAA6D;EACxF,OAAO,MAAM,KAAK,aAAa,CAAC,CAAC,aAAa,gBAAgB,KAAK,QAAQ,OAAO;CACpF;CAEA,eAAuB;EACrB,IAAI,cAAc,KAAA,GAChB,MAAM,IAAI,MAAM,6DAA6D;EAE/E,OAAO;CACT;AACF"}
@@ -1,4 +1,3 @@
1
- require("../_virtual/_rolldown/runtime.cjs");
2
1
  let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
3
2
  //#region src/pframe_utils/axes.ts
4
3
  /** Create id for column copy with added keys in axes domains */
@@ -1 +1 @@
1
- {"version":3,"file":"axes.cjs","names":["LinkerMap","getColumnIdAndSpec","getAxisId","Annotation"],"sources":["../../src/pframe_utils/axes.ts"],"sourcesContent":["/**\n * Axes utilities for PFrame graph operations.\n *\n * Extracted from PFrameForGraphs to break circular dependency\n * between PFrameForGraphs and columns modules.\n *\n * @module pframe_utils/axes\n */\n\nimport type {\n AxisId,\n AxisSpecNormalized,\n CanonicalizedJson,\n PColumn,\n PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n LinkerMap,\n matchAxisId,\n readAnnotation,\n stringifyJson,\n} from \"@milaboratories/pl-model-common\";\nimport type { PColumnDataUniversal } from \"../render\";\n\nexport type AxesVault = Map<CanonicalizedJson<AxisId>, AxisSpecNormalized>;\n\n/** Create id for column copy with added keys in axes domains */\nconst colId = (\n id: PObjectId,\n domains: (Record<string, string> | undefined)[],\n contextDomains: (Record<string, string> | undefined)[],\n) => {\n let wid = id.toString();\n domains?.forEach((domain) => {\n if (domain) {\n for (const [k, v] of Object.entries(domain)) {\n wid += k;\n wid += v;\n }\n }\n });\n contextDomains?.forEach((contextDomain) => {\n if (contextDomain) {\n for (const [k, v] of Object.entries(contextDomain)) {\n wid += k;\n wid += v;\n }\n }\n });\n return wid;\n};\n\n/** All combinations with 1 key from each list */\nfunction getKeysCombinations(idsLists: AxisId[][]) {\n if (!idsLists.length) {\n return [];\n }\n let result: AxisId[][] = [[]];\n idsLists.forEach((list) => {\n const nextResult: AxisId[][] = [];\n list.forEach((key) => {\n nextResult.push(...result.map((resultItem) => [...resultItem, key]));\n });\n result = nextResult;\n });\n return result;\n}\n\nexport function getAvailableWithLinkersAxes(\n linkerColumns: PColumn<PColumnDataUniversal>[],\n blockAxes: AxesVault,\n): AxesVault {\n const linkerMap = LinkerMap.fromColumns(linkerColumns.map(getColumnIdAndSpec));\n const availableAxes = linkerMap.getReachableByLinkersAxesFromAxesNormalized(\n [...blockAxes.values()],\n (linkerKeyId, sourceAxisId) => matchAxisId(sourceAxisId, linkerKeyId),\n );\n\n return new Map(\n availableAxes.map((axisSpec) => {\n const id = getAxisId(axisSpec);\n return [canonicalizeJson(id), axisSpec];\n }),\n );\n}\n\n/** Add columns with fully compatible axes created from partial compatible ones */\nexport function enrichCompatible<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n columns: T[],\n): T[] {\n return columns.flatMap((column) => getAdditionalColumnsForColumn(blockAxes, column));\n}\n\nfunction getAdditionalColumnsForColumn<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n column: T,\n): T[] {\n const columnAxesIds = column.spec.axesSpec.map(getAxisId);\n\n if (columnAxesIds.every((id) => blockAxes.has(canonicalizeJson(id)))) {\n return [column]; // the column is compatible with its own domains without modifications\n }\n\n // options with different possible domains for every axis of secondary column\n const secondaryIdsOptions = columnAxesIds.map((id) => {\n const result = [];\n for (const [_, mainId] of blockAxes) {\n if (matchAxisId(mainId, id) && !matchAxisId(id, mainId)) {\n result.push(mainId);\n }\n }\n return result;\n });\n // all possible combinations of axes with added domains\n const secondaryIdsVariants = getKeysCombinations(secondaryIdsOptions);\n\n // sets of added to column domain fields\n const allAddedDomainValues = new Set<string>();\n const addedNotToAllVariantsDomainValues = new Set<string>();\n const addedByVariantsDomainValues = secondaryIdsVariants.map((idsList) => {\n const addedSet = new Set<string>();\n idsList.map((axisId, idx) => {\n const d1 = column.spec.axesSpec[idx].domain;\n const d2 = axisId.domain;\n Object.entries(d2 ?? {}).forEach(([key, value]) => {\n if (d1?.[key] === undefined) {\n const item = JSON.stringify([key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n const cd1 = column.spec.axesSpec[idx].contextDomain;\n const cd2 = axisId.contextDomain;\n Object.entries(cd2 ?? {}).forEach(([key, value]) => {\n if (cd1?.[key] === undefined) {\n const item = JSON.stringify([\"ctx:\" + key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n return {\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n };\n });\n return addedSet;\n });\n [...allAddedDomainValues].forEach((addedPart) => {\n if (addedByVariantsDomainValues.some((s) => !s.has(addedPart))) {\n addedNotToAllVariantsDomainValues.add(addedPart);\n }\n });\n\n const additionalColumns = secondaryIdsVariants.map((idsList, idx) => {\n const id = colId(\n column.id,\n idsList.map((id) => id.domain),\n idsList.map((id) => id.contextDomain),\n );\n\n const label = readAnnotation(column.spec, Annotation.Label) ?? \"\";\n const labelDomainPart = [...addedByVariantsDomainValues[idx]]\n .filter((str) => addedNotToAllVariantsDomainValues.has(str))\n .sort()\n .map((v) => JSON.parse(v)?.[1]) // use in labels only domain values, but sort them by key to save the same order in all column variants\n .join(\" / \");\n\n const annotations: Annotation = {\n ...column.spec.annotations,\n [Annotation.Graph.IsVirtual]: stringifyJson(true),\n };\n if (label || labelDomainPart) {\n annotations[Annotation.Label] =\n label && labelDomainPart ? label + \" / \" + labelDomainPart : label + labelDomainPart;\n }\n\n return {\n ...column,\n id: id as PObjectId,\n spec: {\n ...column.spec,\n axesSpec: idsList.map((axisId, idx) => ({\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n })),\n annotations,\n },\n };\n });\n\n return [column, ...additionalColumns];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"axes.cjs","names":["LinkerMap","getColumnIdAndSpec","getAxisId","Annotation"],"sources":["../../src/pframe_utils/axes.ts"],"sourcesContent":["/**\n * Axes utilities for PFrame graph operations.\n *\n * Extracted from PFrameForGraphs to break circular dependency\n * between PFrameForGraphs and columns modules.\n *\n * @module pframe_utils/axes\n */\n\nimport type {\n AxisId,\n AxisSpecNormalized,\n CanonicalizedJson,\n PColumn,\n PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n LinkerMap,\n matchAxisId,\n readAnnotation,\n stringifyJson,\n} from \"@milaboratories/pl-model-common\";\nimport type { PColumnDataUniversal } from \"../render\";\n\nexport type AxesVault = Map<CanonicalizedJson<AxisId>, AxisSpecNormalized>;\n\n/** Create id for column copy with added keys in axes domains */\nconst colId = (\n id: PObjectId,\n domains: (Record<string, string> | undefined)[],\n contextDomains: (Record<string, string> | undefined)[],\n) => {\n let wid = id.toString();\n domains?.forEach((domain) => {\n if (domain) {\n for (const [k, v] of Object.entries(domain)) {\n wid += k;\n wid += v;\n }\n }\n });\n contextDomains?.forEach((contextDomain) => {\n if (contextDomain) {\n for (const [k, v] of Object.entries(contextDomain)) {\n wid += k;\n wid += v;\n }\n }\n });\n return wid;\n};\n\n/** All combinations with 1 key from each list */\nfunction getKeysCombinations(idsLists: AxisId[][]) {\n if (!idsLists.length) {\n return [];\n }\n let result: AxisId[][] = [[]];\n idsLists.forEach((list) => {\n const nextResult: AxisId[][] = [];\n list.forEach((key) => {\n nextResult.push(...result.map((resultItem) => [...resultItem, key]));\n });\n result = nextResult;\n });\n return result;\n}\n\nexport function getAvailableWithLinkersAxes(\n linkerColumns: PColumn<PColumnDataUniversal>[],\n blockAxes: AxesVault,\n): AxesVault {\n const linkerMap = LinkerMap.fromColumns(linkerColumns.map(getColumnIdAndSpec));\n const availableAxes = linkerMap.getReachableByLinkersAxesFromAxesNormalized(\n [...blockAxes.values()],\n (linkerKeyId, sourceAxisId) => matchAxisId(sourceAxisId, linkerKeyId),\n );\n\n return new Map(\n availableAxes.map((axisSpec) => {\n const id = getAxisId(axisSpec);\n return [canonicalizeJson(id), axisSpec];\n }),\n );\n}\n\n/** Add columns with fully compatible axes created from partial compatible ones */\nexport function enrichCompatible<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n columns: T[],\n): T[] {\n return columns.flatMap((column) => getAdditionalColumnsForColumn(blockAxes, column));\n}\n\nfunction getAdditionalColumnsForColumn<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n column: T,\n): T[] {\n const columnAxesIds = column.spec.axesSpec.map(getAxisId);\n\n if (columnAxesIds.every((id) => blockAxes.has(canonicalizeJson(id)))) {\n return [column]; // the column is compatible with its own domains without modifications\n }\n\n // options with different possible domains for every axis of secondary column\n const secondaryIdsOptions = columnAxesIds.map((id) => {\n const result = [];\n for (const [_, mainId] of blockAxes) {\n if (matchAxisId(mainId, id) && !matchAxisId(id, mainId)) {\n result.push(mainId);\n }\n }\n return result;\n });\n // all possible combinations of axes with added domains\n const secondaryIdsVariants = getKeysCombinations(secondaryIdsOptions);\n\n // sets of added to column domain fields\n const allAddedDomainValues = new Set<string>();\n const addedNotToAllVariantsDomainValues = new Set<string>();\n const addedByVariantsDomainValues = secondaryIdsVariants.map((idsList) => {\n const addedSet = new Set<string>();\n idsList.map((axisId, idx) => {\n const d1 = column.spec.axesSpec[idx].domain;\n const d2 = axisId.domain;\n Object.entries(d2 ?? {}).forEach(([key, value]) => {\n if (d1?.[key] === undefined) {\n const item = JSON.stringify([key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n const cd1 = column.spec.axesSpec[idx].contextDomain;\n const cd2 = axisId.contextDomain;\n Object.entries(cd2 ?? {}).forEach(([key, value]) => {\n if (cd1?.[key] === undefined) {\n const item = JSON.stringify([\"ctx:\" + key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n return {\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n };\n });\n return addedSet;\n });\n [...allAddedDomainValues].forEach((addedPart) => {\n if (addedByVariantsDomainValues.some((s) => !s.has(addedPart))) {\n addedNotToAllVariantsDomainValues.add(addedPart);\n }\n });\n\n const additionalColumns = secondaryIdsVariants.map((idsList, idx) => {\n const id = colId(\n column.id,\n idsList.map((id) => id.domain),\n idsList.map((id) => id.contextDomain),\n );\n\n const label = readAnnotation(column.spec, Annotation.Label) ?? \"\";\n const labelDomainPart = [...addedByVariantsDomainValues[idx]]\n .filter((str) => addedNotToAllVariantsDomainValues.has(str))\n .sort()\n .map((v) => JSON.parse(v)?.[1]) // use in labels only domain values, but sort them by key to save the same order in all column variants\n .join(\" / \");\n\n const annotations: Annotation = {\n ...column.spec.annotations,\n [Annotation.Graph.IsVirtual]: stringifyJson(true),\n };\n if (label || labelDomainPart) {\n annotations[Annotation.Label] =\n label && labelDomainPart ? label + \" / \" + labelDomainPart : label + labelDomainPart;\n }\n\n return {\n ...column,\n id: id as PObjectId,\n spec: {\n ...column.spec,\n axesSpec: idsList.map((axisId, idx) => ({\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n })),\n annotations,\n },\n };\n });\n\n return [column, ...additionalColumns];\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"axes.d.ts","names":[],"sources":["../../src/pframe_utils/axes.ts"],"mappings":";;;;KA4BY,SAAA,GAAY,GAAA,CAAI,iBAAA,CAAkB,MAAA,GAAS,kBAAA;AAAA,iBA4CvC,2BAAA,CACd,aAAA,EAAe,OAAA,CAAQ,oBAAA,KACvB,SAAA,EAAW,SAAA,GACV,SAAA;;iBAgBa,gBAAA,WAA2B,IAAA,CAAK,OAAA,CAAQ,oBAAA,WAAA,CACtD,SAAA,EAAW,SAAA,EACX,OAAA,EAAS,CAAA,KACR,CAAA"}
1
+ {"version":3,"file":"axes.d.ts","names":[],"sources":["../../src/pframe_utils/axes.ts"],"mappings":";;;;KA4BY,SAAA,GAAY,GAAA,CAAI,iBAAA,CAAkB,MAAA,GAAS,kBAAA;AAAA,iBA4CvC,2BAAA,CACd,aAAA,EAAe,OAAA,CAAQ,oBAAA,KACvB,SAAA,EAAW,SAAA,GACV,SAAA;;iBAgBa,gBAAA,WAA2B,IAAA,CAAK,OAAA,CAAQ,oBAAA,YACtD,SAAA,EAAW,SAAA,EACX,OAAA,EAAS,CAAA,KACR,CAAA"}