@platforma-sdk/model 1.63.12 → 1.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/dist/columns/column_collection_builder.cjs +105 -92
  2. package/dist/columns/column_collection_builder.cjs.map +1 -1
  3. package/dist/columns/column_collection_builder.d.ts +13 -12
  4. package/dist/columns/column_collection_builder.d.ts.map +1 -1
  5. package/dist/columns/column_collection_builder.js +107 -94
  6. package/dist/columns/column_collection_builder.js.map +1 -1
  7. package/dist/columns/column_selector.cjs +8 -80
  8. package/dist/columns/column_selector.cjs.map +1 -1
  9. package/dist/columns/column_selector.d.ts +6 -14
  10. package/dist/columns/column_selector.d.ts.map +1 -1
  11. package/dist/columns/column_selector.js +6 -77
  12. package/dist/columns/column_selector.js.map +1 -1
  13. package/dist/columns/column_snapshot.cjs +3 -3
  14. package/dist/columns/column_snapshot.cjs.map +1 -1
  15. package/dist/columns/column_snapshot.d.ts +3 -3
  16. package/dist/columns/column_snapshot.d.ts.map +1 -1
  17. package/dist/columns/column_snapshot.js +3 -3
  18. package/dist/columns/column_snapshot.js.map +1 -1
  19. package/dist/columns/column_snapshot_provider.cjs +1 -1
  20. package/dist/columns/column_snapshot_provider.cjs.map +1 -1
  21. package/dist/columns/column_snapshot_provider.d.ts +8 -8
  22. package/dist/columns/column_snapshot_provider.d.ts.map +1 -1
  23. package/dist/columns/column_snapshot_provider.js +1 -1
  24. package/dist/columns/column_snapshot_provider.js.map +1 -1
  25. package/dist/columns/ctx_column_sources.cjs.map +1 -1
  26. package/dist/columns/ctx_column_sources.d.ts +2 -1
  27. package/dist/columns/ctx_column_sources.d.ts.map +1 -1
  28. package/dist/columns/ctx_column_sources.js.map +1 -1
  29. package/dist/columns/expand_by_partition.cjs +106 -0
  30. package/dist/columns/expand_by_partition.cjs.map +1 -0
  31. package/dist/columns/expand_by_partition.d.ts +33 -0
  32. package/dist/columns/expand_by_partition.d.ts.map +1 -0
  33. package/dist/columns/expand_by_partition.js +105 -0
  34. package/dist/columns/expand_by_partition.js.map +1 -0
  35. package/dist/columns/index.cjs +1 -0
  36. package/dist/columns/index.d.ts +4 -3
  37. package/dist/columns/index.js +1 -0
  38. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +26 -0
  39. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -0
  40. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js +25 -0
  41. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -0
  42. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs +68 -0
  43. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs.map +1 -0
  44. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js +67 -0
  45. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js.map +1 -0
  46. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +27 -17
  47. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
  48. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +4 -0
  49. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts.map +1 -1
  50. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +28 -18
  51. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
  52. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +258 -175
  53. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  54. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +37 -21
  55. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -1
  56. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +261 -175
  57. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  58. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +64 -0
  59. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -0
  60. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts +17 -0
  61. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts.map +1 -0
  62. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +63 -0
  63. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -0
  64. package/dist/components/PlDataTable/createPlDataTable/index.cjs +2 -1
  65. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
  66. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -1
  67. package/dist/components/PlDataTable/createPlDataTable/index.d.ts.map +1 -1
  68. package/dist/components/PlDataTable/createPlDataTable/index.js +2 -1
  69. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
  70. package/dist/components/PlDataTable/createPlDataTable/utils.cjs +109 -0
  71. package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -0
  72. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts +19 -0
  73. package/dist/components/PlDataTable/createPlDataTable/utils.d.ts.map +1 -0
  74. package/dist/components/PlDataTable/createPlDataTable/utils.js +102 -0
  75. package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -0
  76. package/dist/components/PlDataTable/index.cjs +3 -1
  77. package/dist/components/PlDataTable/index.d.ts +5 -3
  78. package/dist/components/PlDataTable/index.js +3 -1
  79. package/dist/components/PlDataTable/labels.cjs +25 -11
  80. package/dist/components/PlDataTable/labels.cjs.map +1 -1
  81. package/dist/components/PlDataTable/labels.js +25 -11
  82. package/dist/components/PlDataTable/labels.js.map +1 -1
  83. package/dist/components/PlDataTable/state-migration.cjs +8 -2
  84. package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
  85. package/dist/components/PlDataTable/state-migration.d.ts.map +1 -1
  86. package/dist/components/PlDataTable/state-migration.js +8 -2
  87. package/dist/components/PlDataTable/state-migration.js.map +1 -1
  88. package/dist/components/PlDataTable/typesV5.d.ts +23 -15
  89. package/dist/components/PlDataTable/typesV5.d.ts.map +1 -1
  90. package/dist/components/index.cjs +3 -1
  91. package/dist/components/index.d.ts +4 -2
  92. package/dist/components/index.js +3 -1
  93. package/dist/index.cjs +13 -9
  94. package/dist/index.d.ts +9 -7
  95. package/dist/index.js +6 -4
  96. package/dist/labels/derive_distinct_labels.cjs +39 -27
  97. package/dist/labels/derive_distinct_labels.cjs.map +1 -1
  98. package/dist/labels/derive_distinct_labels.d.ts +15 -15
  99. package/dist/labels/derive_distinct_labels.d.ts.map +1 -1
  100. package/dist/labels/derive_distinct_labels.js +39 -27
  101. package/dist/labels/derive_distinct_labels.js.map +1 -1
  102. package/dist/labels/index.cjs +0 -1
  103. package/dist/labels/index.d.ts +1 -2
  104. package/dist/labels/index.js +0 -1
  105. package/dist/package.cjs +1 -1
  106. package/dist/package.js +1 -1
  107. package/dist/render/api.cjs +10 -3
  108. package/dist/render/api.cjs.map +1 -1
  109. package/dist/render/api.d.ts +2 -2
  110. package/dist/render/api.d.ts.map +1 -1
  111. package/dist/render/api.js +10 -3
  112. package/dist/render/api.js.map +1 -1
  113. package/dist/render/util/column_collection.cjs +3 -3
  114. package/dist/render/util/column_collection.cjs.map +1 -1
  115. package/dist/render/util/column_collection.d.ts.map +1 -1
  116. package/dist/render/util/column_collection.js +3 -3
  117. package/dist/render/util/column_collection.js.map +1 -1
  118. package/dist/render/util/label.cjs +2 -2
  119. package/dist/render/util/label.cjs.map +1 -1
  120. package/dist/render/util/label.js +2 -2
  121. package/dist/render/util/label.js.map +1 -1
  122. package/dist/render/util/pcolumn_data.cjs.map +1 -1
  123. package/dist/render/util/pcolumn_data.d.ts +2 -2
  124. package/dist/render/util/pcolumn_data.d.ts.map +1 -1
  125. package/dist/render/util/pcolumn_data.js.map +1 -1
  126. package/package.json +7 -7
  127. package/src/columns/column_collection_builder.test.ts +40 -27
  128. package/src/columns/column_collection_builder.ts +176 -131
  129. package/src/columns/column_selector.test.ts +17 -399
  130. package/src/columns/column_selector.ts +14 -127
  131. package/src/columns/column_snapshot.ts +5 -5
  132. package/src/columns/column_snapshot_provider.ts +11 -10
  133. package/src/columns/ctx_column_sources.ts +2 -2
  134. package/src/columns/expand_by_partition.test.ts +4 -4
  135. package/src/columns/expand_by_partition.ts +4 -3
  136. package/src/columns/index.ts +1 -0
  137. package/src/components/PlDataTable/createPlDataTable/createPTableDefV2.ts +42 -0
  138. package/src/components/PlDataTable/createPlDataTable/createPTableDefV3.ts +89 -0
  139. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +51 -19
  140. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +500 -313
  141. package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +122 -0
  142. package/src/components/PlDataTable/createPlDataTable/index.ts +4 -2
  143. package/src/components/PlDataTable/createPlDataTable/utils.test.ts +257 -0
  144. package/src/components/PlDataTable/createPlDataTable/utils.ts +160 -0
  145. package/src/components/PlDataTable/index.ts +15 -2
  146. package/src/components/PlDataTable/labels.ts +29 -18
  147. package/src/components/PlDataTable/state-migration.ts +6 -1
  148. package/src/components/PlDataTable/typesV5.ts +25 -12
  149. package/src/labels/derive_distinct_labels.test.ts +143 -45
  150. package/src/labels/derive_distinct_labels.ts +102 -49
  151. package/src/labels/index.ts +0 -1
  152. package/src/render/api.ts +15 -5
  153. package/src/render/util/column_collection.ts +4 -3
  154. package/src/render/util/label.ts +2 -2
  155. package/src/render/util/pcolumn_data.ts +5 -3
  156. package/dist/labels/write_labels_to_specs.cjs +0 -14
  157. package/dist/labels/write_labels_to_specs.cjs.map +0 -1
  158. package/dist/labels/write_labels_to_specs.d.ts +0 -7
  159. package/dist/labels/write_labels_to_specs.d.ts.map +0 -1
  160. package/dist/labels/write_labels_to_specs.js +0 -13
  161. package/dist/labels/write_labels_to_specs.js.map +0 -1
  162. package/src/labels/write_labels_to_specs.ts +0 -12
