@platforma-sdk/model 1.59.0 → 1.60.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 (140) hide show
  1. package/dist/block_storage.cjs.map +1 -1
  2. package/dist/block_storage.d.ts +1 -11
  3. package/dist/block_storage.js.map +1 -1
  4. package/dist/block_storage_callbacks.cjs.map +1 -1
  5. package/dist/block_storage_callbacks.js.map +1 -1
  6. package/dist/columns/column_collection_builder.cjs +215 -0
  7. package/dist/columns/column_collection_builder.cjs.map +1 -0
  8. package/dist/columns/column_collection_builder.d.ts +112 -0
  9. package/dist/columns/column_collection_builder.js +214 -0
  10. package/dist/columns/column_collection_builder.js.map +1 -0
  11. package/dist/columns/column_selector.cjs +122 -0
  12. package/dist/columns/column_selector.cjs.map +1 -0
  13. package/dist/columns/column_selector.d.ts +41 -0
  14. package/dist/columns/column_selector.js +118 -0
  15. package/dist/columns/column_selector.js.map +1 -0
  16. package/dist/columns/column_snapshot.cjs +20 -0
  17. package/dist/columns/column_snapshot.cjs.map +1 -0
  18. package/dist/columns/column_snapshot.d.ts +39 -0
  19. package/dist/columns/column_snapshot.js +18 -0
  20. package/dist/columns/column_snapshot.js.map +1 -0
  21. package/dist/columns/column_snapshot_provider.cjs +112 -0
  22. package/dist/columns/column_snapshot_provider.cjs.map +1 -0
  23. package/dist/columns/column_snapshot_provider.d.ts +73 -0
  24. package/dist/columns/column_snapshot_provider.js +107 -0
  25. package/dist/columns/column_snapshot_provider.js.map +1 -0
  26. package/dist/columns/ctx_column_sources.cjs +84 -0
  27. package/dist/columns/ctx_column_sources.cjs.map +1 -0
  28. package/dist/columns/ctx_column_sources.d.ts +33 -0
  29. package/dist/columns/ctx_column_sources.js +82 -0
  30. package/dist/columns/ctx_column_sources.js.map +1 -0
  31. package/dist/columns/index.cjs +5 -0
  32. package/dist/columns/index.d.ts +5 -0
  33. package/dist/columns/index.js +5 -0
  34. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +111 -0
  35. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -0
  36. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +25 -0
  37. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +110 -0
  38. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -0
  39. package/dist/components/PlDataTable/{table.cjs → createPlDataTable/createPlDataTableV3.cjs} +54 -54
  40. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -0
  41. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +39 -0
  42. package/dist/components/PlDataTable/{table.js → createPlDataTable/createPlDataTableV3.js} +53 -53
  43. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -0
  44. package/dist/components/PlDataTable/createPlDataTable/index.cjs +12 -0
  45. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -0
  46. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +15 -0
  47. package/dist/components/PlDataTable/createPlDataTable/index.js +12 -0
  48. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -0
  49. package/dist/components/PlDataTable/createPlDataTableSheet.cjs +18 -0
  50. package/dist/components/PlDataTable/createPlDataTableSheet.cjs.map +1 -0
  51. package/dist/components/PlDataTable/createPlDataTableSheet.d.ts +11 -0
  52. package/dist/components/PlDataTable/createPlDataTableSheet.js +17 -0
  53. package/dist/components/PlDataTable/createPlDataTableSheet.js.map +1 -0
  54. package/dist/components/PlDataTable/index.cjs +4 -1
  55. package/dist/components/PlDataTable/index.d.ts +5 -2
  56. package/dist/components/PlDataTable/index.js +4 -1
  57. package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
  58. package/dist/components/PlDataTable/state-migration.d.ts +2 -2
  59. package/dist/components/PlDataTable/state-migration.js.map +1 -1
  60. package/dist/components/PlDataTable/{v4.d.ts → typesV4.d.ts} +2 -2
  61. package/dist/components/PlDataTable/{v5.d.ts → typesV5.d.ts} +2 -2
  62. package/dist/components/index.cjs +4 -1
  63. package/dist/components/index.d.ts +5 -2
  64. package/dist/components/index.js +4 -1
  65. package/dist/index.cjs +44 -16
  66. package/dist/index.d.ts +17 -5
  67. package/dist/index.js +15 -3
  68. package/dist/labels/derive_distinct_labels.cjs +156 -0
  69. package/dist/labels/derive_distinct_labels.cjs.map +1 -0
  70. package/dist/labels/derive_distinct_labels.d.ts +29 -0
  71. package/dist/labels/derive_distinct_labels.js +155 -0
  72. package/dist/labels/derive_distinct_labels.js.map +1 -0
  73. package/dist/labels/index.cjs +2 -0
  74. package/dist/labels/index.d.ts +2 -0
  75. package/dist/labels/index.js +2 -0
  76. package/dist/labels/write_labels_to_specs.cjs +15 -0
  77. package/dist/labels/write_labels_to_specs.cjs.map +1 -0
  78. package/dist/labels/write_labels_to_specs.d.ts +9 -0
  79. package/dist/labels/write_labels_to_specs.js +14 -0
  80. package/dist/labels/write_labels_to_specs.js.map +1 -0
  81. package/dist/package.cjs +1 -1
  82. package/dist/package.js +1 -1
  83. package/dist/render/api.cjs +11 -2
  84. package/dist/render/api.cjs.map +1 -1
  85. package/dist/render/api.d.ts +9 -5
  86. package/dist/render/api.js +12 -3
  87. package/dist/render/api.js.map +1 -1
  88. package/dist/render/index.d.ts +2 -1
  89. package/dist/render/index.js +1 -1
  90. package/dist/render/internal.cjs.map +1 -1
  91. package/dist/render/internal.d.ts +5 -2
  92. package/dist/render/internal.js.map +1 -1
  93. package/dist/render/util/column_collection.cjs +3 -3
  94. package/dist/render/util/column_collection.cjs.map +1 -1
  95. package/dist/render/util/column_collection.d.ts +3 -2
  96. package/dist/render/util/column_collection.js +4 -4
  97. package/dist/render/util/column_collection.js.map +1 -1
  98. package/dist/render/util/index.d.ts +2 -1
  99. package/dist/render/util/index.js +1 -1
  100. package/dist/render/util/label.cjs +7 -134
  101. package/dist/render/util/label.cjs.map +1 -1
  102. package/dist/render/util/label.d.ts +5 -50
  103. package/dist/render/util/label.js +8 -132
  104. package/dist/render/util/label.js.map +1 -1
  105. package/dist/render/util/split_selectors.d.ts +2 -2
  106. package/package.json +8 -6
  107. package/src/block_storage.ts +0 -11
  108. package/src/block_storage_callbacks.ts +1 -1
  109. package/src/columns/column_collection_builder.test.ts +427 -0
  110. package/src/columns/column_collection_builder.ts +455 -0
  111. package/src/columns/column_selector.test.ts +472 -0
  112. package/src/columns/column_selector.ts +212 -0
  113. package/src/columns/column_snapshot.ts +55 -0
  114. package/src/columns/column_snapshot_provider.ts +177 -0
  115. package/src/columns/ctx_column_sources.ts +107 -0
  116. package/src/columns/expand_by_partition.test.ts +289 -0
  117. package/src/columns/expand_by_partition.ts +187 -0
  118. package/src/columns/index.ts +5 -0
  119. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +193 -0
  120. package/src/components/PlDataTable/{table.ts → createPlDataTable/createPlDataTableV3.ts} +134 -70
  121. package/src/components/PlDataTable/createPlDataTable/index.ts +27 -0
  122. package/src/components/PlDataTable/createPlDataTableSheet.ts +20 -0
  123. package/src/components/PlDataTable/index.ts +6 -4
  124. package/src/components/PlDataTable/state-migration.ts +2 -2
  125. package/src/index.ts +2 -1
  126. package/src/labels/derive_distinct_labels.test.ts +461 -0
  127. package/src/labels/derive_distinct_labels.ts +289 -0
  128. package/src/labels/index.ts +2 -0
  129. package/src/labels/write_labels_to_specs.ts +12 -0
  130. package/src/render/api.ts +25 -3
  131. package/src/render/internal.ts +20 -1
  132. package/src/render/util/column_collection.ts +9 -6
  133. package/src/render/util/label.test.ts +1 -1
  134. package/src/render/util/label.ts +19 -235
  135. package/src/render/util/split_selectors.ts +3 -3
  136. package/dist/components/PlDataTable/table.cjs.map +0 -1
  137. package/dist/components/PlDataTable/table.d.ts +0 -30
  138. package/dist/components/PlDataTable/table.js.map +0 -1
  139. /package/src/components/PlDataTable/{v4.ts → typesV4.ts} +0 -0
  140. /package/src/components/PlDataTable/{v5.ts → typesV5.ts} +0 -0
