@platforma-sdk/model 1.59.3 → 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.
- package/dist/block_storage.cjs.map +1 -1
- package/dist/block_storage.d.ts +1 -11
- package/dist/block_storage.js.map +1 -1
- package/dist/block_storage_callbacks.cjs.map +1 -1
- package/dist/block_storage_callbacks.js.map +1 -1
- package/dist/columns/column_collection_builder.cjs +215 -0
- package/dist/columns/column_collection_builder.cjs.map +1 -0
- package/dist/columns/column_collection_builder.d.ts +112 -0
- package/dist/columns/column_collection_builder.js +214 -0
- package/dist/columns/column_collection_builder.js.map +1 -0
- package/dist/columns/column_selector.cjs +122 -0
- package/dist/columns/column_selector.cjs.map +1 -0
- package/dist/columns/column_selector.d.ts +41 -0
- package/dist/columns/column_selector.js +118 -0
- package/dist/columns/column_selector.js.map +1 -0
- package/dist/columns/column_snapshot.cjs +20 -0
- package/dist/columns/column_snapshot.cjs.map +1 -0
- package/dist/columns/column_snapshot.d.ts +39 -0
- package/dist/columns/column_snapshot.js +18 -0
- package/dist/columns/column_snapshot.js.map +1 -0
- package/dist/columns/column_snapshot_provider.cjs +112 -0
- package/dist/columns/column_snapshot_provider.cjs.map +1 -0
- package/dist/columns/column_snapshot_provider.d.ts +73 -0
- package/dist/columns/column_snapshot_provider.js +107 -0
- package/dist/columns/column_snapshot_provider.js.map +1 -0
- package/dist/columns/ctx_column_sources.cjs +84 -0
- package/dist/columns/ctx_column_sources.cjs.map +1 -0
- package/dist/columns/ctx_column_sources.d.ts +33 -0
- package/dist/columns/ctx_column_sources.js +82 -0
- package/dist/columns/ctx_column_sources.js.map +1 -0
- package/dist/columns/index.cjs +5 -0
- package/dist/columns/index.d.ts +5 -0
- package/dist/columns/index.js +5 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +111 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +25 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +110 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -0
- package/dist/components/PlDataTable/{table.cjs → createPlDataTable/createPlDataTableV3.cjs} +54 -54
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +39 -0
- package/dist/components/PlDataTable/{table.js → createPlDataTable/createPlDataTableV3.js} +53 -53
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/index.cjs +12 -0
- package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts +15 -0
- package/dist/components/PlDataTable/createPlDataTable/index.js +12 -0
- package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -0
- package/dist/components/PlDataTable/createPlDataTableSheet.cjs +18 -0
- package/dist/components/PlDataTable/createPlDataTableSheet.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTableSheet.d.ts +11 -0
- package/dist/components/PlDataTable/createPlDataTableSheet.js +17 -0
- package/dist/components/PlDataTable/createPlDataTableSheet.js.map +1 -0
- package/dist/components/PlDataTable/index.cjs +4 -1
- package/dist/components/PlDataTable/index.d.ts +5 -2
- package/dist/components/PlDataTable/index.js +4 -1
- package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
- package/dist/components/PlDataTable/state-migration.d.ts +2 -2
- package/dist/components/PlDataTable/state-migration.js.map +1 -1
- package/dist/components/PlDataTable/{v4.d.ts → typesV4.d.ts} +2 -2
- package/dist/components/PlDataTable/{v5.d.ts → typesV5.d.ts} +2 -2
- package/dist/components/index.cjs +4 -1
- package/dist/components/index.d.ts +5 -2
- package/dist/components/index.js +4 -1
- package/dist/index.cjs +44 -16
- package/dist/index.d.ts +17 -5
- package/dist/index.js +15 -3
- package/dist/labels/derive_distinct_labels.cjs +156 -0
- package/dist/labels/derive_distinct_labels.cjs.map +1 -0
- package/dist/labels/derive_distinct_labels.d.ts +29 -0
- package/dist/labels/derive_distinct_labels.js +155 -0
- package/dist/labels/derive_distinct_labels.js.map +1 -0
- package/dist/labels/index.cjs +2 -0
- package/dist/labels/index.d.ts +2 -0
- package/dist/labels/index.js +2 -0
- package/dist/labels/write_labels_to_specs.cjs +15 -0
- package/dist/labels/write_labels_to_specs.cjs.map +1 -0
- package/dist/labels/write_labels_to_specs.d.ts +9 -0
- package/dist/labels/write_labels_to_specs.js +14 -0
- package/dist/labels/write_labels_to_specs.js.map +1 -0
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/render/api.cjs +11 -2
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +9 -5
- package/dist/render/api.js +12 -3
- package/dist/render/api.js.map +1 -1
- package/dist/render/index.d.ts +2 -1
- package/dist/render/index.js +1 -1
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts +5 -2
- package/dist/render/internal.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 +3 -2
- package/dist/render/util/column_collection.js +4 -4
- package/dist/render/util/column_collection.js.map +1 -1
- package/dist/render/util/index.d.ts +2 -1
- package/dist/render/util/index.js +1 -1
- package/dist/render/util/label.cjs +7 -134
- package/dist/render/util/label.cjs.map +1 -1
- package/dist/render/util/label.d.ts +5 -50
- package/dist/render/util/label.js +8 -132
- package/dist/render/util/label.js.map +1 -1
- package/dist/render/util/split_selectors.d.ts +2 -2
- package/package.json +9 -7
- package/src/block_storage.ts +0 -11
- package/src/block_storage_callbacks.ts +1 -1
- package/src/columns/column_collection_builder.test.ts +427 -0
- package/src/columns/column_collection_builder.ts +455 -0
- package/src/columns/column_selector.test.ts +472 -0
- package/src/columns/column_selector.ts +212 -0
- package/src/columns/column_snapshot.ts +55 -0
- package/src/columns/column_snapshot_provider.ts +177 -0
- package/src/columns/ctx_column_sources.ts +107 -0
- package/src/columns/expand_by_partition.test.ts +289 -0
- package/src/columns/expand_by_partition.ts +187 -0
- package/src/columns/index.ts +5 -0
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +193 -0
- package/src/components/PlDataTable/{table.ts → createPlDataTable/createPlDataTableV3.ts} +134 -70
- package/src/components/PlDataTable/createPlDataTable/index.ts +27 -0
- package/src/components/PlDataTable/createPlDataTableSheet.ts +20 -0
- package/src/components/PlDataTable/index.ts +6 -4
- package/src/components/PlDataTable/state-migration.ts +2 -2
- package/src/index.ts +2 -1
- package/src/labels/derive_distinct_labels.test.ts +461 -0
- package/src/labels/derive_distinct_labels.ts +289 -0
- package/src/labels/index.ts +2 -0
- package/src/labels/write_labels_to_specs.ts +12 -0
- package/src/render/api.ts +25 -3
- package/src/render/internal.ts +20 -1
- package/src/render/util/column_collection.ts +9 -6
- package/src/render/util/label.test.ts +1 -1
- package/src/render/util/label.ts +19 -235
- package/src/render/util/split_selectors.ts +3 -3
- package/dist/components/PlDataTable/table.cjs.map +0 -1
- package/dist/components/PlDataTable/table.d.ts +0 -30
- package/dist/components/PlDataTable/table.js.map +0 -1
- /package/src/components/PlDataTable/{v4.ts → typesV4.ts} +0 -0
- /package/src/components/PlDataTable/{v5.ts → typesV5.ts} +0 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Annotation,
|
|
3
|
+
parseJson,
|
|
4
|
+
readAnnotation,
|
|
5
|
+
type CanonicalizedJson,
|
|
6
|
+
type PObjectSpec,
|
|
7
|
+
} from "@milaboratories/pl-model-common";
|
|
8
|
+
import { throwError } from "@milaboratories/helpers";
|
|
9
|
+
|
|
10
|
+
const DISTANCE_PENALTY = 0.001;
|
|
11
|
+
const LABEL_TYPE = "__LABEL__";
|
|
12
|
+
const LABEL_TYPE_FULL = "__LABEL__@1";
|
|
13
|
+
|
|
14
|
+
export type WithLabel<T> = {
|
|
15
|
+
value: T;
|
|
16
|
+
label: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type TraceEntry = {
|
|
20
|
+
id?: string;
|
|
21
|
+
type: string;
|
|
22
|
+
label: string;
|
|
23
|
+
importance?: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type Trace = TraceEntry[];
|
|
27
|
+
|
|
28
|
+
export type Entry =
|
|
29
|
+
| PObjectSpec
|
|
30
|
+
| { spec: PObjectSpec; prefixTrace?: TraceEntry[]; suffixTrace?: TraceEntry[] };
|
|
31
|
+
|
|
32
|
+
export type DeriveLabelsOptions = {
|
|
33
|
+
/** Separator to use between label parts (" / " by default) */
|
|
34
|
+
separator?: string;
|
|
35
|
+
/** If true, label will be added as suffix (at the end of the generated label). By default label added as a prefix. */
|
|
36
|
+
addLabelAsSuffix?: boolean;
|
|
37
|
+
/** Force inclusion of native column label */
|
|
38
|
+
includeNativeLabel?: boolean;
|
|
39
|
+
/** Trace elements list that will be forced to be included in the label. */
|
|
40
|
+
forceTraceElements?: string[];
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export function deriveDistinctLabels<T extends Entry>(
|
|
44
|
+
values: T[],
|
|
45
|
+
options: DeriveLabelsOptions = {},
|
|
46
|
+
): WithLabel<T>[] {
|
|
47
|
+
const forceTraceElements =
|
|
48
|
+
options.forceTraceElements !== undefined && options.forceTraceElements.length > 0
|
|
49
|
+
? new Set(options.forceTraceElements)
|
|
50
|
+
: undefined;
|
|
51
|
+
const separator = options.separator ?? " / ";
|
|
52
|
+
|
|
53
|
+
// Phase 1: enrich each value with parsed trace
|
|
54
|
+
const records = values.map((v) => enrichRecord(v, options));
|
|
55
|
+
|
|
56
|
+
// Phase 2: collect global type statistics
|
|
57
|
+
const stats = collectTypeStats(records);
|
|
58
|
+
|
|
59
|
+
// Phase 3: classify types into main (present everywhere) and secondary
|
|
60
|
+
const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);
|
|
61
|
+
|
|
62
|
+
const build = (typeSet: Set<string>, force: boolean) =>
|
|
63
|
+
buildLabels(records, typeSet, forceTraceElements, separator, force);
|
|
64
|
+
|
|
65
|
+
if (mainTypes.length === 0) {
|
|
66
|
+
if (secondaryTypes.length !== 0)
|
|
67
|
+
throw new Error("Non-empty secondary types list while main types list is empty.");
|
|
68
|
+
return build(new Set(LABEL_TYPE_FULL), true)!;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Phase 4: search for minimal type set that produces unique labels
|
|
72
|
+
//
|
|
73
|
+
// includedCount = 2
|
|
74
|
+
// * *
|
|
75
|
+
// T0 T1 T2 T3 T4 T5
|
|
76
|
+
// *
|
|
77
|
+
// additionalType = 3
|
|
78
|
+
//
|
|
79
|
+
// Resulting set: T0, T1, T3
|
|
80
|
+
//
|
|
81
|
+
let includedCount = 0;
|
|
82
|
+
let additionalType = -1;
|
|
83
|
+
while (includedCount < mainTypes.length) {
|
|
84
|
+
const currentSet = new Set<string>();
|
|
85
|
+
if (options.includeNativeLabel) currentSet.add(LABEL_TYPE_FULL);
|
|
86
|
+
for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);
|
|
87
|
+
if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);
|
|
88
|
+
|
|
89
|
+
const candidateResult = build(currentSet, false);
|
|
90
|
+
if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {
|
|
91
|
+
const minimized = minimizeTypeSet(
|
|
92
|
+
currentSet,
|
|
93
|
+
records,
|
|
94
|
+
stats,
|
|
95
|
+
forceTraceElements,
|
|
96
|
+
options,
|
|
97
|
+
separator,
|
|
98
|
+
);
|
|
99
|
+
return build(minimized, false) ?? throwError("Failed to derive unique labels");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
additionalType++;
|
|
103
|
+
if (additionalType >= mainTypes.length) {
|
|
104
|
+
includedCount++;
|
|
105
|
+
additionalType = includedCount;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Fallback: include all types, then minimize
|
|
110
|
+
const fallbackSet = new Set([...mainTypes, ...secondaryTypes]);
|
|
111
|
+
const minimized = minimizeTypeSet(
|
|
112
|
+
fallbackSet,
|
|
113
|
+
records,
|
|
114
|
+
stats,
|
|
115
|
+
forceTraceElements,
|
|
116
|
+
options,
|
|
117
|
+
separator,
|
|
118
|
+
);
|
|
119
|
+
return build(minimized, true) ?? throwError("Failed to derive unique labels");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// --- Pure helpers ---
|
|
123
|
+
type FullTraceEntry = TraceEntry & { fullType: string; occurrenceIndex: number };
|
|
124
|
+
|
|
125
|
+
type EnrichedRecord<T> = {
|
|
126
|
+
value: T;
|
|
127
|
+
fullTrace: FullTraceEntry[];
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
function extractSpecAndTrace(entry: Entry): {
|
|
131
|
+
spec: PObjectSpec;
|
|
132
|
+
prefixTrace: TraceEntry[] | undefined;
|
|
133
|
+
suffixTrace: TraceEntry[] | undefined;
|
|
134
|
+
} {
|
|
135
|
+
if ("spec" in entry && typeof entry.spec === "object") {
|
|
136
|
+
return { spec: entry.spec, prefixTrace: entry.prefixTrace, suffixTrace: entry.suffixTrace };
|
|
137
|
+
}
|
|
138
|
+
return { spec: entry as PObjectSpec, prefixTrace: undefined, suffixTrace: undefined };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function buildFullTrace(trace: TraceEntry[]): FullTraceEntry[] {
|
|
142
|
+
const result: FullTraceEntry[] = [];
|
|
143
|
+
const occurrences = new Map<string, number>();
|
|
144
|
+
|
|
145
|
+
for (let i = trace.length - 1; i >= 0; --i) {
|
|
146
|
+
const entry = trace[i];
|
|
147
|
+
const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;
|
|
148
|
+
occurrences.set(entry.type, occurrenceIndex);
|
|
149
|
+
result.push({
|
|
150
|
+
...entry,
|
|
151
|
+
fullType: `${entry.type}@${occurrenceIndex}`,
|
|
152
|
+
occurrenceIndex,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
result.reverse();
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function enrichRecord<T extends Entry>(value: T, options: DeriveLabelsOptions): EnrichedRecord<T> {
|
|
161
|
+
const { spec, prefixTrace, suffixTrace } = extractSpecAndTrace(value);
|
|
162
|
+
|
|
163
|
+
const label = readAnnotation(spec, Annotation.Label);
|
|
164
|
+
const traceStr = readAnnotation(spec, Annotation.Trace) as
|
|
165
|
+
| CanonicalizedJson<TraceEntry[]>
|
|
166
|
+
| undefined;
|
|
167
|
+
const baseTrace: Trace = traceStr ? (parseJson<Trace>(traceStr) ?? []) : [];
|
|
168
|
+
const trace = [...(prefixTrace ?? []), ...baseTrace, ...(suffixTrace ?? [])];
|
|
169
|
+
|
|
170
|
+
if (label !== undefined) {
|
|
171
|
+
const labelEntry = { label, type: LABEL_TYPE, importance: -2 };
|
|
172
|
+
if (options.addLabelAsSuffix) trace.push(labelEntry);
|
|
173
|
+
else trace.splice(0, 0, labelEntry);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return { value, fullTrace: buildFullTrace(trace) };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
type TypeStats = {
|
|
180
|
+
importances: Map<string, number>;
|
|
181
|
+
countByType: Map<string, number>;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
function collectTypeStats<T>(records: EnrichedRecord<T>[]): TypeStats {
|
|
185
|
+
const importances = new Map<string, number>();
|
|
186
|
+
const countByType = new Map<string, number>();
|
|
187
|
+
|
|
188
|
+
for (const record of records) {
|
|
189
|
+
for (let i = 0; i < record.fullTrace.length; i++) {
|
|
190
|
+
const { fullType, importance: rawImportance } = record.fullTrace[i];
|
|
191
|
+
const importance = rawImportance ?? 0;
|
|
192
|
+
const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;
|
|
193
|
+
|
|
194
|
+
countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);
|
|
195
|
+
importances.set(
|
|
196
|
+
fullType,
|
|
197
|
+
Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return { importances, countByType };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function classifyTypes(
|
|
206
|
+
stats: TypeStats,
|
|
207
|
+
totalRecords: number,
|
|
208
|
+
): { mainTypes: string[]; secondaryTypes: string[] } {
|
|
209
|
+
const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);
|
|
210
|
+
|
|
211
|
+
const mainTypes: string[] = [];
|
|
212
|
+
const secondaryTypes: string[] = [];
|
|
213
|
+
|
|
214
|
+
for (const [typeName] of sorted) {
|
|
215
|
+
if (typeName.endsWith("@1") || stats.countByType.get(typeName) === totalRecords)
|
|
216
|
+
mainTypes.push(typeName);
|
|
217
|
+
else secondaryTypes.push(typeName);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return { mainTypes, secondaryTypes };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function buildLabels<T>(
|
|
224
|
+
records: EnrichedRecord<T>[],
|
|
225
|
+
includedTypes: Set<string>,
|
|
226
|
+
forceTraceElements: Set<string> | undefined,
|
|
227
|
+
separator: string,
|
|
228
|
+
force: boolean,
|
|
229
|
+
): WithLabel<T>[] | undefined {
|
|
230
|
+
const result: WithLabel<T>[] = [];
|
|
231
|
+
|
|
232
|
+
for (const r of records) {
|
|
233
|
+
const parts: string[] = [];
|
|
234
|
+
for (const ft of r.fullTrace) {
|
|
235
|
+
if (includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type)) {
|
|
236
|
+
parts.push(ft.label);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (parts.length === 0) {
|
|
241
|
+
if (!force) return undefined;
|
|
242
|
+
result.push({ label: "Unlabeled", value: r.value });
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
result.push({ label: parts.join(separator), value: r.value });
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function countUniqueLabels<T>(result: WithLabel<T>[] | undefined): number {
|
|
253
|
+
if (result === undefined) return 0;
|
|
254
|
+
return new Set(result.map((c) => c.label)).size;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function minimizeTypeSet<T>(
|
|
258
|
+
typeSet: Set<string>,
|
|
259
|
+
records: EnrichedRecord<T>[],
|
|
260
|
+
stats: TypeStats,
|
|
261
|
+
forceTraceElements: Set<string> | undefined,
|
|
262
|
+
options: DeriveLabelsOptions,
|
|
263
|
+
separator: string,
|
|
264
|
+
): Set<string> {
|
|
265
|
+
const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);
|
|
266
|
+
if (initialResult === undefined) return typeSet;
|
|
267
|
+
|
|
268
|
+
const targetCardinality = countUniqueLabels(initialResult);
|
|
269
|
+
const result = new Set(typeSet);
|
|
270
|
+
|
|
271
|
+
const removable = [...result]
|
|
272
|
+
.filter(
|
|
273
|
+
(t) =>
|
|
274
|
+
!forceTraceElements?.has(t.split("@")[0]) &&
|
|
275
|
+
!(options.includeNativeLabel && t === LABEL_TYPE_FULL),
|
|
276
|
+
)
|
|
277
|
+
.sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));
|
|
278
|
+
|
|
279
|
+
for (const typeToRemove of removable) {
|
|
280
|
+
const candidate = new Set(result);
|
|
281
|
+
candidate.delete(typeToRemove);
|
|
282
|
+
const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);
|
|
283
|
+
if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {
|
|
284
|
+
result.delete(typeToRemove);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Annotation } from "@milaboratories/pl-model-common";
|
|
2
|
+
import type { ColumnSnapshot } from "../columns";
|
|
3
|
+
import type { WithLabel } from "./derive_distinct_labels";
|
|
4
|
+
|
|
5
|
+
export function writeLabelsToSpecs(items: WithLabel<ColumnSnapshot>[]): void {
|
|
6
|
+
for (const { value, label } of items) {
|
|
7
|
+
// @ts-expect-error - annotations are mutable at runtime, even if not in the type
|
|
8
|
+
value.spec.annotations = value.spec.annotations ?? {};
|
|
9
|
+
value.spec.annotations[Annotation.Label] = label;
|
|
10
|
+
value.spec.annotations["pl7.app/label/isDerived"] = "true";
|
|
11
|
+
}
|
|
12
|
+
}
|
package/src/render/api.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type {
|
|
|
3
3
|
AnyFunction,
|
|
4
4
|
AxisId,
|
|
5
5
|
DataInfo,
|
|
6
|
+
DiscoverColumnsRequest,
|
|
7
|
+
DiscoverColumnsResponse,
|
|
6
8
|
Option,
|
|
7
9
|
PColumn,
|
|
8
10
|
PColumnLazy,
|
|
@@ -43,8 +45,8 @@ import {
|
|
|
43
45
|
mapValueInVOE,
|
|
44
46
|
PColumnName,
|
|
45
47
|
readAnnotation,
|
|
46
|
-
selectorsToPredicate,
|
|
47
48
|
withEnrichments,
|
|
49
|
+
legacyColumnSelectorsToPredicate,
|
|
48
50
|
} from "@milaboratories/pl-model-common";
|
|
49
51
|
import canonicalize from "canonicalize";
|
|
50
52
|
import type { Optional } from "utility-types";
|
|
@@ -155,7 +157,7 @@ export class ResultPool implements ColumnProvider, AxisLabelProvider {
|
|
|
155
157
|
const predicate =
|
|
156
158
|
typeof predicateOrSelector === "function"
|
|
157
159
|
? predicateOrSelector
|
|
158
|
-
:
|
|
160
|
+
: legacyColumnSelectorsToPredicate(predicateOrSelector);
|
|
159
161
|
const filtered = this.getSpecs().entries.filter((s) => predicate(s.obj));
|
|
160
162
|
|
|
161
163
|
let labelOps: LabelDerivationOps | ((spec: PObjectSpec, ref: PlRef) => string) = {};
|
|
@@ -494,7 +496,8 @@ export class ResultPool implements ColumnProvider, AxisLabelProvider {
|
|
|
494
496
|
public selectColumns(
|
|
495
497
|
selectors: ((spec: PColumnSpec) => boolean) | PColumnSelector | PColumnSelector[],
|
|
496
498
|
): PColumn<TreeNodeAccessor | undefined>[] {
|
|
497
|
-
const predicate =
|
|
499
|
+
const predicate =
|
|
500
|
+
typeof selectors === "function" ? selectors : legacyColumnSelectorsToPredicate(selectors);
|
|
498
501
|
|
|
499
502
|
const matchedSpecs = this.getSpecs().entries.filter(({ obj: spec }) => {
|
|
500
503
|
if (!isPColumnSpec(spec)) return false;
|
|
@@ -709,6 +712,25 @@ export abstract class RenderCtxBase<Args = unknown, Data = unknown> {
|
|
|
709
712
|
return this.ctx.getBlockLabel(blockId);
|
|
710
713
|
}
|
|
711
714
|
|
|
715
|
+
//
|
|
716
|
+
// Spec Frames
|
|
717
|
+
//
|
|
718
|
+
|
|
719
|
+
public createSpecFrame(specs: Record<string, PColumnSpec>): string {
|
|
720
|
+
return this.ctx.createSpecFrame(specs);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
public specFrameDiscoverColumns(
|
|
724
|
+
handle: string,
|
|
725
|
+
request: DiscoverColumnsRequest,
|
|
726
|
+
): DiscoverColumnsResponse {
|
|
727
|
+
return this.ctx.specFrameDiscoverColumns(handle, request);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
public specFrameDispose(handle: string): void {
|
|
731
|
+
this.ctx.specFrameDispose(handle);
|
|
732
|
+
}
|
|
733
|
+
|
|
712
734
|
public getCurrentUnstableMarker(): string | undefined {
|
|
713
735
|
return this.ctx.getCurrentUnstableMarker();
|
|
714
736
|
}
|
package/src/render/internal.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { Optional } from "utility-types";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
Branded,
|
|
4
|
+
DiscoverColumnsRequest,
|
|
5
|
+
DiscoverColumnsResponse,
|
|
6
|
+
StringifiedJson,
|
|
7
|
+
} from "@milaboratories/pl-model-common";
|
|
3
8
|
import type { CommonFieldTraverseOps, FieldTraversalStep, ResourceType } from "./traversal_ops";
|
|
4
9
|
import type {
|
|
5
10
|
ArchiveFormat,
|
|
@@ -19,6 +24,7 @@ import type {
|
|
|
19
24
|
ValueOrError,
|
|
20
25
|
DataInfo,
|
|
21
26
|
RangeBytes,
|
|
27
|
+
PColumnSpec,
|
|
22
28
|
} from "@milaboratories/pl-model-common";
|
|
23
29
|
import type { TreeNodeAccessor } from "./accessor";
|
|
24
30
|
|
|
@@ -157,6 +163,19 @@ export interface GlobalCfgRenderCtxMethods<AHandle = AccessorHandle, FHandle = F
|
|
|
157
163
|
def: PTableDefV2<PColumn<AHandle | PColumnValues | DataInfo<AHandle>>>,
|
|
158
164
|
): PTableHandle;
|
|
159
165
|
|
|
166
|
+
//
|
|
167
|
+
// Spec Frames (synchronous WASM-based PFrame for spec-level operations)
|
|
168
|
+
//
|
|
169
|
+
|
|
170
|
+
createSpecFrame(specs: Record<string, PColumnSpec>): string;
|
|
171
|
+
|
|
172
|
+
specFrameDiscoverColumns(
|
|
173
|
+
handle: string,
|
|
174
|
+
request: DiscoverColumnsRequest,
|
|
175
|
+
): DiscoverColumnsResponse;
|
|
176
|
+
|
|
177
|
+
specFrameDispose(handle: string): void;
|
|
178
|
+
|
|
160
179
|
//
|
|
161
180
|
// Computable
|
|
162
181
|
//
|
|
@@ -25,17 +25,17 @@ import {
|
|
|
25
25
|
isLinkerColumn,
|
|
26
26
|
isPartitionedDataInfoEntries,
|
|
27
27
|
isPColumnSpec,
|
|
28
|
+
legacyColumnSelectorsToPredicate,
|
|
28
29
|
LinkerMap,
|
|
29
30
|
matchAxisId,
|
|
30
31
|
resolveAnchors,
|
|
31
|
-
selectorsToPredicate,
|
|
32
32
|
} from "@milaboratories/pl-model-common";
|
|
33
33
|
import canonicalize from "canonicalize";
|
|
34
34
|
import type { Optional } from "utility-types";
|
|
35
35
|
import type { TreeNodeAccessor } from "../accessor";
|
|
36
36
|
import type { PColumnDataUniversal } from "../internal";
|
|
37
37
|
import { filterDataInfoEntries } from "./axis_filtering";
|
|
38
|
-
import type { LabelDerivationOps
|
|
38
|
+
import type { LabelDerivationOps } from "./label";
|
|
39
39
|
import { deriveLabels } from "./label";
|
|
40
40
|
import { convertOrParsePColumnData, getUniquePartitionKeys } from "./pcolumn_data";
|
|
41
41
|
import type { APColumnSelectorWithSplit, PColumnSelectorWithSplit } from "./split_selectors";
|
|
@@ -66,7 +66,8 @@ class ArrayColumnProvider implements ColumnProvider {
|
|
|
66
66
|
selectColumns(
|
|
67
67
|
selectors: ((spec: PColumnSpec) => boolean) | PColumnSelector | PColumnSelector[],
|
|
68
68
|
): PColumn<PColumnDataUniversal | undefined>[] {
|
|
69
|
-
const predicate =
|
|
69
|
+
const predicate =
|
|
70
|
+
typeof selectors === "function" ? selectors : legacyColumnSelectorsToPredicate(selectors);
|
|
70
71
|
// Filter based on spec, ignoring data type for now
|
|
71
72
|
return this.columns.filter((column): column is PColumn<PColumnDataUniversal | undefined> =>
|
|
72
73
|
predicate(column.spec),
|
|
@@ -125,7 +126,7 @@ type IntermediateDirectEntry = {
|
|
|
125
126
|
// Union type for intermediate processing
|
|
126
127
|
type IntermediateColumnEntry = IntermediateSplitEntry | IntermediateDirectEntry;
|
|
127
128
|
|
|
128
|
-
function splitFiltersToTrace(splitFilters?: AxisFilterInfo[])
|
|
129
|
+
function splitFiltersToTrace(splitFilters?: AxisFilterInfo[]) {
|
|
129
130
|
if (!splitFilters) return undefined;
|
|
130
131
|
return splitFilters.map((filter) => ({
|
|
131
132
|
type: `split:${canonicalizeAxisId(filter.axisId)}`,
|
|
@@ -300,8 +301,10 @@ export class PColumnCollection {
|
|
|
300
301
|
throw new Error(
|
|
301
302
|
"Anchored selectors in exclude require an AnchoredIdDeriver to be provided in options.",
|
|
302
303
|
);
|
|
303
|
-
return
|
|
304
|
-
|
|
304
|
+
return legacyColumnSelectorsToPredicate(
|
|
305
|
+
resolveAnchors(anchorCtx.anchors, selector, opts),
|
|
306
|
+
);
|
|
307
|
+
} else return legacyColumnSelectorsToPredicate(selector);
|
|
305
308
|
});
|
|
306
309
|
excludePredicate = (spec) => excludePredicartes.some((predicate) => predicate(spec));
|
|
307
310
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Annotation, PColumnSpec } from "@milaboratories/pl-model-common";
|
|
2
2
|
import { expect, test } from "vitest";
|
|
3
|
-
import { deriveLabels, Trace } from "./label";
|
|
3
|
+
import { deriveLabels, type Trace } from "./label";
|
|
4
4
|
|
|
5
5
|
function tracesToSpecs(traces: Trace[]) {
|
|
6
6
|
return traces.map(
|