@@ -4,6 +4,8 @@ const require_column_snapshot = require("./column_snapshot.cjs");
4
4
  const require_column_snapshot_provider = require("./column_snapshot_provider.cjs");
5
5
  const require_column_selector = require("./column_selector.cjs");
6
6
  let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
7
+ let _milaboratories_helpers = require("@milaboratories/helpers");
8
+ let es_toolkit = require("es-toolkit");
7
9
  //#region src/columns/column_collection_builder.ts
8
10
  /**
9
11
  * Mutable builder that accumulates column sources, then produces
@@ -35,58 +37,22 @@ var ColumnCollectionBuilder = class {
35
37
  }
36
38
  build(options) {
37
39
  const allowPartial = options?.allowPartialColumnList === true;
38
- const hasAnchors = options !== void 0 && "anchors" in options;
39
- const allComplete = this.providers.every((p) => p.isColumnListComplete());
40
- if (!allComplete && !allowPartial) return void 0;
41
- const columnMap = this.collectColumns();
42
- if (hasAnchors) {
43
- const anchorSpecs = resolveAnchorSpecs(options.anchors, columnMap);
44
- const idDeriver = new _milaboratories_pl_model_common.AnchoredIdDeriver(anchorSpecs);
45
- return new AnchoredColumnCollectionImpl(this.specDriver, {
46
- columns: columnMap,
47
- idDeriver,
48
- anchorSpecs,
49
- columnListComplete: allowPartial ? allComplete : false
50
- });
51
- } else return new ColumnCollectionImpl(this.specDriver, {
52
- columns: columnMap,
53
- columnListComplete: allowPartial ? allComplete : false
40
+ if (!this.providers.every((p) => p.isColumnListComplete()) && !allowPartial) return void 0;
41
+ const columns = collectColumns(this.providers);
42
+ if (options !== void 0 && "anchors" in options) return new AnchoredColumnCollectionImpl(this.specDriver, {
43
+ anchors: options.anchors,
44
+ columns
54
45
  });
46
+ else return new ColumnCollectionImpl(this.specDriver, { columns });
55
47
  }
56
- /**
57
- * Collect all columns from all providers, dedup by NativePObjectId.
58
- * First source wins.
59
- */
60
- collectColumns() {
61
- const seen = /* @__PURE__ */ new Set();
62
- const result = /* @__PURE__ */ new Map();
63
- for (const provider of this.providers) {
64
- const columns = provider.getAllColumns();
65
- for (const col of columns) {
66
- const nativeId = (0, _milaboratories_pl_model_common.deriveNativeId)(col.spec);
67
- if (seen.has(nativeId)) continue;
68
- seen.add(nativeId);
69
- result.set(col.id, col);
70
- }
71
- }
72
- return result;
73
- }
74
- };
75
- const PLAIN_CONSTRAINTS = {
76
- allowFloatingSourceAxes: true,
77
- allowFloatingHitAxes: true,
78
- allowSourceQualifications: false,
79
- allowHitQualifications: false
80
48
  };
81
49
  var ColumnCollectionImpl = class {
82
50
  columns;
83
51
  specFrameEntry;
84
- columnListComplete;
85
52
  constructor(specDriver, options) {
86
53
  this.specDriver = specDriver;
87
- this.columns = options.columns;
88
- this.columnListComplete = options.columnListComplete ?? false;
89
- this.specFrameEntry = this.specDriver.createSpecFrame(Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])));
54
+ this.columns = new Map(options.columns.map((col) => [col.id, col]));
55
+ this.specFrameEntry = this.specDriver.createSpecFrame(Object.fromEntries(options.columns.map((col) => [col.id, col.spec])));
90
56
  }
91
57
  dispose() {
92
58
  this.specFrameEntry.unref();
@@ -107,7 +73,7 @@ var ColumnCollectionImpl = class {
107
73
  excludeColumns,
108
74
  axes: [],
109
75
  maxHops: 0,
110
- constraints: PLAIN_CONSTRAINTS
76
+ constraints: matchingModeToConstraints("enrichment")
111
77
  }).hits.map((hit) => this.columns.get(hit.hit.columnId)).filter((col) => col !== void 0).map((col) => this.toSnapshot(col));
112
78
  }
113
79
  toSnapshot(col) {
@@ -115,24 +81,23 @@ var ColumnCollectionImpl = class {
115
81
  }
116
82
  };
117
83
  var AnchoredColumnCollectionImpl = class {
118
- columns;
84
+ anchorsMap;
85
+ columnsMap;
119
86
  idDeriver;
87
+ uniqAnchorAxes;
88
+ idToOriginalIdMap;
120
89
  specFrameEntry;
121
- anchorAxes;
122
- /** Reverse lookup: SUniversalPColumnId → PObjectId */
123
- idToOriginal;
124
- columnListComplete;
125
90
  constructor(specDriver, options) {
126
91
  this.specDriver = specDriver;
127
- this.columns = options.columns;
128
- this.idDeriver = options.idDeriver;
129
- this.columnListComplete = options.columnListComplete ?? false;
130
- this.specFrameEntry = this.specDriver.createSpecFrame(Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])));
131
- this.anchorAxes = Object.values(options.anchorSpecs).map((spec) => ({
92
+ this.specFrameEntry = this.specDriver.createSpecFrame(Object.fromEntries(options.columns.map((col) => [col.id, col.spec])));
93
+ this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));
94
+ this.anchorsMap = resolveAnchorMap(options.anchors, options.columns, this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key));
95
+ this.idDeriver = new _milaboratories_pl_model_common.AnchoredIdDeriver(Object.fromEntries(Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec])));
96
+ this.uniqAnchorAxes = (0, es_toolkit.uniqBy)(Array.from(this.anchorsMap.values(), ({ spec }) => ({
132
97
  axesSpec: spec.axesSpec,
133
98
  qualifications: []
134
- }));
135
- this.idToOriginal = new Map(Array.from(this.columns.entries()).map(([id, col]) => [this.idDeriver.deriveS(col.spec), id]));
99
+ })), (axis) => (0, _milaboratories_pl_model_common.canonicalizeJson)((0, _milaboratories_pl_model_common.getAxesId)(axis.axesSpec)) + (0, _milaboratories_pl_model_common.canonicalizeJson)(axis.qualifications));
100
+ this.idToOriginalIdMap = new Map(options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id]));
136
101
  }