@@ -0,0 +1,112 @@
1
+ import { GlobalCfgRenderCtxMethods } from "../render/internal.js";
2
+ import { TreeNodeAccessor } from "../render/accessor.js";
3
+ import { ColumnSnapshot } from "./column_snapshot.js";
4
+ import { ColumnSource } from "./column_snapshot_provider.js";
5
+ import { ColumnSelectorInput } from "./column_selector.js";
6
+ import { AxisQualification, PColumnSpec, PObjectId, PlRef, SUniversalPColumnId } from "@milaboratories/pl-model-common";
7
+
8
+ //#region src/columns/column_collection_builder.d.ts
9
+ /** Subset of render context methods needed for spec frame operations. */
10
+ type SpecFrameCtx = Pick<GlobalCfgRenderCtxMethods, "createSpecFrame" | "specFrameDiscoverColumns" | "specFrameDispose">;
11
+ /** Options for plain collection findColumns. */
12
+ interface FindColumnsOptions {
13
+ /** Include columns matching these selectors. If omitted, includes all columns. */
14
+ include?: ColumnSelectorInput;
15
+ /** Exclude columns matching these selectors. */
16
+ exclude?: ColumnSelectorInput;
17
+ }
18
+ /** Plain collection — no axis context, selector-based filtering only. */
19
+ interface ColumnCollection {
20
+ /** Point lookup by provider-native ID. */
21
+ getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;
22
+ /** Find columns matching selectors. Returns flat list of snapshots.
23
+ * No axis compatibility matching, no linker traversal.
24
+ * Never returns undefined — the "not ready" state was absorbed by the builder. */
25
+ findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];
26
+ }
27
+ /** Axis-aware column collection with anchored identity derivation. */
28
+ interface AnchoredColumnCollection {
29
+ /** Point lookup by anchored ID. */
30
+ getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;
31
+ /** Axis-aware column discovery. */
32
+ findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];
33
+ }
34
+ /** Controls axis matching behavior for anchored discovery. */
35
+ type MatchingMode = "enrichment" | "related" | "exact";
36
+ /** Options for anchored collection findColumns. */
37
+ interface AnchoredFindColumnsOptions extends FindColumnsOptions {
38
+ /** Controls axis matching behavior. Default: 'enrichment'. */
39
+ mode?: MatchingMode;
40
+ /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */
41
+ maxHops?: number;
42
+ }
43
+ /** Result of anchored discovery — column snapshot + routing info. */
44
+ interface ColumnMatch {
45
+ /** Column snapshot with anchored SUniversalPColumnId. */
46
+ readonly column: ColumnSnapshot<SUniversalPColumnId>;
47
+ /** Provider-native ID — for lookups back to the source provider. */
48
+ readonly originalId: PObjectId;
49
+ /** Match variants — different paths/qualifications that reach this column. */
50
+ readonly variants: MatchVariant[];
51
+ }
52
+ /** Qualifications needed for both query (already-integrated) columns and the hit column. */
53
+ interface MatchQualifications {
54
+ /** Qualifications for each query (already-integrated) column set. */
55
+ readonly forQueries: AxisQualification[][];
56
+ /** Qualifications for the hit column. */
57
+ readonly forHit: AxisQualification[];
58
+ }
59
+ /** A single mapping variant describing how a hit column can be integrated. */
60
+ interface MatchVariant {
61
+ /** Full qualifications needed for integration. */
62
+ readonly qualifications: MatchQualifications;
63
+ /** Distinctive (minimal) qualifications needed for integration. */
64
+ readonly distinctiveQualifications: MatchQualifications;
65
+ }
66
+ interface BuildOptions {
67
+ allowPartialColumnList?: true;
68
+ }
69
+ interface AnchoredBuildOptions extends BuildOptions {
70
+ anchors: Record<string, PlRef | PObjectId | PColumnSpec>;
71
+ }
72
+ /**
73
+ * Mutable builder that accumulates column sources, then produces
74
+ * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).
75
+ *
76
+ * Each output lambda creates its own builder — a constraint of the
77
+ * computable framework where each output tracks its own dependencies.
78
+ */
79
+ declare class ColumnCollectionBuilder {
80
+ private readonly specFrameCtx;
81
+ private readonly providers;
82
+ constructor(specFrameCtx: SpecFrameCtx);
83
+ /**
84
+ * Register a column source. Sources added first take precedence for dedup.
85
+ * Does NOT accept undefined — if a source isn't available yet,
86
+ * the caller should return undefined from the output lambda.
87
+ */
88
+ addSource(source: ColumnSource | TreeNodeAccessor): this;
89
+ addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this;
90
+ /** Plain collection — selector-based filtering, PObjectId namespace. */
91
+ build(): undefined | ColumnCollection;
92
+ build(options: {
93
+ allowPartialColumnList: true;
94
+ }): ColumnCollection & {
95
+ readonly columnListComplete: boolean;
96
+ };
97
+ /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */
98
+ build(options: AnchoredBuildOptions & {
99
+ allowPartialColumnList: true;
100
+ }): AnchoredColumnCollection & {
101
+ readonly columnListComplete: boolean;
102
+ };
103
+ build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;
104
+ /**
105
+ * Collect all columns from all providers, dedup by NativePObjectId.
106
+ * First source wins.
107
+ */
108
+ private collectColumns;
109
+ }
110
+ //#endregion
111
+ export { AnchoredBuildOptions, AnchoredColumnCollection, AnchoredFindColumnsOptions, BuildOptions, ColumnCollection, ColumnCollectionBuilder, ColumnMatch, FindColumnsOptions, MatchQualifications, MatchVariant, MatchingMode };
112
+ //# sourceMappingURL=column_collection_builder.d.ts.map
@@ -0,0 +1,214 @@
1
+ import { TreeNodeAccessor } from "../render/accessor.js";
2
+ import { createColumnSnapshot } from "./column_snapshot.js";
3
+ import { ArrayColumnProvider, toColumnSnapshotProvider } from "./column_snapshot_provider.js";
4
+ import { normalizeSelectors } from "./column_selector.js";
5
+ import { AnchoredIdDeriver, deriveNativeId, isPlRef } from "@milaboratories/pl-model-common";
6
+
7
+ //#region src/columns/column_collection_builder.ts
8
+ /**
9
+ * Mutable builder that accumulates column sources, then produces
10
+ * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).
11
+ *
12
+ * Each output lambda creates its own builder — a constraint of the
13
+ * computable framework where each output tracks its own dependencies.
14
+ */
15
+ var ColumnCollectionBuilder = class {
16
+ providers = [];
17
+ constructor(specFrameCtx) {
18
+ this.specFrameCtx = specFrameCtx;
19
+ }
20
+ /**
21
+ * Register a column source. Sources added first take precedence for dedup.
22
+ * Does NOT accept undefined — if a source isn't available yet,
23
+ * the caller should return undefined from the output lambda.
24
+ */
25
+ addSource(source) {
26
+ if (source instanceof TreeNodeAccessor) {
27
+ const columns = source.getPColumns();
28
+ if (columns) this.providers.push(new ArrayColumnProvider(columns));
29
+ } else this.providers.push(toColumnSnapshotProvider(source));
30
+ return this;
31
+ }
32
+ addSources(sources) {
33
+ for (const source of sources) this.addSource(source);
34
+ return this;
35
+ }
36
+ build(options) {
37
+ const allowPartial = options?.allowPartialColumnList === true;
38
+ const hasAnchors = options !== void 0 && "anchors" in options;
39
+ const allComplete = this.providers.every((p) => p.isColumnListComplete());
40
+ if (!allComplete && !allowPartial) return void 0;
41
+ const columnMap = this.collectColumns();
42
+ if (hasAnchors) {
43
+ const anchorSpecs = resolveAnchorSpecs(options.anchors, columnMap);
44
+ const idDeriver = new AnchoredIdDeriver(anchorSpecs);
45
+ return new AnchoredColumnCollectionImpl(this.specFrameCtx, {
46
+ columns: columnMap,
47
+ idDeriver,
48
+ anchorSpecs,
49
+ columnListComplete: allowPartial ? allComplete : false
50
+ });
51
+ } else return new ColumnCollectionImpl(this.specFrameCtx, {
52
+ columns: columnMap,
53
+ columnListComplete: allowPartial ? allComplete : false
54
+ });
55
+ }
56
+ /**
57
+ * Collect all columns from all providers, dedup by NativePObjectId.
58
+ * First source wins.
59
+ */
60
+ collectColumns() {
61
+ const seen = /* @__PURE__ */ new Set();
62
+ const result = /* @__PURE__ */ new Map();
63
+ for (const provider of this.providers) {
64
+ const columns = provider.getAllColumns();
65
+ for (const col of columns) {
66
+ const nativeId = deriveNativeId(col.spec);
67
+ if (seen.has(nativeId)) continue;
68
+ seen.add(nativeId);
69
+ result.set(col.id, col);
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ };
75
+ const PLAIN_CONSTRAINTS = {
76
+ allowFloatingSourceAxes: true,
77
+ allowFloatingHitAxes: true,
78
+ allowSourceQualifications: false,
79
+ allowHitQualifications: false
80
+ };
81
+ var ColumnCollectionImpl = class {
82
+ columns;
83
+ specFrameHandle;
84
+ columnListComplete;
85
+ constructor(ctx, options) {
86
+ this.ctx = ctx;
87
+ this.columns = options.columns;
88
+ this.columnListComplete = options.columnListComplete ?? false;
89
+ this.specFrameHandle = this.ctx.createSpecFrame(Array.from(this.columns.entries()).reduce((acc, [id, col]) => (acc[id] = col.spec, acc), {}));
90
+ }
91
+ getColumn(id) {
92
+ const col = this.columns.get(id);
93
+ if (col === void 0) return void 0;
94
+ return this.toSnapshot(col);
95
+ }
96
+ findColumns(options) {
97
+ const columnFilter = options?.include ? toMultiColumnSelectors(options.include) : [];
98
+ let results = this.ctx.specFrameDiscoverColumns(this.specFrameHandle, {
99
+ columnFilter,
100
+ axes: [],
101
+ constraints: PLAIN_CONSTRAINTS
102
+ }).hits.map((hit) => this.columns.get(hit.hit.columnId)).filter((col) => col !== void 0).map((col) => this.toSnapshot(col));
103
+ if (options?.exclude) throw new Error("Exclude filter is not yet implemented for plain ColumnCollection");
104
+ return results;
105
+ }
106
+ toSnapshot(col) {
107
+ return remapSnapshot(col.id, col);
108
+ }
109
+ };
110
+ var AnchoredColumnCollectionImpl = class {
111
+ columns;
112
+ idDeriver;
113
+ specFrameHandle;
114
+ anchorAxes;
115
+ /** Reverse lookup: SUniversalPColumnId → PObjectId */
116
+ idToOriginal;
117
+ columnListComplete;
118
+ constructor(ctx, options) {
119
+ this.ctx = ctx;
120
+ this.columns = options.columns;
121
+ this.idDeriver = options.idDeriver;
122
+ this.columnListComplete = options.columnListComplete ?? false;
123
+ this.specFrameHandle = this.ctx.createSpecFrame(Array.from(this.columns.entries()).reduce((acc, [id, col]) => (acc[id] = col.spec, acc), {}));
124
+ this.anchorAxes = Object.values(options.anchorSpecs).map((spec) => ({
125
+ axesSpec: spec.axesSpec,
126
+ qualifications: []
127
+ }));
128
+ this.idToOriginal = new Map(Array.from(this.columns.entries()).map(([id, col]) => [this.idDeriver.deriveS(col.spec), id]));
129
+ }
130
+ getColumn(id) {
131
+ const origId = this.idToOriginal.get(id);
132
+ if (origId === void 0) return void 0;
133
+ const col = this.columns.get(origId);
134
+ if (col === void 0) return void 0;
135
+ return this.toSnapshot(id, col);
136
+ }
137
+ findColumns(options) {
138
+ const constraints = matchingModeToConstraints(options?.mode ?? "enrichment");
139
+ const columnFilter = options?.include ? toMultiColumnSelectors(options.include) : [];
140
+ let results = this.ctx.specFrameDiscoverColumns(this.specFrameHandle, {
141
+ columnFilter,
142
+ constraints,
143
+ axes: this.anchorAxes
144
+ }).hits.map((hit) => {
145
+ const origId = hit.hit.columnId;
146
+ const col = this.columns.get(origId);
147
+ if (!col) return void 0;
148
+ const universalId = this.idDeriver.deriveS(col.spec);
149
+ return {
150
+ column: this.toSnapshot(universalId, col),
151
+ originalId: origId,
152
+ variants: hit.mappingVariants.map((v) => ({
153
+ qualifications: v.qualifications,
154
+ distinctiveQualifications: v.distinctiveQualifications
155
+ }))
156
+ };
157
+ }).filter((m) => m !== void 0);
158
+ if (options?.exclude) throw new Error("Exclude filter is not yet implemented for AnchoredColumnCollection");
159
+ return results;
160
+ }
161
+ toSnapshot(universalId, col) {
162
+ return remapSnapshot(universalId, col);
163
+ }
164
+ };
165
+ /** Create a new snapshot with a different ID, preserving data accessors. */
166
+ function remapSnapshot(id, col) {
167
+ return createColumnSnapshot(id, col.spec, col.dataStatus, col.data);
168
+ }
169
+ /** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */
170
+ function toMultiColumnSelectors(input) {
171
+ return normalizeSelectors(input);
172
+ }
173
+ /**
174
+ * Resolve each anchor value to a PColumnSpec.
175
+ * - PColumnSpec: used directly
176
+ * - PObjectId (string): looked up in the collected column map
177
+ * - PlRef: not supported at this level — caller must resolve before building
178
+ */
179
+ function resolveAnchorSpecs(anchors, columnMap) {
180
+ const result = {};
181
+ for (const [key, anchor] of Object.entries(anchors)) if (typeof anchor === "string") {
182
+ const col = columnMap.get(anchor);
183
+ if (!col) throw new Error(`Anchor "${key}": column with id "${anchor}" not found in sources`);
184
+ result[key] = col.spec;
185
+ } else if (isPlRef(anchor)) throw new Error(`Anchor "${key}": PlRef anchors must be resolved to PColumnSpec before building. Use the column's spec directly or pass its PObjectId.`);
186
+ else result[key] = anchor;
187
+ return result;
188
+ }
189
+ function matchingModeToConstraints(mode) {
190
+ switch (mode) {
191
+ case "enrichment": return {
192
+ allowFloatingSourceAxes: true,
193
+ allowFloatingHitAxes: true,
194
+ allowSourceQualifications: false,
195
+ allowHitQualifications: false
196
+ };
197
+ case "related": return {
198
+ allowFloatingSourceAxes: true,
199
+ allowFloatingHitAxes: true,
200
+ allowSourceQualifications: true,
201
+ allowHitQualifications: true
202
+ };
203
+ case "exact": return {
204
+ allowFloatingSourceAxes: false,
205
+ allowFloatingHitAxes: false,
206
+ allowSourceQualifications: false,
207
+ allowHitQualifications: false
208
+ };
209
+ }
210
+ }
211
+
212
+ //#endregion
213
+ export { ColumnCollectionBuilder };
214
+ //# sourceMappingURL=column_collection_builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column_collection_builder.js","names":[],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n 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 { GlobalCfgRenderCtxMethods } from \"../render/internal\";\n\n/** Subset of render context methods needed for spec frame operations. */\ntype SpecFrameCtx = Pick<\n GlobalCfgRenderCtxMethods,\n \"createSpecFrame\" | \"specFrameDiscoverColumns\" | \"specFrameDispose\"\n>;\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 {\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 {\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}\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 specFrameCtx: SpecFrameCtx) {}\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.specFrameCtx, {\n columns: columnMap,\n idDeriver,\n anchorSpecs,\n columnListComplete: allowPartial ? allComplete : false,\n });\n } else {\n return new ColumnCollectionImpl(this.specFrameCtx, {\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 {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameHandle: string;\n public readonly columnListComplete: boolean;\n\n constructor(\n private readonly ctx: SpecFrameCtx,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = options.columns;\n this.columnListComplete = options.columnListComplete ?? false;\n this.specFrameHandle = this.ctx.createSpecFrame(\n Array.from(this.columns.entries()).reduce(\n (acc, [id, col]) => ((acc[id] = col.spec), acc),\n {} as Record<string, PColumnSpec>,\n ),\n );\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 columnFilter = options?.include ? toMultiColumnSelectors(options.include) : [];\n\n const response = this.ctx.specFrameDiscoverColumns(this.specFrameHandle, {\n columnFilter,\n axes: [],\n constraints: PLAIN_CONSTRAINTS,\n });\n\n // Map hits back to snapshots\n let 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 if (options?.exclude) {\n throw new Error(\"Exclude filter is not yet implemented for plain ColumnCollection\");\n }\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 {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly specFrameHandle: string;\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 ctx: SpecFrameCtx,\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.specFrameHandle = this.ctx.createSpecFrame(\n Array.from(this.columns.entries()).reduce(\n (acc, [id, col]) => ((acc[id] = col.spec), acc),\n {} as Record<string, PColumnSpec>,\n ),\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 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 columnFilter = options?.include ? toMultiColumnSelectors(options.include) : [];\n\n const response = this.ctx.specFrameDiscoverColumns(this.specFrameHandle, {\n columnFilter,\n constraints,\n axes: this.anchorAxes,\n });\n\n // Map hits back to ColumnMatch entries\n let 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 } satisfies ColumnMatch;\n })\n .filter((m): m is ColumnMatch => m !== undefined);\n\n if (options?.exclude) {\n throw new Error(\"Exclude filter is not yet implemented for AnchoredColumnCollection\");\n }\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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"}
@@ -0,0 +1,122 @@
1
+
2
+ //#region src/columns/column_selector.ts
3
+ function normalizeStringMatchers(input) {
4
+ if (typeof input === "string") return [{
5
+ type: "regex",
6
+ value: input
7
+ }];
8
+ if (!Array.isArray(input)) return [input];
9
+ return input.map((v) => typeof v === "string" ? {
10
+ type: "regex",
11
+ value: v
12
+ } : v);
13
+ }
14
+ function normalizeRecord(input) {
15
+ const result = {};
16
+ for (const [key, value] of Object.entries(input)) result[key] = normalizeStringMatchers(value);
17
+ return result;
18
+ }
19
+ function normalizeTypes(input) {
20
+ return Array.isArray(input) ? input : [input];
21
+ }
22
+ function normalizeAxisSelector(input) {
23
+ const result = {};
24
+ if (input.name !== void 0) result.name = normalizeStringMatchers(input.name);
25
+ if (input.type !== void 0) result.type = normalizeTypes(input.type);
26
+ if (input.domain !== void 0) result.domain = normalizeRecord(input.domain);
27
+ if (input.contextDomain !== void 0) result.contextDomain = normalizeRecord(input.contextDomain);
28
+ if (input.annotations !== void 0) result.annotations = normalizeRecord(input.annotations);
29
+ return result;
30
+ }
31
+ /** Normalize relaxed input to strict ColumnSelector[]. */
32
+ function normalizeSelectors(input) {
33
+ return (Array.isArray(input) ? input : [input]).map(normalizeSingleSelector);
34
+ }
35
+ function normalizeSingleSelector(input) {
36
+ const result = {};
37
+ if (input.name !== void 0) result.name = normalizeStringMatchers(input.name);
38
+ if (input.type !== void 0) result.type = normalizeTypes(input.type);
39
+ if (input.domain !== void 0) result.domain = normalizeRecord(input.domain);
40
+ if (input.contextDomain !== void 0) result.contextDomain = normalizeRecord(input.contextDomain);
41
+ if (input.annotations !== void 0) result.annotations = normalizeRecord(input.annotations);
42
+ if (input.axes !== void 0) result.axes = input.axes.map(normalizeAxisSelector);
43
+ if (input.partialAxesMatch !== void 0) result.partialAxesMatch = input.partialAxesMatch;
44
+ return result;
45
+ }
46
+ function matchStringValue(value, matchers) {
47
+ return matchers.some((m) => {
48
+ if (m.type === "exact") return value === m.value;
49
+ return new RegExp(`^(?:${m.value})$`).test(value);
50
+ });
51
+ }
52
+ function matchRecordField(actual, required) {
53
+ const record = actual ?? {};
54
+ for (const [key, matchers] of Object.entries(required)) {
55
+ const value = record[key];
56
+ if (value === void 0) return false;
57
+ if (!matchStringValue(value, matchers)) return false;
58
+ }
59
+ return true;
60
+ }
61
+ /** Get combined domain: column's own domain merged with all axis domains. */
62
+ function getCombinedDomain(spec) {
63
+ const result = {};
64
+ if (spec.domain) Object.assign(result, spec.domain);
65
+ for (const axis of spec.axesSpec) if (axis.domain) Object.assign(result, axis.domain);
66
+ return result;
67
+ }
68
+ /** Get combined context domain: column's own contextDomain merged with all axis contextDomains. */
69
+ function getCombinedContextDomain(spec) {
70
+ const result = {};
71
+ if (spec.contextDomain) Object.assign(result, spec.contextDomain);
72
+ for (const axis of spec.axesSpec) if ("contextDomain" in axis && axis.contextDomain) Object.assign(result, axis.contextDomain);
73
+ return result;
74
+ }
75
+ function matchAxisSelector(axis, selector) {
76
+ if (selector.name !== void 0 && !matchStringValue(axis.name, selector.name)) return false;
77
+ if (selector.type !== void 0 && !selector.type.includes(axis.type)) return false;
78
+ if (selector.domain !== void 0 && !matchRecordField(axis.domain, selector.domain)) return false;
79
+ if (selector.contextDomain !== void 0 && !matchRecordField("contextDomain" in axis ? axis.contextDomain : void 0, selector.contextDomain)) return false;
80
+ if (selector.annotations !== void 0 && !matchRecordField(axis.annotations, selector.annotations)) return false;
81
+ return true;
82
+ }
83
+ /** Check if a PColumnSpec matches a single strict ColumnSelector. */
84
+ function matchColumn(spec, selector) {
85
+ if (selector.name !== void 0 && !matchStringValue(spec.name, selector.name)) return false;
86
+ if (selector.type !== void 0 && !selector.type.includes(spec.valueType)) return false;
87
+ if (selector.domain !== void 0) {
88
+ if (!matchRecordField(getCombinedDomain(spec), selector.domain)) return false;
89
+ }
90
+ if (selector.contextDomain !== void 0) {
91
+ if (!matchRecordField(getCombinedContextDomain(spec), selector.contextDomain)) return false;
92
+ }
93
+ if (selector.annotations !== void 0) {
94
+ if (!matchRecordField(spec.annotations, selector.annotations)) return false;
95
+ }
96
+ if (selector.axes !== void 0) if (selector.partialAxesMatch ?? true) {
97
+ for (const axisSel of selector.axes) if (!spec.axesSpec.some((axis) => matchAxisSelector(axis, axisSel))) return false;
98
+ } else {
99
+ if (spec.axesSpec.length !== selector.axes.length) return false;
100
+ for (let i = 0; i < selector.axes.length; i++) if (!matchAxisSelector(spec.axesSpec[i], selector.axes[i])) return false;
101
+ }
102
+ return true;
103
+ }
104
+ /** Check if a PColumnSpec matches any of the selectors (OR across array). */
105
+ function matchColumnSelectors(selectors, spec) {
106
+ return selectors.some((sel) => matchColumn(spec, sel));
107
+ }
108
+ /**
109
+ * Convert selector input to a predicate function.
110
+ * Normalizes relaxed form, then returns a function that OR-matches.
111
+ */
112
+ function columnSelectorsToPredicate(input) {
113
+ const selectors = normalizeSelectors(input);
114
+ return (spec) => matchColumnSelectors(selectors, spec);
115
+ }
116
+
117
+ //#endregion
118
+ exports.columnSelectorsToPredicate = columnSelectorsToPredicate;
119
+ exports.matchColumn = matchColumn;
120
+ exports.matchColumnSelectors = matchColumnSelectors;
121
+ exports.normalizeSelectors = normalizeSelectors;
122
+ //# sourceMappingURL=column_selector.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column_selector.cjs","names":[],"sources":["../../src/columns/column_selector.ts"],"sourcesContent":["import type {\n MultiAxisSelector,\n MultiColumnSelector,\n PColumnSpec,\n StringMatcher,\n ValueType,\n} from \"@milaboratories/pl-model-common\";\n\nexport type { StringMatcher } from \"@milaboratories/pl-model-common\";\n\n// --- Relaxed types ---\n\n/** Relaxed string matcher input: plain string, single matcher, or array of mixed. */\nexport type RelaxedStringMatchers = string | StringMatcher | (string | StringMatcher)[];\n\n/** Relaxed record matcher: values can be plain strings or relaxed matchers. */\nexport type RelaxedRecord = Record<string, RelaxedStringMatchers>;\n\n/** Relaxed axis selector — accepts plain strings where strict requires StringMatcher[]. */\nexport interface RelaxedAxisSelector {\n name?: RelaxedStringMatchers;\n type?: ValueType | ValueType[];\n domain?: RelaxedRecord;\n contextDomain?: RelaxedRecord;\n annotations?: RelaxedRecord;\n}\n\n/** Relaxed column selector — convenient hand-written form. */\nexport interface RelaxedColumnSelector {\n name?: RelaxedStringMatchers;\n type?: ValueType | ValueType[];\n domain?: RelaxedRecord;\n contextDomain?: RelaxedRecord;\n annotations?: RelaxedRecord;\n axes?: RelaxedAxisSelector[];\n partialAxesMatch?: boolean;\n}\n\n/** Input that normalizes to ColumnSelector[]. */\nexport type ColumnSelectorInput = RelaxedColumnSelector | RelaxedColumnSelector[];\n\n// --- Normalization ---\n\nfunction normalizeStringMatchers(input: RelaxedStringMatchers): StringMatcher[] {\n if (typeof input === \"string\") return [{ type: \"regex\", value: input }];\n if (!Array.isArray(input)) return [input];\n return input.map((v) =>\n typeof v === \"string\" ? ({ type: \"regex\", value: v } satisfies StringMatcher) : v,\n );\n}\n\nfunction normalizeRecord(input: RelaxedRecord): Record<string, StringMatcher[]> {\n const result: Record<string, StringMatcher[]> = {};\n for (const [key, value] of Object.entries(input)) {\n result[key] = normalizeStringMatchers(value);\n }\n return result;\n}\n\nfunction normalizeTypes(input: ValueType | ValueType[]): ValueType[] {\n return Array.isArray(input) ? input : [input];\n}\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\nfunction normalizeAxisSelector(input: RelaxedAxisSelector): MultiAxisSelector {\n const result: Mutable<MultiAxisSelector> = {};\n if (input.name !== undefined) result.name = normalizeStringMatchers(input.name);\n if (input.type !== undefined) result.type = normalizeTypes(input.type);\n if (input.domain !== undefined) result.domain = normalizeRecord(input.domain);\n if (input.contextDomain !== undefined)\n result.contextDomain = normalizeRecord(input.contextDomain);\n if (input.annotations !== undefined) result.annotations = normalizeRecord(input.annotations);\n return result;\n}\n\n/** Normalize relaxed input to strict ColumnSelector[]. */\nexport function normalizeSelectors(input: ColumnSelectorInput): MultiColumnSelector[] {\n const arr = Array.isArray(input) ? input : [input];\n return arr.map(normalizeSingleSelector);\n}\n\nfunction normalizeSingleSelector(input: RelaxedColumnSelector): MultiColumnSelector {\n const result: Mutable<MultiColumnSelector> = {};\n if (input.name !== undefined) result.name = normalizeStringMatchers(input.name);\n if (input.type !== undefined) result.type = normalizeTypes(input.type);\n if (input.domain !== undefined) result.domain = normalizeRecord(input.domain);\n if (input.contextDomain !== undefined)\n result.contextDomain = normalizeRecord(input.contextDomain);\n if (input.annotations !== undefined) result.annotations = normalizeRecord(input.annotations);\n if (input.axes !== undefined) result.axes = input.axes.map(normalizeAxisSelector);\n if (input.partialAxesMatch !== undefined) result.partialAxesMatch = input.partialAxesMatch;\n return result;\n}\n\n// --- Matching ---\n\nfunction matchStringValue(value: string, matchers: StringMatcher[]): boolean {\n return matchers.some((m) => {\n if (m.type === \"exact\") return value === m.value;\n return new RegExp(`^(?:${m.value})$`).test(value);\n });\n}\n\nfunction matchRecordField(\n actual: Record<string, string> | undefined,\n required: Record<string, StringMatcher[]>,\n): boolean {\n const record = actual ?? {};\n for (const [key, matchers] of Object.entries(required)) {\n const value = record[key];\n if (value === undefined) return false;\n if (!matchStringValue(value, matchers)) return false;\n }\n return true;\n}\n\n/** Get combined domain: column's own domain merged with all axis domains. */\nfunction getCombinedDomain(spec: PColumnSpec): Record<string, string> {\n const result: Record<string, string> = {};\n if (spec.domain) Object.assign(result, spec.domain);\n for (const axis of spec.axesSpec) {\n if (axis.domain) Object.assign(result, axis.domain);\n }\n return result;\n}\n\n/** Get combined context domain: column's own contextDomain merged with all axis contextDomains. */\nfunction getCombinedContextDomain(spec: PColumnSpec): Record<string, string> {\n const result: Record<string, string> = {};\n if (spec.contextDomain) Object.assign(result, spec.contextDomain);\n for (const axis of spec.axesSpec) {\n if (\"contextDomain\" in axis && axis.contextDomain) Object.assign(result, axis.contextDomain);\n }\n return result;\n}\n\nfunction matchAxisSelector(\n axis: PColumnSpec[\"axesSpec\"][number],\n selector: MultiAxisSelector,\n): boolean {\n if (selector.name !== undefined && !matchStringValue(axis.name, selector.name)) return false;\n if (selector.type !== undefined && !selector.type.includes(axis.type as ValueType)) return false;\n if (selector.domain !== undefined && !matchRecordField(axis.domain, selector.domain))\n return false;\n if (\n selector.contextDomain !== undefined &&\n !matchRecordField(\n \"contextDomain\" in axis ? (axis.contextDomain as Record<string, string>) : undefined,\n selector.contextDomain,\n )\n )\n return false;\n if (\n selector.annotations !== undefined &&\n !matchRecordField(axis.annotations, selector.annotations)\n )\n return false;\n return true;\n}\n\n/** Check if a PColumnSpec matches a single strict ColumnSelector. */\nexport function matchColumn(spec: PColumnSpec, selector: MultiColumnSelector): boolean {\n if (selector.name !== undefined && !matchStringValue(spec.name, selector.name)) return false;\n if (selector.type !== undefined && !selector.type.includes(spec.valueType)) return false;\n\n if (selector.domain !== undefined) {\n const combined = getCombinedDomain(spec);\n if (!matchRecordField(combined, selector.domain)) return false;\n }\n\n if (selector.contextDomain !== undefined) {\n const combined = getCombinedContextDomain(spec);\n if (!matchRecordField(combined, selector.contextDomain)) return false;\n }\n\n if (selector.annotations !== undefined) {\n if (!matchRecordField(spec.annotations, selector.annotations)) return false;\n }\n\n if (selector.axes !== undefined) {\n const partialMatch = selector.partialAxesMatch ?? true;\n if (partialMatch) {\n for (const axisSel of selector.axes) {\n if (!spec.axesSpec.some((axis) => matchAxisSelector(axis, axisSel))) return false;\n }\n } else {\n if (spec.axesSpec.length !== selector.axes.length) return false;\n for (let i = 0; i < selector.axes.length; i++) {\n if (!matchAxisSelector(spec.axesSpec[i], selector.axes[i])) return false;\n }\n }\n }\n\n return true;\n}\n\n/** Check if a PColumnSpec matches any of the selectors (OR across array). */\nexport function matchColumnSelectors(selectors: MultiColumnSelector[], spec: PColumnSpec): boolean {\n return selectors.some((sel) => matchColumn(spec, sel));\n}\n\n/**\n * Convert selector input to a predicate function.\n * Normalizes relaxed form, then returns a function that OR-matches.\n */\nexport function columnSelectorsToPredicate(\n input: ColumnSelectorInput,\n): (spec: PColumnSpec) => boolean {\n const selectors = normalizeSelectors(input);\n return (spec) => matchColumnSelectors(selectors, spec);\n}\n"],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { MultiColumnSelector, PColumnSpec, StringMatcher, StringMatcher as StringMatcher$1, ValueType } from "@milaboratories/pl-model-common";
2
+
3
+ //#region src/columns/column_selector.d.ts
4
+ /** Relaxed string matcher input: plain string, single matcher, or array of mixed. */
5
+ type RelaxedStringMatchers = string | StringMatcher | (string | StringMatcher)[];
6
+ /** Relaxed record matcher: values can be plain strings or relaxed matchers. */
7
+ type RelaxedRecord = Record<string, RelaxedStringMatchers>;
8
+ /** Relaxed axis selector — accepts plain strings where strict requires StringMatcher[]. */
9
+ interface RelaxedAxisSelector {
10
+ name?: RelaxedStringMatchers;
11
+ type?: ValueType | ValueType[];
12
+ domain?: RelaxedRecord;
13
+ contextDomain?: RelaxedRecord;
14
+ annotations?: RelaxedRecord;
15
+ }
16
+ /** Relaxed column selector — convenient hand-written form. */
17
+ interface RelaxedColumnSelector {
18
+ name?: RelaxedStringMatchers;
19
+ type?: ValueType | ValueType[];
20
+ domain?: RelaxedRecord;
21
+ contextDomain?: RelaxedRecord;
22
+ annotations?: RelaxedRecord;
23
+ axes?: RelaxedAxisSelector[];
24
+ partialAxesMatch?: boolean;
25
+ }
26
+ /** Input that normalizes to ColumnSelector[]. */
27
+ type ColumnSelectorInput = RelaxedColumnSelector | RelaxedColumnSelector[];
28
+ /** Normalize relaxed input to strict ColumnSelector[]. */
29
+ declare function normalizeSelectors(input: ColumnSelectorInput): MultiColumnSelector[];
30
+ /** Check if a PColumnSpec matches a single strict ColumnSelector. */
31
+ declare function matchColumn(spec: PColumnSpec, selector: MultiColumnSelector): boolean;
32
+ /** Check if a PColumnSpec matches any of the selectors (OR across array). */
33
+ declare function matchColumnSelectors(selectors: MultiColumnSelector[], spec: PColumnSpec): boolean;
34
+ /**
35
+ * Convert selector input to a predicate function.
36
+ * Normalizes relaxed form, then returns a function that OR-matches.
37
+ */
38
+ declare function columnSelectorsToPredicate(input: ColumnSelectorInput): (spec: PColumnSpec) => boolean;
39
+ //#endregion
40
+ export { ColumnSelectorInput, RelaxedAxisSelector, RelaxedColumnSelector, RelaxedRecord, RelaxedStringMatchers, type StringMatcher$1 as StringMatcher, columnSelectorsToPredicate, matchColumn, matchColumnSelectors, normalizeSelectors };
41
+ //# sourceMappingURL=column_selector.d.ts.map