@platforma-sdk/model 1.53.15 → 1.54.8
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/annotations/converter.cjs +8 -32
- package/dist/annotations/converter.cjs.map +1 -1
- package/dist/annotations/converter.d.ts.map +1 -1
- package/dist/annotations/converter.js +7 -31
- package/dist/annotations/converter.js.map +1 -1
- package/dist/block_model.cjs +1 -0
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts.map +1 -1
- package/dist/block_model.js +1 -0
- package/dist/block_model.js.map +1 -1
- package/dist/builder.cjs +1 -0
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +1 -0
- package/dist/builder.js.map +1 -1
- package/dist/components/PlDataTable/index.d.ts +5 -0
- package/dist/components/PlDataTable/index.d.ts.map +1 -0
- package/dist/components/PlDataTable/labels.cjs +91 -0
- package/dist/components/PlDataTable/labels.cjs.map +1 -0
- package/dist/components/PlDataTable/labels.d.ts +7 -0
- package/dist/components/PlDataTable/labels.d.ts.map +1 -0
- package/dist/components/PlDataTable/labels.js +88 -0
- package/dist/components/PlDataTable/labels.js.map +1 -0
- package/dist/components/PlDataTable/state-migration.cjs +162 -0
- package/dist/components/PlDataTable/state-migration.cjs.map +1 -0
- package/dist/components/PlDataTable/state-migration.d.ts +94 -0
- package/dist/components/PlDataTable/state-migration.d.ts.map +1 -0
- package/dist/components/PlDataTable/state-migration.js +158 -0
- package/dist/components/PlDataTable/state-migration.js.map +1 -0
- package/dist/components/PlDataTable/table.cjs +187 -0
- package/dist/components/PlDataTable/table.cjs.map +1 -0
- package/dist/components/PlDataTable/table.d.ts +26 -0
- package/dist/components/PlDataTable/table.d.ts.map +1 -0
- package/dist/components/PlDataTable/table.js +183 -0
- package/dist/components/PlDataTable/table.js.map +1 -0
- package/dist/components/PlDataTable/v4.d.ts +157 -0
- package/dist/components/PlDataTable/v4.d.ts.map +1 -0
- package/dist/components/PlDataTable/v5.d.ts +114 -0
- package/dist/components/PlDataTable/v5.d.ts.map +1 -0
- package/dist/filters/converters/filterToQuery.cjs +244 -0
- package/dist/filters/converters/filterToQuery.cjs.map +1 -0
- package/dist/filters/converters/filterToQuery.d.ts +4 -0
- package/dist/filters/converters/filterToQuery.d.ts.map +1 -0
- package/dist/filters/converters/filterToQuery.js +242 -0
- package/dist/filters/converters/filterToQuery.js.map +1 -0
- package/dist/filters/{converter.cjs → converters/filterUiToExpressionImpl.cjs} +3 -2
- package/dist/filters/converters/filterUiToExpressionImpl.cjs.map +1 -0
- package/dist/filters/{converter.d.ts → converters/filterUiToExpressionImpl.d.ts} +2 -2
- package/dist/filters/converters/filterUiToExpressionImpl.d.ts.map +1 -0
- package/dist/filters/{converter.js → converters/filterUiToExpressionImpl.js} +3 -2
- package/dist/filters/converters/filterUiToExpressionImpl.js.map +1 -0
- package/dist/filters/converters/index.d.ts +3 -0
- package/dist/filters/converters/index.d.ts.map +1 -0
- package/dist/filters/distill.cjs +61 -0
- package/dist/filters/distill.cjs.map +1 -0
- package/dist/filters/distill.d.ts +7 -0
- package/dist/filters/distill.d.ts.map +1 -0
- package/dist/filters/distill.js +59 -0
- package/dist/filters/distill.js.map +1 -0
- package/dist/filters/index.d.ts +2 -1
- package/dist/filters/index.d.ts.map +1 -1
- package/dist/filters/types.d.ts +1 -117
- package/dist/filters/types.d.ts.map +1 -1
- package/dist/index.cjs +17 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/package.json.cjs +1 -1
- package/dist/package.json.js +1 -1
- package/dist/pframe_utils/columns.cjs +2 -0
- package/dist/pframe_utils/columns.cjs.map +1 -1
- package/dist/pframe_utils/columns.js +2 -0
- package/dist/pframe_utils/columns.js.map +1 -1
- package/dist/pframe_utils/index.cjs +2 -0
- package/dist/pframe_utils/index.cjs.map +1 -1
- package/dist/pframe_utils/index.js +2 -0
- package/dist/pframe_utils/index.js.map +1 -1
- package/dist/pframe_utils/querySpec.d.ts +2 -0
- package/dist/pframe_utils/querySpec.d.ts.map +1 -0
- package/dist/render/api.cjs +7 -0
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +3 -2
- package/dist/render/api.d.ts.map +1 -1
- package/dist/render/api.js +8 -1
- package/dist/render/api.js.map +1 -1
- package/dist/render/future.d.ts +1 -1
- package/dist/render/index.d.ts +2 -1
- package/dist/render/index.d.ts.map +1 -1
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts +4 -1
- package/dist/render/internal.d.ts.map +1 -1
- package/dist/render/internal.js.map +1 -1
- package/dist/render/util/column_collection.cjs.map +1 -1
- package/dist/render/util/column_collection.d.ts +1 -1
- package/dist/render/util/column_collection.d.ts.map +1 -1
- package/dist/render/util/column_collection.js.map +1 -1
- package/dist/render/util/pcolumn_data.cjs.map +1 -1
- package/dist/render/util/pcolumn_data.d.ts +1 -1
- package/dist/render/util/pcolumn_data.d.ts.map +1 -1
- package/dist/render/util/pcolumn_data.js.map +1 -1
- package/package.json +8 -6
- package/src/annotations/converter.ts +12 -40
- package/src/block_model.ts +1 -0
- package/src/builder.ts +1 -0
- package/src/components/PlDataTable/index.ts +24 -0
- package/src/components/PlDataTable/labels.ts +101 -0
- package/src/components/PlDataTable/state-migration.ts +285 -0
- package/src/components/PlDataTable/table.ts +278 -0
- package/src/components/PlDataTable/v4.ts +193 -0
- package/src/components/PlDataTable/v5.ts +140 -0
- package/src/filters/converters/filterToQuery.test.ts +417 -0
- package/src/filters/converters/filterToQuery.ts +258 -0
- package/src/filters/{converter.test.ts → converters/filterUiToExpressionImpl.test.ts} +2 -2
- package/src/filters/{converter.ts → converters/filterUiToExpressionImpl.ts} +3 -2
- package/src/filters/converters/index.ts +2 -0
- package/src/filters/distill.test.ts +191 -0
- package/src/filters/distill.ts +67 -0
- package/src/filters/index.ts +2 -1
- package/src/filters/types.ts +7 -48
- package/src/pframe_utils/querySpec.ts +1 -0
- package/src/render/api.ts +13 -6
- package/src/render/index.ts +2 -1
- package/src/render/internal.ts +11 -0
- package/src/render/util/column_collection.ts +1 -1
- package/src/render/util/pcolumn_data.ts +1 -1
- package/dist/components/PlDataTable.cjs +0 -307
- package/dist/components/PlDataTable.cjs.map +0 -1
- package/dist/components/PlDataTable.d.ts +0 -366
- package/dist/components/PlDataTable.d.ts.map +0 -1
- package/dist/components/PlDataTable.js +0 -297
- package/dist/components/PlDataTable.js.map +0 -1
- package/dist/filters/converter.cjs.map +0 -1
- package/dist/filters/converter.d.ts.map +0 -1
- package/dist/filters/converter.js.map +0 -1
- package/src/components/PlDataTable.ts +0 -794
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import type { FilterSpec, FilterSpecLeaf } from "@milaboratories/pl-model-common";
|
|
3
|
+
import { distillFilterSpec } from "./distill";
|
|
4
|
+
|
|
5
|
+
type F = FilterSpec<FilterSpecLeaf<string>>;
|
|
6
|
+
|
|
7
|
+
const leaf: F = { type: "equal", column: "c1", x: 1 };
|
|
8
|
+
const emptyLeaf: F = { type: undefined };
|
|
9
|
+
const incompleteLeaf: F = { type: "equal", column: "c1", x: undefined as unknown as number };
|
|
10
|
+
|
|
11
|
+
describe("distillFilterSpec", () => {
|
|
12
|
+
it("returns null for null input", () => {
|
|
13
|
+
expect(distillFilterSpec(null)).toBeNull();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("returns null for undefined input", () => {
|
|
17
|
+
expect(distillFilterSpec(undefined)).toBeNull();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("returns valid leaf as-is", () => {
|
|
21
|
+
expect(distillFilterSpec(leaf)).toEqual(leaf);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("returns null for empty leaf", () => {
|
|
25
|
+
expect(distillFilterSpec(emptyLeaf)).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("returns null for incomplete leaf", () => {
|
|
29
|
+
expect(distillFilterSpec(incompleteLeaf)).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// --- distill (strips extra metadata) ---
|
|
33
|
+
|
|
34
|
+
it("strips non-FilterSpec metadata from leaf", () => {
|
|
35
|
+
const leafWithMeta = { type: "equal" as const, column: "c1", x: 1, _extra: true, label: "hi" };
|
|
36
|
+
expect(distillFilterSpec(leafWithMeta)).toEqual({ type: "equal", column: "c1", x: 1 });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("strips non-FilterSpec metadata from nested nodes", () => {
|
|
40
|
+
const filter = {
|
|
41
|
+
type: "and" as const,
|
|
42
|
+
filters: [{ type: "equal" as const, column: "c1", x: 1, _meta: "remove" }],
|
|
43
|
+
_rootMeta: 42,
|
|
44
|
+
};
|
|
45
|
+
expect(distillFilterSpec(filter)).toEqual({
|
|
46
|
+
type: "and",
|
|
47
|
+
filters: [{ type: "equal", column: "c1", x: 1 }],
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// --- and ---
|
|
52
|
+
|
|
53
|
+
it("filters out empty children from and", () => {
|
|
54
|
+
const filter: F = { type: "and", filters: [emptyLeaf, leaf, emptyLeaf] };
|
|
55
|
+
expect(distillFilterSpec(filter)).toEqual({ type: "and", filters: [leaf] });
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("returns null when all and children are empty", () => {
|
|
59
|
+
const filter: F = { type: "and", filters: [emptyLeaf, emptyLeaf] };
|
|
60
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns null for and with no children", () => {
|
|
64
|
+
const filter: F = { type: "and", filters: [] };
|
|
65
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// --- or ---
|
|
69
|
+
|
|
70
|
+
it("filters out empty children from or", () => {
|
|
71
|
+
const leaf2: F = { type: "equal", column: "c2", x: 2 };
|
|
72
|
+
const filter: F = { type: "or", filters: [leaf, emptyLeaf, leaf2] };
|
|
73
|
+
expect(distillFilterSpec(filter)).toEqual({ type: "or", filters: [leaf, leaf2] });
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("returns null when all or children are empty", () => {
|
|
77
|
+
const filter: F = { type: "or", filters: [emptyLeaf] };
|
|
78
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// --- not ---
|
|
82
|
+
|
|
83
|
+
it("preserves not with valid inner filter", () => {
|
|
84
|
+
const filter: F = { type: "not", filter: leaf };
|
|
85
|
+
expect(distillFilterSpec(filter)).toEqual({ type: "not", filter: leaf });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("returns null for not wrapping an empty filter", () => {
|
|
89
|
+
const filter: F = { type: "not", filter: emptyLeaf };
|
|
90
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// --- nested collapse ---
|
|
94
|
+
|
|
95
|
+
it("returns null when nested and collapses", () => {
|
|
96
|
+
const filter: F = {
|
|
97
|
+
type: "not",
|
|
98
|
+
filter: { type: "and", filters: [emptyLeaf] },
|
|
99
|
+
};
|
|
100
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("returns null when parent and has only a collapsing child", () => {
|
|
104
|
+
const filter: F = {
|
|
105
|
+
type: "and",
|
|
106
|
+
filters: [{ type: "or", filters: [emptyLeaf] }],
|
|
107
|
+
};
|
|
108
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("keeps valid siblings when one child collapses", () => {
|
|
112
|
+
const filter: F = {
|
|
113
|
+
type: "and",
|
|
114
|
+
filters: [{ type: "or", filters: [emptyLeaf] }, leaf],
|
|
115
|
+
};
|
|
116
|
+
expect(distillFilterSpec(filter)).toEqual({ type: "and", filters: [leaf] });
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// --- unfilled fields (at least one undefined field drops the leaf) ---
|
|
120
|
+
|
|
121
|
+
it("returns null for leaf with undefined column", () => {
|
|
122
|
+
const filter: F = { type: "equal", column: undefined as unknown as string, x: 1 };
|
|
123
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("returns null for leaf with undefined value (string filter)", () => {
|
|
127
|
+
const filter: F = {
|
|
128
|
+
type: "patternEquals",
|
|
129
|
+
column: "c1",
|
|
130
|
+
value: undefined as unknown as string,
|
|
131
|
+
};
|
|
132
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("returns null for greaterThan with undefined x", () => {
|
|
136
|
+
const filter: F = {
|
|
137
|
+
type: "greaterThan",
|
|
138
|
+
column: "c1",
|
|
139
|
+
x: undefined as unknown as number,
|
|
140
|
+
};
|
|
141
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("returns null for topN with undefined n", () => {
|
|
145
|
+
const filter: F = {
|
|
146
|
+
type: "topN",
|
|
147
|
+
column: "c1",
|
|
148
|
+
n: undefined as unknown as number,
|
|
149
|
+
};
|
|
150
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("returns null for inSet with undefined value", () => {
|
|
154
|
+
const filter: F = {
|
|
155
|
+
type: "inSet",
|
|
156
|
+
column: "c1",
|
|
157
|
+
value: undefined as unknown as string[],
|
|
158
|
+
};
|
|
159
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("drops incomplete leaf from and, keeps filled siblings", () => {
|
|
163
|
+
const incomplete: F = { type: "greaterThan", column: "c1", x: undefined as unknown as number };
|
|
164
|
+
const filter: F = { type: "and", filters: [leaf, incomplete] };
|
|
165
|
+
expect(distillFilterSpec(filter)).toEqual({ type: "and", filters: [leaf] });
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("drops incomplete leaf from or, keeps filled siblings", () => {
|
|
169
|
+
const incomplete: F = {
|
|
170
|
+
type: "patternEquals",
|
|
171
|
+
column: "c1",
|
|
172
|
+
value: undefined as unknown as string,
|
|
173
|
+
};
|
|
174
|
+
const leaf2: F = { type: "equal", column: "c2", x: 2 };
|
|
175
|
+
const filter: F = { type: "or", filters: [incomplete, leaf2] };
|
|
176
|
+
expect(distillFilterSpec(filter)).toEqual({ type: "or", filters: [leaf2] });
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("returns null for not wrapping an incomplete leaf", () => {
|
|
180
|
+
const incomplete: F = { type: "equal", column: undefined as unknown as string, x: 1 };
|
|
181
|
+
const filter: F = { type: "not", filter: incomplete };
|
|
182
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("returns null when and contains only incomplete leaves", () => {
|
|
186
|
+
const a: F = { type: "equal", column: "c1", x: undefined as unknown as number };
|
|
187
|
+
const b: F = { type: "greaterThan", column: undefined as unknown as string, x: 5 };
|
|
188
|
+
const filter: F = { type: "and", filters: [a, b] };
|
|
189
|
+
expect(distillFilterSpec(filter)).toBeNull();
|
|
190
|
+
});
|
|
191
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { DistributiveKeys, UnionToTuples } from "@milaboratories/helpers";
|
|
2
|
+
import { type FilterSpec, type FilterSpecLeaf } from "@milaboratories/pl-model-common";
|
|
3
|
+
|
|
4
|
+
/** All possible field names that can appear in any FilterSpecLeaf variant. */
|
|
5
|
+
type FilterSpecLeafKey = DistributiveKeys<FilterSpecLeaf<string>>;
|
|
6
|
+
|
|
7
|
+
/** Compile-time check: every key in the tuple is a valid leaf key (via satisfies). */
|
|
8
|
+
const KNOWN_LEAF_KEYS_TUPLE: UnionToTuples<FilterSpecLeafKey> = [
|
|
9
|
+
"n",
|
|
10
|
+
"x",
|
|
11
|
+
"rhs",
|
|
12
|
+
"type",
|
|
13
|
+
"value",
|
|
14
|
+
"column",
|
|
15
|
+
"minDiff",
|
|
16
|
+
"maxEdits",
|
|
17
|
+
"wildcard",
|
|
18
|
+
"replacement",
|
|
19
|
+
"substitutionsOnly",
|
|
20
|
+
];
|
|
21
|
+
const KNOWN_LEAF_KEYS: Set<FilterSpecLeafKey> = new Set(KNOWN_LEAF_KEYS_TUPLE);
|
|
22
|
+
|
|
23
|
+
/** Returns true if the leaf is filled — type is defined and no required fields are undefined. */
|
|
24
|
+
function isFilledLeaf(node: Record<string, unknown>): boolean {
|
|
25
|
+
if (node.type == null) return false;
|
|
26
|
+
return !Object.values(node).some((v) => v === undefined);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function distillLeaf(node: Record<string, unknown>): FilterSpecLeaf<string> {
|
|
30
|
+
const result: Record<string, unknown> = {};
|
|
31
|
+
for (const [key, value] of Object.entries(node)) {
|
|
32
|
+
if (KNOWN_LEAF_KEYS.has(key as FilterSpecLeafKey)) {
|
|
33
|
+
result[key] = value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return result as FilterSpecLeaf<string>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function distillNode<T extends FilterSpecLeaf<unknown>>(
|
|
40
|
+
node: FilterSpec<T, unknown, unknown>,
|
|
41
|
+
): FilterSpec<T> | null {
|
|
42
|
+
switch (node.type) {
|
|
43
|
+
case "and":
|
|
44
|
+
case "or": {
|
|
45
|
+
const filtered = node.filters.map(distillNode).filter((f): f is FilterSpec<T> => f !== null);
|
|
46
|
+
return filtered.length === 0 ? null : { type: node.type, filters: filtered };
|
|
47
|
+
}
|
|
48
|
+
case "not": {
|
|
49
|
+
const inner = distillNode(node.filter);
|
|
50
|
+
return inner === null ? null : { type: "not", filter: inner };
|
|
51
|
+
}
|
|
52
|
+
default:
|
|
53
|
+
if (!isFilledLeaf(node)) return null;
|
|
54
|
+
return distillLeaf(node);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Strips non-FilterSpec metadata (whitelist approach) and removes
|
|
60
|
+
* unfilled leaves (type is undefined or any required field is undefined).
|
|
61
|
+
*/
|
|
62
|
+
export function distillFilterSpec<T extends FilterSpecLeaf<unknown>>(
|
|
63
|
+
filter: null | undefined | FilterSpec<T, unknown, unknown>,
|
|
64
|
+
): null | FilterSpec<T> {
|
|
65
|
+
if (filter == null) return null;
|
|
66
|
+
return distillNode(filter);
|
|
67
|
+
}
|
package/src/filters/index.ts
CHANGED
package/src/filters/types.ts
CHANGED
|
@@ -8,51 +8,10 @@ export type SimplifiedUniversalPColumnEntry = {
|
|
|
8
8
|
obj: SimplifiedPColumnSpec;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
export type
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
| { type: undefined }
|
|
19
|
-
| { type: "isNA"; column: T }
|
|
20
|
-
| { type: "isNotNA"; column: T }
|
|
21
|
-
| { type: "patternEquals"; column: T; value: string }
|
|
22
|
-
| { type: "patternNotEquals"; column: T; value: string }
|
|
23
|
-
| { type: "patternContainSubsequence"; column: T; value: string }
|
|
24
|
-
| { type: "patternNotContainSubsequence"; column: T; value: string }
|
|
25
|
-
| { type: "patternMatchesRegularExpression"; column: T; value: string }
|
|
26
|
-
| {
|
|
27
|
-
type: "patternFuzzyContainSubsequence";
|
|
28
|
-
column: T;
|
|
29
|
-
value: string;
|
|
30
|
-
maxEdits?: number;
|
|
31
|
-
substitutionsOnly?: boolean;
|
|
32
|
-
wildcard?: string;
|
|
33
|
-
}
|
|
34
|
-
| { type: "inSet"; column: T; value: string[] }
|
|
35
|
-
| { type: "notInSet"; column: T; value: string[] }
|
|
36
|
-
| { type: "topN"; column: T; n: number }
|
|
37
|
-
| { type: "bottomN"; column: T; n: number }
|
|
38
|
-
| { type: "equal"; column: T; x: number }
|
|
39
|
-
| { type: "notEqual"; column: T; x: number }
|
|
40
|
-
| { type: "lessThan"; column: T; x: number }
|
|
41
|
-
| { type: "greaterThan"; column: T; x: number }
|
|
42
|
-
| { type: "lessThanOrEqual"; column: T; x: number }
|
|
43
|
-
| { type: "greaterThanOrEqual"; column: T; x: number }
|
|
44
|
-
| { type: "equalToColumn"; column: T; rhs: T }
|
|
45
|
-
| { type: "lessThanColumn"; column: T; rhs: T; minDiff?: number }
|
|
46
|
-
| { type: "greaterThanColumn"; column: T; rhs: T; minDiff?: number }
|
|
47
|
-
| { type: "lessThanColumnOrEqual"; column: T; rhs: T; minDiff?: number }
|
|
48
|
-
| { type: "greaterThanColumnOrEqual"; column: T; rhs: T; minDiff?: number };
|
|
49
|
-
|
|
50
|
-
export type FilterSpec<
|
|
51
|
-
Leaf extends FilterSpecLeaf<unknown> = FilterSpecLeaf<SUniversalPColumnId>,
|
|
52
|
-
CommonNode = {},
|
|
53
|
-
CommonLeaf = CommonNode,
|
|
54
|
-
> = FilterSpecNode<Leaf, CommonNode, CommonLeaf>;
|
|
55
|
-
|
|
56
|
-
export type FilterSpecType = Exclude<FilterSpec, { type: undefined }>["type"];
|
|
57
|
-
|
|
58
|
-
export type FilterSpecOfType<T extends FilterSpecType> = Extract<FilterSpec, { type: T }>;
|
|
11
|
+
export type {
|
|
12
|
+
FilterSpecNode,
|
|
13
|
+
FilterSpecLeaf,
|
|
14
|
+
FilterSpec,
|
|
15
|
+
FilterSpecType,
|
|
16
|
+
FilterSpecOfType,
|
|
17
|
+
} from "@milaboratories/pl-model-common";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { collectQueryColumns, isBooleanExpression } from "@milaboratories/pl-model-common";
|
package/src/render/api.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type {
|
|
|
16
16
|
PObjectSpec,
|
|
17
17
|
PSpecPredicate,
|
|
18
18
|
PTableDef,
|
|
19
|
+
PTableDefV2,
|
|
19
20
|
PTableHandle,
|
|
20
21
|
PTableRecordFilter,
|
|
21
22
|
PTableSorting,
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
mapDataInfo,
|
|
37
38
|
mapPObjectData,
|
|
38
39
|
mapPTableDef,
|
|
40
|
+
mapPTableDefV2,
|
|
39
41
|
mapValueInVOE,
|
|
40
42
|
PColumnName,
|
|
41
43
|
readAnnotation,
|
|
@@ -58,12 +60,9 @@ import type { LabelDerivationOps } from "./util/label";
|
|
|
58
60
|
import { deriveLabels } from "./util/label";
|
|
59
61
|
import type { APColumnSelectorWithSplit } from "./util/split_selectors";
|
|
60
62
|
import { patchInSetFilters } from "./util/pframe_upgraders";
|
|
61
|
-
import { allPColumnsReady } from "./util";
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
| TreeEntry
|
|
65
|
-
| DataInfo<TreeEntry>
|
|
66
|
-
| PColumnValues;
|
|
63
|
+
import { allPColumnsReady } from "./util/pcolumn_data";
|
|
64
|
+
import type { PColumnDataUniversal } from "./internal";
|
|
65
|
+
import { collectQueryColumns } from "@milaboratories/pl-model-common";
|
|
67
66
|
|
|
68
67
|
/**
|
|
69
68
|
* Helper function to match domain objects
|
|
@@ -682,6 +681,13 @@ export abstract class RenderCtxBase<Args, Data> {
|
|
|
682
681
|
return this.ctx.createPTable(mapPTableDef(rawDef, (po) => transformPColumnData(po)));
|
|
683
682
|
}
|
|
684
683
|
|
|
684
|
+
public createPTableV2(def: PTableDefV2<PColumn<PColumnDataUniversal>>): PTableHandle | undefined {
|
|
685
|
+
const columns = collectQueryColumns(def.query);
|
|
686
|
+
this.verifyInlineAndExplicitColumnsSupport(columns);
|
|
687
|
+
if (!allPColumnsReady(columns)) return undefined;
|
|
688
|
+
return this.ctx.createPTableV2(mapPTableDefV2(def, (po) => transformPColumnData(po)));
|
|
689
|
+
}
|
|
690
|
+
|
|
685
691
|
/** @deprecated scheduled for removal from SDK */
|
|
686
692
|
public getBlockLabel(blockId: string): string {
|
|
687
693
|
return this.ctx.getBlockLabel(blockId);
|
|
@@ -721,6 +727,7 @@ export class RenderCtx<Args, Data> extends RenderCtxBase<Args, Data> {
|
|
|
721
727
|
/** Render context for legacy v1/v2 blocks - provides backward compatibility */
|
|
722
728
|
export class RenderCtxLegacy<Args, UiState> extends RenderCtxBase<Args, UiState> {
|
|
723
729
|
private _argsCache?: { v: Args };
|
|
730
|
+
|
|
724
731
|
public get args(): Args {
|
|
725
732
|
if (this._argsCache === undefined) {
|
|
726
733
|
const raw = this.ctx.args;
|
package/src/render/index.ts
CHANGED
|
@@ -2,5 +2,6 @@ export * from "./api";
|
|
|
2
2
|
export * from "./traversal_ops";
|
|
3
3
|
export * from "./accessor";
|
|
4
4
|
export * from "./util";
|
|
5
|
-
export { type ExtractFutureRefType } from "./future";
|
|
6
5
|
export { FutureRef } from "./future";
|
|
6
|
+
export type { PColumnDataUniversal } from "./internal";
|
|
7
|
+
export type { ExtractFutureRefType } from "./future";
|
package/src/render/internal.ts
CHANGED
|
@@ -13,12 +13,14 @@ import type {
|
|
|
13
13
|
PObjectSpec,
|
|
14
14
|
PSpecPredicate,
|
|
15
15
|
PTableDef,
|
|
16
|
+
PTableDefV2,
|
|
16
17
|
PTableHandle,
|
|
17
18
|
ResultCollection,
|
|
18
19
|
ValueOrError,
|
|
19
20
|
DataInfo,
|
|
20
21
|
RangeBytes,
|
|
21
22
|
} from "@milaboratories/pl-model-common";
|
|
23
|
+
import type { TreeNodeAccessor } from "./accessor";
|
|
22
24
|
|
|
23
25
|
export const StagingAccessorName = "staging";
|
|
24
26
|
export const MainAccessorName = "main";
|
|
@@ -26,6 +28,11 @@ export const MainAccessorName = "main";
|
|
|
26
28
|
export type AccessorHandle = Branded<string, "AccessorHandle">;
|
|
27
29
|
export type FutureHandle = Branded<string, "FutureHandle">;
|
|
28
30
|
|
|
31
|
+
export type PColumnDataUniversal<TreeEntry = TreeNodeAccessor> =
|
|
32
|
+
| TreeEntry
|
|
33
|
+
| DataInfo<TreeEntry>
|
|
34
|
+
| PColumnValues;
|
|
35
|
+
|
|
29
36
|
export interface GlobalCfgRenderCtxMethods<AHandle = AccessorHandle, FHandle = FutureHandle> {
|
|
30
37
|
//
|
|
31
38
|
// Root accessor creation
|
|
@@ -146,6 +153,10 @@ export interface GlobalCfgRenderCtxMethods<AHandle = AccessorHandle, FHandle = F
|
|
|
146
153
|
|
|
147
154
|
createPTable(def: PTableDef<PColumn<AHandle | PColumnValues | DataInfo<AHandle>>>): PTableHandle;
|
|
148
155
|
|
|
156
|
+
createPTableV2(
|
|
157
|
+
def: PTableDefV2<PColumn<AHandle | PColumnValues | DataInfo<AHandle>>>,
|
|
158
|
+
): PTableHandle;
|
|
159
|
+
|
|
149
160
|
//
|
|
150
161
|
// Computable
|
|
151
162
|
//
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
import canonicalize from "canonicalize";
|
|
34
34
|
import type { Optional } from "utility-types";
|
|
35
35
|
import type { TreeNodeAccessor } from "../accessor";
|
|
36
|
-
import type { PColumnDataUniversal } from "../
|
|
36
|
+
import type { PColumnDataUniversal } from "../internal";
|
|
37
37
|
import { filterDataInfoEntries } from "./axis_filtering";
|
|
38
38
|
import type { LabelDerivationOps, TraceEntry } from "./label";
|
|
39
39
|
import { deriveLabels } from "./label";
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
type PColumnKey,
|
|
17
17
|
} from "@milaboratories/pl-model-common";
|
|
18
18
|
import { TreeNodeAccessor } from "../accessor";
|
|
19
|
-
import type { PColumnDataUniversal } from "../
|
|
19
|
+
import type { PColumnDataUniversal } from "../internal";
|
|
20
20
|
|
|
21
21
|
const PCD_PREFIX = "PColumnData/";
|
|
22
22
|
|