137
102
  dispose() {
138
103
  this.specFrameEntry.unref();
@@ -140,74 +105,122 @@ var AnchoredColumnCollectionImpl = class {
140
105
  [Symbol.dispose]() {
141
106
  this.dispose();
142
107
  }
108
+ getAnchors() {
109
+ return this.anchorsMap;
110
+ }
143
111
  getColumn(id) {
144
- const origId = this.idToOriginal.get(id);
112
+ const origId = this.idToOriginalIdMap.get(id);
145
113
  if (origId === void 0) return void 0;
146
- const col = this.columns.get(origId);
114
+ const col = this.columnsMap.get(origId);
147
115
  if (col === void 0) return void 0;
148
- return this.toSnapshot(id, col);
116
+ return remapSnapshot(id, col);
149
117
  }
150
118
  findColumns(options) {
151
119
  const constraints = matchingModeToConstraints(options?.mode ?? "enrichment");
152
120
  const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : void 0;
153
121
  const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : void 0;
154
- return this.specDriver.discoverColumns(this.specFrameEntry.key, {
122
+ const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {
155
123
  includeColumns,
156
124
  excludeColumns,
157
125
  constraints,
158
- axes: this.anchorAxes,
159
- maxHops: options?.maxHops ?? 4
160
- }).hits.map((hit) => {
126
+ maxHops: options?.maxHops ?? 4,
127
+ axes: this.uniqAnchorAxes
128
+ });
129
+ const results = [];
130
+ for (const hit of response.hits) {
161
131
  const origId = hit.hit.columnId;
162
- const col = this.columns.get(origId);
163
- if (!col) return void 0;
164
- const universalId = this.idDeriver.deriveS(col.spec);
165
- return {
166
- column: this.toSnapshot(universalId, col),
167
- originalId: origId,
168
- variants: hit.mappingVariants.map((v) => ({
169
- qualifications: v.qualifications,
170
- distinctiveQualifications: v.distinctiveQualifications
132
+ const col = this.columnsMap.get(origId) ?? (0, _milaboratories_helpers.throwError)(`Column with id ${origId} not found in collection`);
133
+ const associatedId = this.idDeriver.deriveS(col.spec);
134
+ results.push({
135
+ path: hit.path.map((step) => ({
136
+ linker: remapSnapshot(this.idDeriver.deriveS(step.linker.spec), this.columnsMap.get(step.linker.columnId) ?? (0, _milaboratories_helpers.throwError)(`Linker column with id ${step.linker.columnId} not found in collection`)),
137
+ qualifications: step.qualifications
171
138
  })),
172
- path: hit.path
173
- };
174
- }).filter((m) => m !== void 0);
175
- }
176
- toSnapshot(universalId, col) {
177
- return remapSnapshot(universalId, col);
139
+ column: remapSnapshot(associatedId, col),
140
+ variants: hit.mappingVariants,
141
+ originalId: origId
142
+ });
143
+ }
144
+ return results;
178
145
  }
179
146
  };
147
+ /**
148
+ * Collect all columns from all providers, dedup by NativePObjectId.
149
+ * First source wins.
150
+ */
151
+ function collectColumns(providers) {
152
+ const seen = /* @__PURE__ */ new Set();
153
+ const result = [];
154
+ for (const provider of providers) {
155
+ const columns = provider.getAllColumns();
156
+ for (const col of columns) {
157
+ const nativeId = (0, _milaboratories_pl_model_common.deriveNativeId)(col.spec);
158
+ if (seen.has(nativeId)) continue;
159
+ seen.add(nativeId);
160
+ result.push(col);
161
+ }
162
+ }
163
+ return result;
164
+ }
180
165
  /** Create a new snapshot with a different ID, preserving data accessors. */
181
166
  function remapSnapshot(id, col) {
182
- return require_column_snapshot.createColumnSnapshot(id, col.spec, col.dataStatus, col.data);
167
+ return require_column_snapshot.createColumnSnapshot(id, col.spec, col.data, col.dataStatus);
183
168
  }
184
169
  /** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */
185
170
  function toMultiColumnSelectors(input) {
186
- return require_column_selector.normalizeSelectors(input);
171
+ return require_column_selector.convertColumnSelectorToMultiColumnSelector(input);
187
172
  }
188
173
  /**
189
174
  * Resolve each anchor value to a PColumnSpec.
190
175
  * - PColumnSpec: used directly
191
176
  * - PObjectId (string): looked up in the collected column map
192
- * - PlRef: not supported at this level — caller must resolve before building
193
177
  */
194
- function resolveAnchorSpecs(anchors, columnMap) {
195
- const result = {};
178
+ function resolveAnchorMap(anchors, columns, discoverColumns) {
179
+ const result = /* @__PURE__ */ new Map();
180
+ const resovedIds = /* @__PURE__ */ new Set();
181
+ const getDuplicateError = (key) => `Anchor "${key}": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;
196
182
  for (const [key, anchor] of Object.entries(anchors)) if (typeof anchor === "string") {
197
- const col = columnMap.get(anchor);
198
- if (!col) throw new Error(`Anchor "${key}": column with id "${anchor}" not found in sources`);
199
- result[key] = col.spec;
200
- } else if ((0, _milaboratories_pl_model_common.isPlRef)(anchor)) throw new Error(`Anchor "${key}": PlRef anchors must be resolved to PColumnSpec before building. Use the column's spec directly or pass its PObjectId.`);
201
- else result[key] = anchor;
183
+ const found = columns.find((col) => col.id === anchor) ?? (0, _milaboratories_helpers.throwError)(`Anchor "${key}": column with id "${anchor}" not found in sources`);
184
+ if (resovedIds.has(found.id)) (0, _milaboratories_helpers.throwError)(getDuplicateError(key));
185
+ result.set(key, {
186
+ columnId: found.id,
187
+ spec: found.spec
188
+ });
189
+ resovedIds.add(found.id);
190
+ } else if ("kind" in anchor) {
191
+ if (!(0, _milaboratories_pl_model_common.isPColumnSpec)(anchor)) (0, _milaboratories_helpers.throwError)(`Anchor "${key}": invalid PColumnSpec`);
192
+ const nativeId = (0, _milaboratories_pl_model_common.deriveNativeId)(anchor);
193
+ const found = columns.find((col) => (0, _milaboratories_pl_model_common.deriveNativeId)(col.spec) === nativeId) ?? (0, _milaboratories_helpers.throwError)(`Anchor "${key}": no column matching spec found in sources`);
194
+ if (resovedIds.has(found.id)) (0, _milaboratories_helpers.throwError)(getDuplicateError(key));
195
+ result.set(key, {
196
+ columnId: found.id,
197
+ spec: anchor
198
+ });
199
+ resovedIds.add(found.id);
200
+ } else {
201
+ const matched = discoverColumns({
202
+ includeColumns: toMultiColumnSelectors(anchor),
203
+ excludeColumns: void 0,
204
+ axes: [],
205
+ maxHops: 0,
206
+ constraints: matchingModeToConstraints("exact")
207
+ });
208
+ if (matched.hits.length === 0) (0, _milaboratories_helpers.throwError)(`Anchor "${key}": no columns matched selector`);
209
+ if (matched.hits.length > 1) (0, _milaboratories_helpers.throwError)(`Anchor "${key}": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`);
210
+ if (resovedIds.has(matched.hits[0].hit.columnId)) (0, _milaboratories_helpers.throwError)(getDuplicateError(key));
211
+ result.set(key, matched.hits[0].hit);
212
+ resovedIds.add(matched.hits[0].hit.columnId);
213
+ }
214
+ if (resovedIds.size === 0) (0, _milaboratories_helpers.throwError)("At least one anchor must be resolved to a valid column");
202
215
  return result;
203
216
  }
204
217
  function matchingModeToConstraints(mode) {
205
218
  switch (mode) {
206
219
  case "enrichment": return {
207
220
  allowFloatingSourceAxes: true,
208
- allowFloatingHitAxes: true,
209
- allowSourceQualifications: false,
210
- allowHitQualifications: false
221
+ allowFloatingHitAxes: false,
222
+ allowSourceQualifications: true,
223
+ allowHitQualifications: true
211
224
  };
212
225
  case "related": return {
213
226
  allowFloatingSourceAxes: true,
@@ -1 +1 @@
1
- {"version":3,"file":"column_collection_builder.cjs","names":["TreeNodeAccessor","ArrayColumnProvider","toColumnSnapshotProvider","AnchoredIdDeriver","createColumnSnapshot","normalizeSelectors"],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsStepInfo,\n MultiColumnSelector,\n NativePObjectId,\n PColumnSpec,\n PlRef,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport { AnchoredIdDeriver, deriveNativeId, isPlRef } from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelectorInput } from \"./column_selector\";\nimport { normalizeSelectors } from \"./column_selector\";\nimport { TreeNodeAccessor } from \"../render/accessor\";\nimport type { ColumnSnapshot } from \"./column_snapshot\";\nimport { createColumnSnapshot } from \"./column_snapshot\";\nimport type { ColumnSnapshotProvider, ColumnSource } from \"./column_snapshot_provider\";\nimport { ArrayColumnProvider, toColumnSnapshotProvider } from \"./column_snapshot_provider\";\n\nimport type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from \"@milaboratories/pl-model-common\";\n\n// --- FindColumnsOptions ---\n\n/** Options for plain collection findColumns. */\nexport interface FindColumnsOptions {\n /** Include columns matching these selectors. If omitted, includes all columns. */\n include?: ColumnSelectorInput;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelectorInput;\n}\n\n// --- ColumnCollection ---\n\n/** Plain collection — no axis context, selector-based filtering only. */\nexport interface ColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n /** Point lookup by provider-native ID. */\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;\n\n /** Find columns matching selectors. Returns flat list of snapshots.\n * No axis compatibility matching, no linker traversal.\n * Never returns undefined — the \"not ready\" state was absorbed by the builder. */\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];\n}\n\n// --- AnchoredColumnCollection ---\n\n/** Axis-aware column collection with anchored identity derivation. */\nexport interface AnchoredColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n /** Point lookup by anchored ID. */\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;\n\n /** Axis-aware column discovery. */\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];\n}\n\n/** Controls axis matching behavior for anchored discovery. */\nexport type MatchingMode = \"enrichment\" | \"related\" | \"exact\";\n\n/** Options for anchored collection findColumns. */\nexport interface AnchoredFindColumnsOptions extends FindColumnsOptions {\n /** Controls axis matching behavior. Default: 'enrichment'. */\n mode?: MatchingMode;\n /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */\n maxHops?: number;\n}\n\n/** Result of anchored discovery — column snapshot + routing info. */\nexport interface ColumnMatch {\n /** Column snapshot with anchored SUniversalPColumnId. */\n readonly column: ColumnSnapshot<SUniversalPColumnId>;\n /** Provider-native ID — for lookups back to the source provider. */\n readonly originalId: PObjectId;\n /** Match variants — different paths/qualifications that reach this column. */\n readonly variants: MatchVariant[];\n /** Linker steps traversed to reach this hit; empty for direct matches. */\n readonly path: DiscoverColumnsStepInfo[];\n}\n\n/** Qualifications needed for both query (already-integrated) columns and the hit column. */\nexport interface MatchQualifications {\n /** Qualifications for each query (already-integrated) column set. */\n readonly forQueries: AxisQualification[][];\n /** Qualifications for the hit column. */\n readonly forHit: AxisQualification[];\n}\n\n/** A single mapping variant describing how a hit column can be integrated. */\nexport interface MatchVariant {\n /** Full qualifications needed for integration. */\n readonly qualifications: MatchQualifications;\n /** Distinctive (minimal) qualifications needed for integration. */\n readonly distinctiveQualifications: MatchQualifications;\n}\n\n// --- Build options ---\n\nexport interface BuildOptions {\n allowPartialColumnList?: true;\n}\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, PlRef | PObjectId | PColumnSpec>;\n}\n\n// --- ColumnCollectionBuilder ---\n\n/**\n * Mutable builder that accumulates column sources, then produces\n * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).\n *\n * Each output lambda creates its own builder — a constraint of the\n * computable framework where each output tracks its own dependencies.\n */\nexport class ColumnCollectionBuilder {\n private readonly providers: ColumnSnapshotProvider[] = [];\n\n constructor(private readonly specDriver: PFrameSpecDriver) {}\n\n /**\n * Register a column source. Sources added first take precedence for dedup.\n * Does NOT accept undefined — if a source isn't available yet,\n * the caller should return undefined from the output lambda.\n */\n addSource(source: ColumnSource | TreeNodeAccessor): this {\n if (source instanceof TreeNodeAccessor) {\n const columns = source.getPColumns();\n if (columns) this.providers.push(new ArrayColumnProvider(columns));\n } else {\n this.providers.push(toColumnSnapshotProvider(source));\n }\n return this;\n }\n\n addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this {\n for (const source of sources) {\n this.addSource(source);\n }\n return this;\n }\n\n /** Plain collection — selector-based filtering, PObjectId namespace. */\n build(): undefined | ColumnCollection;\n build(options: {\n allowPartialColumnList: true;\n }): ColumnCollection & { readonly columnListComplete: boolean };\n /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */\n build(\n options: AnchoredBuildOptions & { allowPartialColumnList: true },\n ): AnchoredColumnCollection & { readonly columnListComplete: boolean };\n build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;\n build(\n options?: BuildOptions | AnchoredBuildOptions,\n ):\n | undefined\n | ColumnCollection\n | AnchoredColumnCollection\n | (ColumnCollection & { readonly columnListComplete: boolean })\n | (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {\n const allowPartial = options?.allowPartialColumnList === true;\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n // Check column list completeness\n const allComplete = this.providers.every((p) => p.isColumnListComplete());\n if (!allComplete && !allowPartial) return undefined;\n\n // Collect all columns, dedup by native ID (first source wins)\n const columnMap = this.collectColumns();\n\n if (hasAnchors) {\n const anchorSpecs = resolveAnchorSpecs(options.anchors, columnMap);\n const idDeriver = new AnchoredIdDeriver(anchorSpecs);\n\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n columns: columnMap,\n idDeriver,\n anchorSpecs,\n columnListComplete: allowPartial ? allComplete : false,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns: columnMap,\n columnListComplete: allowPartial ? allComplete : false,\n });\n }\n }\n\n /**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\n private collectColumns(): Map<PObjectId, ColumnSnapshot<PObjectId>> {\n const seen = new Set<NativePObjectId>();\n const result = new Map<PObjectId, ColumnSnapshot<PObjectId>>();\n\n for (const provider of this.providers) {\n const columns = provider.getAllColumns();\n for (const col of columns) {\n const nativeId = deriveNativeId(col.spec);\n if (seen.has(nativeId)) continue;\n seen.add(nativeId);\n result.set(col.id, col);\n }\n }\n\n return result;\n }\n}\n\n// --- Permissive constraints for plain (non-anchored) filtering ---\n\nconst PLAIN_CONSTRAINTS: DiscoverColumnsConstraints = {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n};\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n readonly columnListComplete?: boolean;\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n public readonly columnListComplete: boolean;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = options.columns;\n this.columnListComplete = options.columnListComplete ?? false;\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {\n const col = this.columns.get(id);\n if (col === undefined) return undefined;\n return this.toSnapshot(col);\n }\n\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[] {\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n axes: [],\n maxHops: 0,\n constraints: PLAIN_CONSTRAINTS,\n });\n\n // Map hits back to snapshots\n const results = response.hits\n .map((hit) => this.columns.get(hit.hit.columnId as PObjectId))\n .filter((col): col is ColumnSnapshot<PObjectId> => col !== undefined)\n .map((col) => this.toSnapshot(col));\n\n return results;\n }\n\n private toSnapshot(col: ColumnSnapshot<PObjectId>): ColumnSnapshot<PObjectId> {\n return remapSnapshot(col.id, col);\n }\n}\n\n// --- AnchoredColumnCollectionImpl ---\n\ninterface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {\n readonly idDeriver: AnchoredIdDeriver;\n readonly anchorSpecs: Record<string, PColumnSpec>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n private readonly anchorAxes: ColumnAxesWithQualifications[];\n /** Reverse lookup: SUniversalPColumnId → PObjectId */\n private readonly idToOriginal: Map<SUniversalPColumnId, PObjectId>;\n public readonly columnListComplete: boolean;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n this.columns = options.columns;\n this.idDeriver = options.idDeriver;\n this.columnListComplete = options.columnListComplete ?? false;\n\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])),\n );\n\n // Build anchor axes for discovery requests\n this.anchorAxes = Object.values(options.anchorSpecs).map((spec) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n }));\n\n // Build reverse lookup map\n this.idToOriginal = new Map(\n Array.from(this.columns.entries()).map(\n ([id, col]) => [this.idDeriver.deriveS(col.spec), id] as const,\n ),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginal.get(id);\n if (origId === undefined) return undefined;\n const col = this.columns.get(origId);\n if (col === undefined) return undefined;\n return this.toSnapshot(id, col);\n }\n\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {\n const mode = options?.mode ?? \"enrichment\";\n const constraints = matchingModeToConstraints(mode);\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n constraints,\n axes: this.anchorAxes,\n maxHops: options?.maxHops ?? 4,\n });\n\n // Map hits back to ColumnMatch entries\n const results = response.hits\n .map((hit) => {\n const origId = hit.hit.columnId as PObjectId;\n const col = this.columns.get(origId);\n if (!col) return undefined;\n const universalId = this.idDeriver.deriveS(col.spec);\n return {\n column: this.toSnapshot(universalId, col),\n originalId: origId,\n variants: hit.mappingVariants.map(\n (v): MatchVariant => ({\n qualifications: v.qualifications,\n distinctiveQualifications: v.distinctiveQualifications,\n }),\n ),\n path: hit.path,\n } satisfies ColumnMatch;\n })\n .filter((m): m is ColumnMatch => m !== undefined);\n\n return results;\n }\n\n private toSnapshot(\n universalId: SUniversalPColumnId,\n col: ColumnSnapshot<PObjectId>,\n ): ColumnSnapshot<SUniversalPColumnId> {\n return remapSnapshot(universalId, col);\n }\n}\n\n// --- Shared snapshot helpers ---\n\n/** Create a new snapshot with a different ID, preserving data accessors. */\nfunction remapSnapshot<Id extends PObjectId>(\n id: Id,\n col: ColumnSnapshot<PObjectId>,\n): ColumnSnapshot<Id> {\n return createColumnSnapshot(id, col.spec, col.dataStatus, col.data);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelectorInput): MultiColumnSelector[] {\n return normalizeSelectors(input);\n}\n\n// --- Anchor resolution ---\n\n/**\n * Resolve each anchor value to a PColumnSpec.\n * - PColumnSpec: used directly\n * - PObjectId (string): looked up in the collected column map\n * - PlRef: not supported at this level — caller must resolve before building\n */\nfunction resolveAnchorSpecs(\n anchors: Record<string, PlRef | PObjectId | PColumnSpec>,\n columnMap: Map<PObjectId, ColumnSnapshot<PObjectId>>,\n): Record<string, PColumnSpec> {\n const result: Record<string, PColumnSpec> = {};\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n // PObjectId — look up in collected columns\n const col = columnMap.get(anchor as PObjectId);\n if (!col) throw new Error(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n result[key] = col.spec;\n } else if (isPlRef(anchor)) {\n throw new Error(\n `Anchor \"${key}\": PlRef anchors must be resolved to PColumnSpec before building. ` +\n `Use the column's spec directly or pass its PObjectId.`,\n );\n } else {\n // PColumnSpec\n result[key] = anchor;\n }\n }\n return result;\n}\n\n// --- MatchingMode → DiscoverColumnsConstraints ---\n\nfunction matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstraints {\n switch (mode) {\n case \"enrichment\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n case \"related\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"exact\":\n return {\n allowFloatingSourceAxes: false,\n allowFloatingHitAxes: false,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"column_collection_builder.cjs","names":["TreeNodeAccessor","ArrayColumnProvider","toColumnSnapshotProvider","AnchoredIdDeriver","createColumnSnapshot","convertColumnSelectorToMultiColumnSelector"],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n MultiColumnSelector,\n NativePObjectId,\n PColumnIdAndSpec,\n PColumnSpec,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n AnchoredIdDeriver,\n canonicalizeJson,\n deriveNativeId,\n getAxesId,\n isPColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelector, RelaxedColumnSelector } from \"./column_selector\";\nimport { convertColumnSelectorToMultiColumnSelector } from \"./column_selector\";\nimport { TreeNodeAccessor } from \"../render/accessor\";\nimport type { ColumnSnapshot } from \"./column_snapshot\";\nimport { createColumnSnapshot } from \"./column_snapshot\";\nimport type { ColumnSnapshotProvider, ColumnSource } from \"./column_snapshot_provider\";\nimport { ArrayColumnProvider, toColumnSnapshotProvider } from \"./column_snapshot_provider\";\n\nimport type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { uniqBy } from \"es-toolkit\";\n\n// --- FindColumnsOptions ---\n\n/** Options for plain collection findColumns. */\nexport interface FindColumnsOptions {\n /** Include columns matching these selectors. If omitted, includes all columns. */\n include?: ColumnSelector;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelector;\n}\n\n// --- ColumnCollection ---\n\n/** Plain collection — no axis context, selector-based filtering only. */\nexport interface ColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** Point lookup by provider-native ID. */\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;\n\n /** Find columns matching selectors. Returns flat list of snapshots.\n * No axis compatibility matching, no linker traversal.\n * Never returns undefined — the \"not ready\" state was absorbed by the builder. */\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];\n}\n\n// --- AnchoredColumnCollection ---\n\n/** Axis-aware column collection with anchored identity derivation. */\nexport interface AnchoredColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** List of anchors used for discovery, with their resolved specs. */\n getAnchors(): Map<string, PColumnIdAndSpec>;\n\n /** Point lookup by anchored ID. */\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;\n\n /** Axis-aware column discovery. */\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];\n}\n\n/** Controls axis matching behavior for anchored discovery. */\nexport type MatchingMode = \"enrichment\" | \"related\" | \"exact\";\n\n/** Options for anchored collection findColumns. */\nexport interface AnchoredFindColumnsOptions extends FindColumnsOptions {\n /** Controls axis matching behavior. Default: 'enrichment'. */\n mode?: MatchingMode;\n /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */\n maxHops?: number;\n}\n\n/** Result of anchored discovery — column snapshot + routing info. */\nexport interface ColumnMatch {\n /** Column snapshot with anchored SUniversalPColumnId. */\n readonly column: ColumnSnapshot<SUniversalPColumnId>;\n /** Provider-native ID — for lookups back to the source provider. */\n readonly originalId: PObjectId;\n /** Match variants — different paths/qualifications that reach this column. */\n readonly variants: MatchVariant[];\n /** Linker steps traversed to reach this hit; empty for direct matches. */\n readonly path: {\n linker: ColumnSnapshot<SUniversalPColumnId>;\n qualifications: AxisQualification[];\n }[];\n}\n\n/** Qualifications needed for both query (already-integrated) columns and the hit column. */\nexport interface MatchQualifications {\n /** Qualifications for each query (already-integrated) column set. */\n readonly forQueries: AxisQualification[][];\n /** Qualifications for the hit column. */\n readonly forHit: AxisQualification[];\n}\n\n/** A single mapping variant describing how a hit column can be integrated. */\nexport interface MatchVariant {\n /** Full qualifications needed for integration. */\n readonly qualifications: MatchQualifications;\n /** Distinctive (minimal) qualifications needed for integration. */\n readonly distinctiveQualifications: MatchQualifications;\n}\n\n// --- Build options ---\n\nexport interface BuildOptions {\n allowPartialColumnList?: true;\n}\n\nexport type AnchorEntry = PObjectId | PColumnSpec | RelaxedColumnSelector;\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, AnchorEntry>;\n}\n\n// --- ColumnCollectionBuilder ---\n\n/**\n * Mutable builder that accumulates column sources, then produces\n * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).\n *\n * Each output lambda creates its own builder — a constraint of the\n * computable framework where each output tracks its own dependencies.\n */\nexport class ColumnCollectionBuilder {\n private readonly providers: ColumnSnapshotProvider[] = [];\n\n constructor(private readonly specDriver: PFrameSpecDriver) {}\n\n /**\n * Register a column source. Sources added first take precedence for dedup.\n * Does NOT accept undefined — if a source isn't available yet,\n * the caller should return undefined from the output lambda.\n */\n addSource(source: ColumnSource | TreeNodeAccessor): this {\n if (source instanceof TreeNodeAccessor) {\n const columns = source.getPColumns();\n if (columns) this.providers.push(new ArrayColumnProvider(columns));\n } else {\n this.providers.push(toColumnSnapshotProvider(source));\n }\n return this;\n }\n\n addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this {\n for (const source of sources) {\n this.addSource(source);\n }\n return this;\n }\n\n /** Plain collection — selector-based filtering, PObjectId namespace. */\n build(): undefined | ColumnCollection;\n build(options: {\n allowPartialColumnList: true;\n }): ColumnCollection & { readonly columnListComplete: boolean };\n /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */\n build(\n options: AnchoredBuildOptions & { allowPartialColumnList: true },\n ): AnchoredColumnCollection & { readonly columnListComplete: boolean };\n build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;\n build(\n options?: BuildOptions | AnchoredBuildOptions,\n ):\n | undefined\n | ColumnCollection\n | AnchoredColumnCollection\n | (ColumnCollection & { readonly columnListComplete: boolean })\n | (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {\n const allowPartial = options?.allowPartialColumnList === true;\n\n // Check column list completeness\n const allComplete = this.providers.every((p) => p.isColumnListComplete());\n if (!allComplete && !allowPartial) return undefined;\n\n // Collect all columns, dedup by native ID (first source wins)\n const columns = collectColumns(this.providers);\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n if (hasAnchors) {\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n anchors: options.anchors,\n columns,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns,\n });\n }\n }\n}\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: ColumnSnapshot<PObjectId>[];\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = new Map(options.columns.map((col) => [col.id, col]));\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {\n const col = this.columns.get(id);\n if (col === undefined) return undefined;\n return this.toSnapshot(col);\n }\n\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[] {\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"enrichment\"),\n });\n\n // Map hits back to snapshots\n const results = response.hits\n .map((hit) => this.columns.get(hit.hit.columnId as PObjectId))\n .filter((col): col is ColumnSnapshot<PObjectId> => col !== undefined)\n .map((col) => this.toSnapshot(col));\n\n return results;\n }\n\n private toSnapshot(col: ColumnSnapshot<PObjectId>): ColumnSnapshot<PObjectId> {\n return remapSnapshot(col.id, col);\n }\n}\n\n// --- AnchoredColumnCollectionImpl ---\n\ninterface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {\n readonly anchors: Record<string, AnchorEntry>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly anchorsMap: Map<string, PColumnIdAndSpec>;\n private readonly columnsMap: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly uniqAnchorAxes: ColumnAxesWithQualifications[];\n private readonly idToOriginalIdMap: Map<SUniversalPColumnId, PObjectId>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));\n this.anchorsMap = resolveAnchorMap(\n options.anchors,\n options.columns,\n this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key),\n );\n this.idDeriver = new AnchoredIdDeriver(\n Object.fromEntries(\n Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec] as const),\n ),\n );\n this.uniqAnchorAxes = uniqBy(\n Array.from(this.anchorsMap.values(), ({ spec }) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n })),\n (axis) => canonicalizeJson(getAxesId(axis.axesSpec)) + canonicalizeJson(axis.qualifications),\n );\n this.idToOriginalIdMap = new Map(\n options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id] as const),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getAnchors(): Map<string, PColumnIdAndSpec> {\n return this.anchorsMap;\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginalIdMap.get(id);\n if (origId === undefined) return undefined;\n const col = this.columnsMap.get(origId);\n if (col === undefined) return undefined;\n return remapSnapshot(id, col);\n }\n\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {\n const mode = options?.mode ?? \"enrichment\";\n const constraints = matchingModeToConstraints(mode);\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n constraints,\n maxHops: options?.maxHops ?? 4,\n axes: this.uniqAnchorAxes,\n });\n\n // Map every WASM discovery hit to a ColumnMatch.\n // The same physical column may appear multiple times when reachable through\n // different linker paths — each hit becomes a separate ColumnMatch so that\n // the caller can expand them into distinct table columns.\n const results: ColumnMatch[] = [];\n for (const hit of response.hits) {\n const origId = hit.hit.columnId as PObjectId;\n const col =\n this.columnsMap.get(origId) ??\n throwError(`Column with id ${origId} not found in collection`);\n const associatedId = this.idDeriver.deriveS(col.spec);\n\n results.push({\n path: hit.path.map((step) => ({\n linker: remapSnapshot(\n this.idDeriver.deriveS(step.linker.spec),\n this.columnsMap.get(step.linker.columnId) ??\n throwError(`Linker column with id ${step.linker.columnId} not found in collection`),\n ),\n qualifications: step.qualifications,\n })),\n column: remapSnapshot(associatedId, col),\n variants: hit.mappingVariants,\n originalId: origId,\n });\n }\n\n return results;\n }\n}\n\n/**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\nfunction collectColumns(providers: ColumnSnapshotProvider[]): ColumnSnapshot<PObjectId>[] {\n const seen = new Set<NativePObjectId>();\n const result: ColumnSnapshot<PObjectId>[] = [];\n\n for (const provider of providers) {\n const columns = provider.getAllColumns();\n for (const col of columns) {\n const nativeId = deriveNativeId(col.spec);\n if (seen.has(nativeId)) continue;\n seen.add(nativeId);\n result.push(col);\n }\n }\n\n return result;\n}\n\n// --- Shared snapshot helpers ---\n\n/** Create a new snapshot with a different ID, preserving data accessors. */\nfunction remapSnapshot<Id extends PObjectId>(\n id: Id,\n col: ColumnSnapshot<PObjectId>,\n): ColumnSnapshot<Id> {\n return createColumnSnapshot(id, col.spec, col.data, col.dataStatus);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelector): MultiColumnSelector[] {\n return convertColumnSelectorToMultiColumnSelector(input);\n}\n\n// --- Anchor resolution ---\n\n/**\n * Resolve each anchor value to a PColumnSpec.\n * - PColumnSpec: used directly\n * - PObjectId (string): looked up in the collected column map\n */\nfunction resolveAnchorMap(\n anchors: Record<string, AnchorEntry>,\n columns: ColumnSnapshot<PObjectId>[],\n discoverColumns: (request: DiscoverColumnsRequest) => DiscoverColumnsResponse,\n): Map<string, PColumnIdAndSpec> {\n const result = new Map<string, PColumnIdAndSpec>();\n const resovedIds = new Set<PObjectId>();\n const getDuplicateError = (key: string) =>\n `Anchor \"${key}\": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;\n\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n const found =\n columns.find((col) => col.id === anchor) ??\n throwError(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: found.spec });\n resovedIds.add(found.id);\n } else if (\"kind\" in anchor) {\n if (!isPColumnSpec(anchor)) throwError(`Anchor \"${key}\": invalid PColumnSpec`);\n const nativeId = deriveNativeId(anchor);\n const found =\n columns.find((col) => deriveNativeId(col.spec) === nativeId) ??\n throwError(`Anchor \"${key}\": no column matching spec found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: anchor });\n resovedIds.add(found.id);\n } else {\n const matched = discoverColumns({\n includeColumns: toMultiColumnSelectors(anchor),\n excludeColumns: undefined,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"exact\"),\n });\n if (matched.hits.length === 0) {\n throwError(`Anchor \"${key}\": no columns matched selector`);\n }\n if (matched.hits.length > 1) {\n throwError(\n `Anchor \"${key}\": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`,\n );\n }\n if (resovedIds.has(matched.hits[0].hit.columnId as PObjectId)) {\n throwError(getDuplicateError(key));\n }\n\n result.set(key, matched.hits[0].hit);\n resovedIds.add(matched.hits[0].hit.columnId);\n }\n }\n\n if (resovedIds.size === 0) {\n throwError(\"At least one anchor must be resolved to a valid column\");\n }\n\n return result;\n}\n\n// --- MatchingMode → DiscoverColumnsConstraints ---\n\nfunction matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstraints {\n switch (mode) {\n case \"enrichment\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: false,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"related\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"exact\":\n return {\n allowFloatingSourceAxes: false,\n allowFloatingHitAxes: false,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n }\n}\n"],"mappings":"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"}
@@ -1,16 +1,16 @@
1
1
  import { TreeNodeAccessor } from "../render/accessor.js";
2
2
  import { ColumnSnapshot } from "./column_snapshot.js";
3
3
  import { ColumnSource } from "./column_snapshot_provider.js";
4
- import { ColumnSelectorInput } from "./column_selector.js";
5
- import { AxisQualification, DiscoverColumnsStepInfo, PColumnSpec, PFrameSpecDriver, PObjectId, PlRef, SUniversalPColumnId } from "@milaboratories/pl-model-common";
4
+ import { ColumnSelector, RelaxedColumnSelector } from "./column_selector.js";
5
+ import { AxisQualification, PColumnIdAndSpec, PColumnSpec, PFrameSpecDriver, PObjectId, SUniversalPColumnId } from "@milaboratories/pl-model-common";
6
6
 
7
7
  //#region src/columns/column_collection_builder.d.ts
8
8
  /** Options for plain collection findColumns. */
9
9
  interface FindColumnsOptions {
10
10
  /** Include columns matching these selectors. If omitted, includes all columns. */
11
- include?: ColumnSelectorInput;
11
+ include?: ColumnSelector;
12
12
  /** Exclude columns matching these selectors. */
13
- exclude?: ColumnSelectorInput;
13
+ exclude?: ColumnSelector;
14
14
  }
15
15
  /** Plain collection — no axis context, selector-based filtering only. */
16
16
  interface ColumnCollection extends Disposable {
@@ -27,6 +27,8 @@ interface ColumnCollection extends Disposable {
27
27
  interface AnchoredColumnCollection extends Disposable {
28
28
  /** Release the underlying spec frame WASM resource. */
29
29
  dispose(): void;
30
+ /** List of anchors used for discovery, with their resolved specs. */
31
+ getAnchors(): Map<string, PColumnIdAndSpec>;
30
32
  /** Point lookup by anchored ID. */
31
33
  getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;
32
34
  /** Axis-aware column discovery. */
@@ -50,7 +52,10 @@ interface ColumnMatch {
50
52
  /** Match variants — different paths/qualifications that reach this column. */
51
53
  readonly variants: MatchVariant[];
52
54
  /** Linker steps traversed to reach this hit; empty for direct matches. */
53
- readonly path: DiscoverColumnsStepInfo[];
55
+ readonly path: {
56
+ linker: ColumnSnapshot<SUniversalPColumnId>;
57
+ qualifications: AxisQualification[];
58
+ }[];
54
59
  }
55
60
  /** Qualifications needed for both query (already-integrated) columns and the hit column. */
56
61
  interface MatchQualifications {
@@ -69,8 +74,9 @@ interface MatchVariant {
69
74
  interface BuildOptions {
70
75
  allowPartialColumnList?: true;
71
76
  }
77
+ type AnchorEntry = PObjectId | PColumnSpec | RelaxedColumnSelector;
72
78
  interface AnchoredBuildOptions extends BuildOptions {
73
- anchors: Record<string, PlRef | PObjectId | PColumnSpec>;
79
+ anchors: Record<string, AnchorEntry>;
74
80
  }
75
81
  /**
76
82
  * Mutable builder that accumulates column sources, then produces
@@ -104,12 +110,7 @@ declare class ColumnCollectionBuilder {
104
110
  readonly columnListComplete: boolean;
105
111
  };
106
112
  build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;
107
- /**
108
- * Collect all columns from all providers, dedup by NativePObjectId.
109
- * First source wins.
110
- */
111
- private collectColumns;
112
113
  }
113
114
  //#endregion
114
- export { AnchoredBuildOptions, AnchoredColumnCollection, AnchoredFindColumnsOptions, BuildOptions, ColumnCollection, ColumnCollectionBuilder, ColumnMatch, FindColumnsOptions, MatchQualifications, MatchVariant, MatchingMode };
115
+ export { AnchorEntry, AnchoredBuildOptions, AnchoredColumnCollection, AnchoredFindColumnsOptions, BuildOptions, ColumnCollection, ColumnCollectionBuilder, ColumnMatch, FindColumnsOptions, MatchQualifications, MatchVariant, MatchingMode };
115
116
  //# sourceMappingURL=column_collection_builder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"column_collection_builder.d.ts","names":[],"sources":["../../src/columns/column_collection_builder.ts"],"mappings":";;;;;;;;UA0BiB,kBAAA;EAAkB;EAEjC,OAAA,GAAU,mBAAA;EAEmB;EAA7B,OAAA,GAAU,mBAAA;AAAA;;UAMK,gBAAA,SAAyB,UAAA;EANX;EAQ7B,OAAA;EAFe;EAIf,SAAA,CAAU,EAAA,EAAI,SAAA,eAAwB,cAAA,CAAe,SAAA;;;;EAKrD,WAAA,CAAY,OAAA,GAAU,kBAAA,GAAqB,cAAA,CAAe,SAAA;AAAA;;UAM3C,wBAAA,SAAiC,UAAA;EAfR;EAiBxC,OAAA;EAjBkD;EAmBlD,SAAA,CAAU,EAAA,EAAI,mBAAA,eAAkC,cAAA,CAAe,mBAAA;EAjB/D;EAoBA,WAAA,CAAY,OAAA,GAAU,0BAAA,GAA6B,WAAA;AAAA;;KAIzC,YAAA;;UAGK,0BAAA,SAAmC,kBAAA;EApB5B;EAsBtB,IAAA,GAAO,YAAA;EAtBoC;EAwB3C,OAAA;AAAA;;UAIe,WAAA;EAtByB;EAAA,SAwB/B,MAAA,EAAQ,cAAA,CAAe,mBAAA;EApBlB;EAAA,SAsBL,UAAA,EAAY,SAAA;EAtB2B;EAAA,SAwBvC,QAAA,EAAU,YAAA;EArBgC;EAAA,SAuB1C,IAAA,EAAM,uBAAA;AAAA;;UAIA,mBAAA;EAhCf;EAAA,SAkCS,UAAA,EAAY,iBAAA;EAhCP;EAAA,SAkCL,MAAA,EAAQ,iBAAA;AAAA;;UAIF,YAAA;EAnCO;EAAA,SAqCb,cAAA,EAAgB,mBAAA;EArC0B;EAAA,SAuC1C,yBAAA,EAA2B,mBAAA;AAAA;AAAA,UAKrB,YAAA;EACf,sBAAA;AAAA;AAAA,UAGe,oBAAA,SAA6B,YAAA;EAC5C,OAAA,EAAS,MAAA,SAAe,KAAA,GAAQ,SAAA,GAAY,WAAA;AAAA;;;;;;;;cAYjC,uBAAA;EAAA,iBAGkB,UAAA;EAAA,iBAFZ,SAAA;cAEY,UAAA,EAAY,gBAAA;;;;;;EAOzC,SAAA,CAAU,MAAA,EAAQ,YAAA,GAAe,gBAAA;EAUjC,UAAA,CAAW,OAAA,GAAU,YAAA,GAAe,gBAAA;EA1DE;EAkEtC,KAAA,CAAA,eAAqB,gBAAA;EACrB,KAAA,CAAM,OAAA;IACJ,sBAAA;EAAA,IACE,gBAAA;IAAA,SAA8B,kBAAA;EAAA;EAvEf;EAyEnB,KAAA,CACE,OAAA,EAAS,oBAAA;IAAyB,sBAAA;EAAA,IACjC,wBAAA;IAAA,SAAsC,kBAAA;EAAA;EACzC,KAAA,CAAM,OAAA,EAAS,oBAAA,eAAmC,wBAAA;;;;;UAyC1C,cAAA;AAAA"}
1
+ {"version":3,"file":"column_collection_builder.d.ts","names":[],"sources":["../../src/columns/column_collection_builder.ts"],"mappings":";;;;;;;;UAmCiB,kBAAA;EAAkB;EAEjC,OAAA,GAAU,cAAA;EAEc;EAAxB,OAAA,GAAU,cAAA;AAAA;;UAMK,gBAAA,SAAyB,UAAA;EANhB;EAQxB,OAAA;EAFe;EAKf,SAAA,CAAU,EAAA,EAAI,SAAA,eAAwB,cAAA,CAAe,SAAA;;;;EAKrD,WAAA,CAAY,OAAA,GAAU,kBAAA,GAAqB,cAAA,CAAe,SAAA;AAAA;;UAM3C,wBAAA,SAAiC,UAAA;EAhBR;EAkBxC,OAAA;EAlBkD;EAqBlD,UAAA,IAAc,GAAA,SAAY,gBAAA;EAnB1B;EAsBA,SAAA,CAAU,EAAA,EAAI,mBAAA,eAAkC,cAAA,CAAe,mBAAA;EAnBjD;EAsBd,WAAA,CAAY,OAAA,GAAU,0BAAA,GAA6B,WAAA;AAAA;;KAIzC,YAAA;;UAGK,0BAAA,SAAmC,kBAAA;EAxBP;EA0B3C,IAAA,GAAO,YAAA;EA1B4D;EA4BnE,OAAA;AAAA;;UAIe,WAAA;EArBW;EAAA,SAuBjB,MAAA,EAAQ,cAAA,CAAe,mBAAA;EApBlB;EAAA,SAsBL,UAAA,EAAY,SAAA;EAtB2B;EAAA,SAwBvC,QAAA,EAAU,YAAA;EArBgC;EAAA,SAuB1C,IAAA;IACP,MAAA,EAAQ,cAAA,CAAe,mBAAA;IACvB,cAAA,EAAgB,iBAAA;EAAA;AAAA;;UAKH,mBAAA;EApCW;EAAA,SAsCjB,UAAA,EAAY,iBAAA;EAnCP;EAAA,SAqCL,MAAA,EAAQ,iBAAA;AAAA;;UAIF,YAAA;EAtCO;EAAA,SAwCb,cAAA,EAAgB,mBAAA;EAxC0B;EAAA,SA0C1C,yBAAA,EAA2B,mBAAA;AAAA;AAAA,UAKrB,YAAA;EACf,sBAAA;AAAA;AAAA,KAGU,WAAA,GAAc,SAAA,GAAY,WAAA,GAAc,qBAAA;AAAA,UAEnC,oBAAA,SAA6B,YAAA;EAC5C,OAAA,EAAS,MAAA,SAAe,WAAA;AAAA;;;;;;;;cAYb,uBAAA;EAAA,iBAGkB,UAAA;EAAA,iBAFZ,SAAA;cAEY,UAAA,EAAY,gBAAA;EApDT;;;;;EA2DhC,SAAA,CAAU,MAAA,EAAQ,YAAA,GAAe,gBAAA;EAUjC,UAAA,CAAW,OAAA,GAAU,YAAA,GAAe,gBAAA;EA7DD;EAqEnC,KAAA,CAAA,eAAqB,gBAAA;EACrB,KAAA,CAAM,OAAA;IACJ,sBAAA;EAAA,IACE,gBAAA;IAAA,SAA8B,kBAAA;EAAA;EA5EzB;EA8ET,KAAA,CACE,OAAA,EAAS,oBAAA;IAAyB,sBAAA;EAAA,IACjC,wBAAA;IAAA,SAAsC,kBAAA;EAAA;EACzC,KAAA,CAAM,OAAA,EAAS,oBAAA,eAAmC,wBAAA;AAAA"}