@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.
- package/dist/columns/column_collection_builder.cjs +105 -92
- package/dist/columns/column_collection_builder.cjs.map +1 -1
- package/dist/columns/column_collection_builder.d.ts +13 -12
- package/dist/columns/column_collection_builder.d.ts.map +1 -1
- package/dist/columns/column_collection_builder.js +107 -94
- package/dist/columns/column_collection_builder.js.map +1 -1
- package/dist/columns/column_selector.cjs +8 -80
- package/dist/columns/column_selector.cjs.map +1 -1
- package/dist/columns/column_selector.d.ts +6 -14
- package/dist/columns/column_selector.d.ts.map +1 -1
- package/dist/columns/column_selector.js +6 -77
- package/dist/columns/column_selector.js.map +1 -1
- package/dist/columns/column_snapshot.cjs +3 -3
- package/dist/columns/column_snapshot.cjs.map +1 -1
- package/dist/columns/column_snapshot.d.ts +3 -3
- package/dist/columns/column_snapshot.d.ts.map +1 -1
- package/dist/columns/column_snapshot.js +3 -3
- package/dist/columns/column_snapshot.js.map +1 -1
- package/dist/columns/column_snapshot_provider.cjs +1 -1
- package/dist/columns/column_snapshot_provider.cjs.map +1 -1
- package/dist/columns/column_snapshot_provider.d.ts +8 -8
- package/dist/columns/column_snapshot_provider.d.ts.map +1 -1
- package/dist/columns/column_snapshot_provider.js +1 -1
- package/dist/columns/column_snapshot_provider.js.map +1 -1
- package/dist/columns/ctx_column_sources.cjs.map +1 -1
- package/dist/columns/ctx_column_sources.d.ts +2 -1
- package/dist/columns/ctx_column_sources.d.ts.map +1 -1
- package/dist/columns/ctx_column_sources.js.map +1 -1
- package/dist/columns/expand_by_partition.cjs +106 -0
- package/dist/columns/expand_by_partition.cjs.map +1 -0
- package/dist/columns/expand_by_partition.d.ts +33 -0
- package/dist/columns/expand_by_partition.d.ts.map +1 -0
- package/dist/columns/expand_by_partition.js +105 -0
- package/dist/columns/expand_by_partition.js.map +1 -0
- package/dist/columns/index.cjs +1 -0
- package/dist/columns/index.d.ts +4 -3
- package/dist/columns/index.js +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +26 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js +25 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs +68 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js +67 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +27 -17
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +4 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +28 -18
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +258 -175
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +37 -21
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +261 -175
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +64 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts +17 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +63 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/index.cjs +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.js +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs +109 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.d.ts +19 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.d.ts.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.js +102 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -0
- package/dist/components/PlDataTable/index.cjs +3 -1
- package/dist/components/PlDataTable/index.d.ts +5 -3
- package/dist/components/PlDataTable/index.js +3 -1
- package/dist/components/PlDataTable/labels.cjs +25 -11
- package/dist/components/PlDataTable/labels.cjs.map +1 -1
- package/dist/components/PlDataTable/labels.js +25 -11
- package/dist/components/PlDataTable/labels.js.map +1 -1
- package/dist/components/PlDataTable/state-migration.cjs +8 -2
- package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
- package/dist/components/PlDataTable/state-migration.d.ts.map +1 -1
- package/dist/components/PlDataTable/state-migration.js +8 -2
- package/dist/components/PlDataTable/state-migration.js.map +1 -1
- package/dist/components/PlDataTable/typesV5.d.ts +23 -15
- package/dist/components/PlDataTable/typesV5.d.ts.map +1 -1
- package/dist/components/index.cjs +3 -1
- package/dist/components/index.d.ts +4 -2
- package/dist/components/index.js +3 -1
- package/dist/index.cjs +13 -9
- package/dist/index.d.ts +9 -7
- package/dist/index.js +6 -4
- package/dist/labels/derive_distinct_labels.cjs +39 -27
- package/dist/labels/derive_distinct_labels.cjs.map +1 -1
- package/dist/labels/derive_distinct_labels.d.ts +15 -15
- package/dist/labels/derive_distinct_labels.d.ts.map +1 -1
- package/dist/labels/derive_distinct_labels.js +39 -27
- package/dist/labels/derive_distinct_labels.js.map +1 -1
- package/dist/labels/index.cjs +0 -1
- package/dist/labels/index.d.ts +1 -2
- package/dist/labels/index.js +0 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/render/api.cjs +10 -3
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +2 -2
- package/dist/render/api.d.ts.map +1 -1
- package/dist/render/api.js +10 -3
- package/dist/render/api.js.map +1 -1
- package/dist/render/util/column_collection.cjs +3 -3
- package/dist/render/util/column_collection.cjs.map +1 -1
- package/dist/render/util/column_collection.d.ts.map +1 -1
- package/dist/render/util/column_collection.js +3 -3
- package/dist/render/util/column_collection.js.map +1 -1
- package/dist/render/util/label.cjs +2 -2
- package/dist/render/util/label.cjs.map +1 -1
- package/dist/render/util/label.js +2 -2
- package/dist/render/util/label.js.map +1 -1
- package/dist/render/util/pcolumn_data.cjs.map +1 -1
- package/dist/render/util/pcolumn_data.d.ts +2 -2
- package/dist/render/util/pcolumn_data.d.ts.map +1 -1
- package/dist/render/util/pcolumn_data.js.map +1 -1
- package/package.json +7 -7
- package/src/columns/column_collection_builder.test.ts +40 -27
- package/src/columns/column_collection_builder.ts +176 -131
- package/src/columns/column_selector.test.ts +17 -399
- package/src/columns/column_selector.ts +14 -127
- package/src/columns/column_snapshot.ts +5 -5
- package/src/columns/column_snapshot_provider.ts +11 -10
- package/src/columns/ctx_column_sources.ts +2 -2
- package/src/columns/expand_by_partition.test.ts +4 -4
- package/src/columns/expand_by_partition.ts +4 -3
- package/src/columns/index.ts +1 -0
- package/src/components/PlDataTable/createPlDataTable/createPTableDefV2.ts +42 -0
- package/src/components/PlDataTable/createPlDataTable/createPTableDefV3.ts +89 -0
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +51 -19
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +500 -313
- package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +122 -0
- package/src/components/PlDataTable/createPlDataTable/index.ts +4 -2
- package/src/components/PlDataTable/createPlDataTable/utils.test.ts +257 -0
- package/src/components/PlDataTable/createPlDataTable/utils.ts +160 -0
- package/src/components/PlDataTable/index.ts +15 -2
- package/src/components/PlDataTable/labels.ts +29 -18
- package/src/components/PlDataTable/state-migration.ts +6 -1
- package/src/components/PlDataTable/typesV5.ts +25 -12
- package/src/labels/derive_distinct_labels.test.ts +143 -45
- package/src/labels/derive_distinct_labels.ts +102 -49
- package/src/labels/index.ts +0 -1
- package/src/render/api.ts +15 -5
- package/src/render/util/column_collection.ts +4 -3
- package/src/render/util/label.ts +2 -2
- package/src/render/util/pcolumn_data.ts +5 -3
- package/dist/labels/write_labels_to_specs.cjs +0 -14
- package/dist/labels/write_labels_to_specs.cjs.map +0 -1
- package/dist/labels/write_labels_to_specs.d.ts +0 -7
- package/dist/labels/write_labels_to_specs.d.ts.map +0 -1
- package/dist/labels/write_labels_to_specs.js +0 -13
- package/dist/labels/write_labels_to_specs.js.map +0 -1
- package/src/labels/write_labels_to_specs.ts +0 -12
|
@@ -2,17 +2,24 @@ import type {
|
|
|
2
2
|
AxisQualification,
|
|
3
3
|
ColumnAxesWithQualifications,
|
|
4
4
|
DiscoverColumnsConstraints,
|
|
5
|
-
|
|
5
|
+
DiscoverColumnsRequest,
|
|
6
|
+
DiscoverColumnsResponse,
|
|
6
7
|
MultiColumnSelector,
|
|
7
8
|
NativePObjectId,
|
|
9
|
+
PColumnIdAndSpec,
|
|
8
10
|
PColumnSpec,
|
|
9
|
-
PlRef,
|
|
10
11
|
PObjectId,
|
|
11
12
|
SUniversalPColumnId,
|
|
12
13
|
} from "@milaboratories/pl-model-common";
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
import {
|
|
15
|
+
AnchoredIdDeriver,
|
|
16
|
+
canonicalizeJson,
|
|
17
|
+
deriveNativeId,
|
|
18
|
+
getAxesId,
|
|
19
|
+
isPColumnSpec,
|
|
20
|
+
} from "@milaboratories/pl-model-common";
|
|
21
|
+
import type { ColumnSelector, RelaxedColumnSelector } from "./column_selector";
|
|
22
|
+
import { convertColumnSelectorToMultiColumnSelector } from "./column_selector";
|
|
16
23
|
import { TreeNodeAccessor } from "../render/accessor";
|
|
17
24
|
import type { ColumnSnapshot } from "./column_snapshot";
|
|
18
25
|
import { createColumnSnapshot } from "./column_snapshot";
|
|
@@ -20,15 +27,17 @@ import type { ColumnSnapshotProvider, ColumnSource } from "./column_snapshot_pro
|
|
|
20
27
|
import { ArrayColumnProvider, toColumnSnapshotProvider } from "./column_snapshot_provider";
|
|
21
28
|
|
|
22
29
|
import type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from "@milaboratories/pl-model-common";
|
|
30
|
+
import { throwError } from "@milaboratories/helpers";
|
|
31
|
+
import { uniqBy } from "es-toolkit";
|
|
23
32
|
|
|
24
33
|
// --- FindColumnsOptions ---
|
|
25
34
|
|
|
26
35
|
/** Options for plain collection findColumns. */
|
|
27
36
|
export interface FindColumnsOptions {
|
|
28
37
|
/** Include columns matching these selectors. If omitted, includes all columns. */
|
|
29
|
-
include?:
|
|
38
|
+
include?: ColumnSelector;
|
|
30
39
|
/** Exclude columns matching these selectors. */
|
|
31
|
-
exclude?:
|
|
40
|
+
exclude?: ColumnSelector;
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
// --- ColumnCollection ---
|
|
@@ -37,6 +46,7 @@ export interface FindColumnsOptions {
|
|
|
37
46
|
export interface ColumnCollection extends Disposable {
|
|
38
47
|
/** Release the underlying spec frame WASM resource. */
|
|
39
48
|
dispose(): void;
|
|
49
|
+
|
|
40
50
|
/** Point lookup by provider-native ID. */
|
|
41
51
|
getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;
|
|
42
52
|
|
|
@@ -52,6 +62,10 @@ export interface ColumnCollection extends Disposable {
|
|
|
52
62
|
export interface AnchoredColumnCollection extends Disposable {
|
|
53
63
|
/** Release the underlying spec frame WASM resource. */
|
|
54
64
|
dispose(): void;
|
|
65
|
+
|
|
66
|
+
/** List of anchors used for discovery, with their resolved specs. */
|
|
67
|
+
getAnchors(): Map<string, PColumnIdAndSpec>;
|
|
68
|
+
|
|
55
69
|
/** Point lookup by anchored ID. */
|
|
56
70
|
getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;
|
|
57
71
|
|
|
@@ -79,7 +93,10 @@ export interface ColumnMatch {
|
|
|
79
93
|
/** Match variants — different paths/qualifications that reach this column. */
|
|
80
94
|
readonly variants: MatchVariant[];
|
|
81
95
|
/** Linker steps traversed to reach this hit; empty for direct matches. */
|
|
82
|
-
readonly path:
|
|
96
|
+
readonly path: {
|
|
97
|
+
linker: ColumnSnapshot<SUniversalPColumnId>;
|
|
98
|
+
qualifications: AxisQualification[];
|
|
99
|
+
}[];
|
|
83
100
|
}
|
|
84
101
|
|
|
85
102
|
/** Qualifications needed for both query (already-integrated) columns and the hit column. */
|
|
@@ -104,8 +121,10 @@ export interface BuildOptions {
|
|
|
104
121
|
allowPartialColumnList?: true;
|
|
105
122
|
}
|
|
106
123
|
|
|
124
|
+
export type AnchorEntry = PObjectId | PColumnSpec | RelaxedColumnSelector;
|
|
125
|
+
|
|
107
126
|
export interface AnchoredBuildOptions extends BuildOptions {
|
|
108
|
-
anchors: Record<string,
|
|
127
|
+
anchors: Record<string, AnchorEntry>;
|
|
109
128
|
}
|
|
110
129
|
|
|
111
130
|
// --- ColumnCollectionBuilder ---
|
|
@@ -163,84 +182,45 @@ export class ColumnCollectionBuilder {
|
|
|
163
182
|
| (ColumnCollection & { readonly columnListComplete: boolean })
|
|
164
183
|
| (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {
|
|
165
184
|
const allowPartial = options?.allowPartialColumnList === true;
|
|
166
|
-
const hasAnchors = options !== undefined && "anchors" in options;
|
|
167
185
|
|
|
168
186
|
// Check column list completeness
|
|
169
187
|
const allComplete = this.providers.every((p) => p.isColumnListComplete());
|
|
170
188
|
if (!allComplete && !allowPartial) return undefined;
|
|
171
189
|
|
|
172
190
|
// Collect all columns, dedup by native ID (first source wins)
|
|
173
|
-
const
|
|
191
|
+
const columns = collectColumns(this.providers);
|
|
192
|
+
const hasAnchors = options !== undefined && "anchors" in options;
|
|
174
193
|
|
|
175
194
|
if (hasAnchors) {
|
|
176
|
-
const anchorSpecs = resolveAnchorSpecs(options.anchors, columnMap);
|
|
177
|
-
const idDeriver = new AnchoredIdDeriver(anchorSpecs);
|
|
178
|
-
|
|
179
195
|
return new AnchoredColumnCollectionImpl(this.specDriver, {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
anchorSpecs,
|
|
183
|
-
columnListComplete: allowPartial ? allComplete : false,
|
|
196
|
+
anchors: options.anchors,
|
|
197
|
+
columns,
|
|
184
198
|
});
|
|
185
199
|
} else {
|
|
186
200
|
return new ColumnCollectionImpl(this.specDriver, {
|
|
187
|
-
columns
|
|
188
|
-
columnListComplete: allowPartial ? allComplete : false,
|
|
201
|
+
columns,
|
|
189
202
|
});
|
|
190
203
|
}
|
|
191
204
|
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Collect all columns from all providers, dedup by NativePObjectId.
|
|
195
|
-
* First source wins.
|
|
196
|
-
*/
|
|
197
|
-
private collectColumns(): Map<PObjectId, ColumnSnapshot<PObjectId>> {
|
|
198
|
-
const seen = new Set<NativePObjectId>();
|
|
199
|
-
const result = new Map<PObjectId, ColumnSnapshot<PObjectId>>();
|
|
200
|
-
|
|
201
|
-
for (const provider of this.providers) {
|
|
202
|
-
const columns = provider.getAllColumns();
|
|
203
|
-
for (const col of columns) {
|
|
204
|
-
const nativeId = deriveNativeId(col.spec);
|
|
205
|
-
if (seen.has(nativeId)) continue;
|
|
206
|
-
seen.add(nativeId);
|
|
207
|
-
result.set(col.id, col);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return result;
|
|
212
|
-
}
|
|
213
205
|
}
|
|
214
206
|
|
|
215
|
-
// --- Permissive constraints for plain (non-anchored) filtering ---
|
|
216
|
-
|
|
217
|
-
const PLAIN_CONSTRAINTS: DiscoverColumnsConstraints = {
|
|
218
|
-
allowFloatingSourceAxes: true,
|
|
219
|
-
allowFloatingHitAxes: true,
|
|
220
|
-
allowSourceQualifications: false,
|
|
221
|
-
allowHitQualifications: false,
|
|
222
|
-
};
|
|
223
|
-
|
|
224
207
|
// --- ColumnCollectionImpl ---
|
|
225
208
|
|
|
226
209
|
interface ColumnCollectionImplOptions {
|
|
227
|
-
readonly columns:
|
|
228
|
-
readonly columnListComplete?: boolean;
|
|
210
|
+
readonly columns: ColumnSnapshot<PObjectId>[];
|
|
229
211
|
}
|
|
230
212
|
|
|
231
213
|
class ColumnCollectionImpl implements ColumnCollection, Disposable {
|
|
232
214
|
private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;
|
|
233
215
|
private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;
|
|
234
|
-
public readonly columnListComplete: boolean;
|
|
235
216
|
|
|
236
217
|
constructor(
|
|
237
218
|
private readonly specDriver: PFrameSpecDriver,
|
|
238
219
|
options: ColumnCollectionImplOptions,
|
|
239
220
|
) {
|
|
240
|
-
this.columns = options.columns;
|
|
241
|
-
this.columnListComplete = options.columnListComplete ?? false;
|
|
221
|
+
this.columns = new Map(options.columns.map((col) => [col.id, col]));
|
|
242
222
|
this.specFrameEntry = this.specDriver.createSpecFrame(
|
|
243
|
-
Object.fromEntries(
|
|
223
|
+
Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),
|
|
244
224
|
);
|
|
245
225
|
}
|
|
246
226
|
|
|
@@ -267,7 +247,7 @@ class ColumnCollectionImpl implements ColumnCollection, Disposable {
|
|
|
267
247
|
excludeColumns,
|
|
268
248
|
axes: [],
|
|
269
249
|
maxHops: 0,
|
|
270
|
-
constraints:
|
|
250
|
+
constraints: matchingModeToConstraints("enrichment"),
|
|
271
251
|
});
|
|
272
252
|
|
|
273
253
|
// Map hits back to snapshots
|
|
@@ -287,44 +267,47 @@ class ColumnCollectionImpl implements ColumnCollection, Disposable {
|
|
|
287
267
|
// --- AnchoredColumnCollectionImpl ---
|
|
288
268
|
|
|
289
269
|
interface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {
|
|
290
|
-
readonly
|
|
291
|
-
readonly anchorSpecs: Record<string, PColumnSpec>;
|
|
270
|
+
readonly anchors: Record<string, AnchorEntry>;
|
|
292
271
|
}
|
|
293
272
|
|
|
294
273
|
class AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {
|
|
295
|
-
private readonly
|
|
274
|
+
private readonly anchorsMap: Map<string, PColumnIdAndSpec>;
|
|
275
|
+
private readonly columnsMap: Map<PObjectId, ColumnSnapshot<PObjectId>>;
|
|
276
|
+
|
|
296
277
|
private readonly idDeriver: AnchoredIdDeriver;
|
|
278
|
+
private readonly uniqAnchorAxes: ColumnAxesWithQualifications[];
|
|
279
|
+
private readonly idToOriginalIdMap: Map<SUniversalPColumnId, PObjectId>;
|
|
297
280
|
private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;
|
|
298
|
-
private readonly anchorAxes: ColumnAxesWithQualifications[];
|
|
299
|
-
/** Reverse lookup: SUniversalPColumnId → PObjectId */
|
|
300
|
-
private readonly idToOriginal: Map<SUniversalPColumnId, PObjectId>;
|
|
301
|
-
public readonly columnListComplete: boolean;
|
|
302
281
|
|
|
303
282
|
constructor(
|
|
304
283
|
private readonly specDriver: PFrameSpecDriver,
|
|
305
284
|
options: AnchoredColumnCollectionImplOptions,
|
|
306
285
|
) {
|
|
307
|
-
this.columns = options.columns;
|
|
308
|
-
this.idDeriver = options.idDeriver;
|
|
309
|
-
this.columnListComplete = options.columnListComplete ?? false;
|
|
310
|
-
|
|
311
286
|
// Create spec frame from all collected columns
|
|
312
287
|
this.specFrameEntry = this.specDriver.createSpecFrame(
|
|
313
|
-
Object.fromEntries(
|
|
288
|
+
Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),
|
|
314
289
|
);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
Array.from(this.columns.entries()).map(
|
|
325
|
-
([id, col]) => [this.idDeriver.deriveS(col.spec), id] as const,
|
|
290
|
+
this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));
|
|
291
|
+
this.anchorsMap = resolveAnchorMap(
|
|
292
|
+
options.anchors,
|
|
293
|
+
options.columns,
|
|
294
|
+
this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key),
|
|
295
|
+
);
|
|
296
|
+
this.idDeriver = new AnchoredIdDeriver(
|
|
297
|
+
Object.fromEntries(
|
|
298
|
+
Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec] as const),
|
|
326
299
|
),
|
|
327
300
|
);
|
|
301
|
+
this.uniqAnchorAxes = uniqBy(
|
|
302
|
+
Array.from(this.anchorsMap.values(), ({ spec }) => ({
|
|
303
|
+
axesSpec: spec.axesSpec,
|
|
304
|
+
qualifications: [],
|
|
305
|
+
})),
|
|
306
|
+
(axis) => canonicalizeJson(getAxesId(axis.axesSpec)) + canonicalizeJson(axis.qualifications),
|
|
307
|
+
);
|
|
308
|
+
this.idToOriginalIdMap = new Map(
|
|
309
|
+
options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id] as const),
|
|
310
|
+
);
|
|
328
311
|
}
|
|
329
312
|
|
|
330
313
|
dispose(): void {
|
|
@@ -335,12 +318,16 @@ class AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposab
|
|
|
335
318
|
this.dispose();
|
|
336
319
|
}
|
|
337
320
|
|
|
321
|
+
getAnchors(): Map<string, PColumnIdAndSpec> {
|
|
322
|
+
return this.anchorsMap;
|
|
323
|
+
}
|
|
324
|
+
|
|
338
325
|
getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {
|
|
339
|
-
const origId = this.
|
|
326
|
+
const origId = this.idToOriginalIdMap.get(id);
|
|
340
327
|
if (origId === undefined) return undefined;
|
|
341
|
-
const col = this.
|
|
328
|
+
const col = this.columnsMap.get(origId);
|
|
342
329
|
if (col === undefined) return undefined;
|
|
343
|
-
return
|
|
330
|
+
return remapSnapshot(id, col);
|
|
344
331
|
}
|
|
345
332
|
|
|
346
333
|
findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {
|
|
@@ -353,40 +340,60 @@ class AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposab
|
|
|
353
340
|
includeColumns,
|
|
354
341
|
excludeColumns,
|
|
355
342
|
constraints,
|
|
356
|
-
axes: this.anchorAxes,
|
|
357
343
|
maxHops: options?.maxHops ?? 4,
|
|
344
|
+
axes: this.uniqAnchorAxes,
|
|
358
345
|
});
|
|
359
346
|
|
|
360
|
-
// Map
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
347
|
+
// Map every WASM discovery hit to a ColumnMatch.
|
|
348
|
+
// The same physical column may appear multiple times when reachable through
|
|
349
|
+
// different linker paths — each hit becomes a separate ColumnMatch so that
|
|
350
|
+
// the caller can expand them into distinct table columns.
|
|
351
|
+
const results: ColumnMatch[] = [];
|
|
352
|
+
for (const hit of response.hits) {
|
|
353
|
+
const origId = hit.hit.columnId as PObjectId;
|
|
354
|
+
const col =
|
|
355
|
+
this.columnsMap.get(origId) ??
|
|
356
|
+
throwError(`Column with id ${origId} not found in collection`);
|
|
357
|
+
const associatedId = this.idDeriver.deriveS(col.spec);
|
|
358
|
+
|
|
359
|
+
results.push({
|
|
360
|
+
path: hit.path.map((step) => ({
|
|
361
|
+
linker: remapSnapshot(
|
|
362
|
+
this.idDeriver.deriveS(step.linker.spec),
|
|
363
|
+
this.columnsMap.get(step.linker.columnId) ??
|
|
364
|
+
throwError(`Linker column with id ${step.linker.columnId} not found in collection`),
|
|
375
365
|
),
|
|
376
|
-
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
|
|
366
|
+
qualifications: step.qualifications,
|
|
367
|
+
})),
|
|
368
|
+
column: remapSnapshot(associatedId, col),
|
|
369
|
+
variants: hit.mappingVariants,
|
|
370
|
+
originalId: origId,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
380
373
|
|
|
381
374
|
return results;
|
|
382
375
|
}
|
|
376
|
+
}
|
|
383
377
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
378
|
+
/**
|
|
379
|
+
* Collect all columns from all providers, dedup by NativePObjectId.
|
|
380
|
+
* First source wins.
|
|
381
|
+
*/
|
|
382
|
+
function collectColumns(providers: ColumnSnapshotProvider[]): ColumnSnapshot<PObjectId>[] {
|
|
383
|
+
const seen = new Set<NativePObjectId>();
|
|
384
|
+
const result: ColumnSnapshot<PObjectId>[] = [];
|
|
385
|
+
|
|
386
|
+
for (const provider of providers) {
|
|
387
|
+
const columns = provider.getAllColumns();
|
|
388
|
+
for (const col of columns) {
|
|
389
|
+
const nativeId = deriveNativeId(col.spec);
|
|
390
|
+
if (seen.has(nativeId)) continue;
|
|
391
|
+
seen.add(nativeId);
|
|
392
|
+
result.push(col);
|
|
393
|
+
}
|
|
389
394
|
}
|
|
395
|
+
|
|
396
|
+
return result;
|
|
390
397
|
}
|
|
391
398
|
|
|
392
399
|
// --- Shared snapshot helpers ---
|
|
@@ -396,12 +403,12 @@ function remapSnapshot<Id extends PObjectId>(
|
|
|
396
403
|
id: Id,
|
|
397
404
|
col: ColumnSnapshot<PObjectId>,
|
|
398
405
|
): ColumnSnapshot<Id> {
|
|
399
|
-
return createColumnSnapshot(id, col.spec, col.
|
|
406
|
+
return createColumnSnapshot(id, col.spec, col.data, col.dataStatus);
|
|
400
407
|
}
|
|
401
408
|
|
|
402
409
|
/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */
|
|
403
|
-
function toMultiColumnSelectors(input:
|
|
404
|
-
return
|
|
410
|
+
function toMultiColumnSelectors(input: ColumnSelector): MultiColumnSelector[] {
|
|
411
|
+
return convertColumnSelectorToMultiColumnSelector(input);
|
|
405
412
|
}
|
|
406
413
|
|
|
407
414
|
// --- Anchor resolution ---
|
|
@@ -410,29 +417,67 @@ function toMultiColumnSelectors(input: ColumnSelectorInput): MultiColumnSelector
|
|
|
410
417
|
* Resolve each anchor value to a PColumnSpec.
|
|
411
418
|
* - PColumnSpec: used directly
|
|
412
419
|
* - PObjectId (string): looked up in the collected column map
|
|
413
|
-
* - PlRef: not supported at this level — caller must resolve before building
|
|
414
420
|
*/
|
|
415
|
-
function
|
|
416
|
-
anchors: Record<string,
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
421
|
+
function resolveAnchorMap(
|
|
422
|
+
anchors: Record<string, AnchorEntry>,
|
|
423
|
+
columns: ColumnSnapshot<PObjectId>[],
|
|
424
|
+
discoverColumns: (request: DiscoverColumnsRequest) => DiscoverColumnsResponse,
|
|
425
|
+
): Map<string, PColumnIdAndSpec> {
|
|
426
|
+
const result = new Map<string, PColumnIdAndSpec>();
|
|
427
|
+
const resovedIds = new Set<PObjectId>();
|
|
428
|
+
const getDuplicateError = (key: string) =>
|
|
429
|
+
`Anchor "${key}": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;
|
|
430
|
+
|
|
420
431
|
for (const [key, anchor] of Object.entries(anchors)) {
|
|
421
432
|
if (typeof anchor === "string") {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
433
|
+
const found =
|
|
434
|
+
columns.find((col) => col.id === anchor) ??
|
|
435
|
+
throwError(`Anchor "${key}": column with id "${anchor}" not found in sources`);
|
|
436
|
+
if (resovedIds.has(found.id)) {
|
|
437
|
+
throwError(getDuplicateError(key));
|
|
438
|
+
}
|
|
439
|
+
result.set(key, { columnId: found.id, spec: found.spec });
|
|
440
|
+
resovedIds.add(found.id);
|
|
441
|
+
} else if ("kind" in anchor) {
|
|
442
|
+
if (!isPColumnSpec(anchor)) throwError(`Anchor "${key}": invalid PColumnSpec`);
|
|
443
|
+
const nativeId = deriveNativeId(anchor);
|
|
444
|
+
const found =
|
|
445
|
+
columns.find((col) => deriveNativeId(col.spec) === nativeId) ??
|
|
446
|
+
throwError(`Anchor "${key}": no column matching spec found in sources`);
|
|
447
|
+
if (resovedIds.has(found.id)) {
|
|
448
|
+
throwError(getDuplicateError(key));
|
|
449
|
+
}
|
|
450
|
+
result.set(key, { columnId: found.id, spec: anchor });
|
|
451
|
+
resovedIds.add(found.id);
|
|
431
452
|
} else {
|
|
432
|
-
|
|
433
|
-
|
|
453
|
+
const matched = discoverColumns({
|
|
454
|
+
includeColumns: toMultiColumnSelectors(anchor),
|
|
455
|
+
excludeColumns: undefined,
|
|
456
|
+
axes: [],
|
|
457
|
+
maxHops: 0,
|
|
458
|
+
constraints: matchingModeToConstraints("exact"),
|
|
459
|
+
});
|
|
460
|
+
if (matched.hits.length === 0) {
|
|
461
|
+
throwError(`Anchor "${key}": no columns matched selector`);
|
|
462
|
+
}
|
|
463
|
+
if (matched.hits.length > 1) {
|
|
464
|
+
throwError(
|
|
465
|
+
`Anchor "${key}": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
if (resovedIds.has(matched.hits[0].hit.columnId as PObjectId)) {
|
|
469
|
+
throwError(getDuplicateError(key));
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
result.set(key, matched.hits[0].hit);
|
|
473
|
+
resovedIds.add(matched.hits[0].hit.columnId);
|
|
434
474
|
}
|
|
435
475
|
}
|
|
476
|
+
|
|
477
|
+
if (resovedIds.size === 0) {
|
|
478
|
+
throwError("At least one anchor must be resolved to a valid column");
|
|
479
|
+
}
|
|
480
|
+
|
|
436
481
|
return result;
|
|
437
482
|
}
|
|
438
483
|
|
|
@@ -443,9 +488,9 @@ function matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstrain
|
|
|
443
488
|
case "enrichment":
|
|
444
489
|
return {
|
|
445
490
|
allowFloatingSourceAxes: true,
|
|
446
|
-
allowFloatingHitAxes:
|
|
447
|
-
allowSourceQualifications:
|
|
448
|
-
allowHitQualifications:
|
|
491
|
+
allowFloatingHitAxes: false,
|
|
492
|
+
allowSourceQualifications: true,
|
|
493
|
+
allowHitQualifications: true,
|
|
449
494
|
};
|
|
450
495
|
case "related":
|
|
451
496
|
return {
|