@milaboratories/pl-model-common 1.24.0 → 1.24.2
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/drivers/pframe/index.d.ts +1 -0
- package/dist/drivers/pframe/index.d.ts.map +1 -1
- package/dist/drivers/pframe/query/index.d.ts +3 -0
- package/dist/drivers/pframe/query/index.d.ts.map +1 -0
- package/dist/drivers/pframe/query/query_common.d.ts +791 -0
- package/dist/drivers/pframe/query/query_common.d.ts.map +1 -0
- package/dist/drivers/pframe/query/query_data.d.ts +66 -0
- package/dist/drivers/pframe/query/query_data.d.ts.map +1 -0
- package/dist/drivers/pframe/query/query_spec.d.ts +76 -0
- package/dist/drivers/pframe/query/query_spec.d.ts.map +1 -0
- package/dist/drivers/pframe/spec/selectors.cjs.map +1 -1
- package/dist/drivers/pframe/spec/selectors.d.ts +12 -1
- package/dist/drivers/pframe/spec/selectors.d.ts.map +1 -1
- package/dist/drivers/pframe/spec/selectors.js.map +1 -1
- package/dist/drivers/pframe/spec/spec.cjs +22 -0
- package/dist/drivers/pframe/spec/spec.cjs.map +1 -1
- package/dist/drivers/pframe/spec/spec.d.ts +28 -5
- package/dist/drivers/pframe/spec/spec.d.ts.map +1 -1
- package/dist/drivers/pframe/spec/spec.js +22 -1
- package/dist/drivers/pframe/spec/spec.js.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/src/drivers/pframe/index.ts +1 -1
- package/src/drivers/pframe/query/index.ts +2 -0
- package/src/drivers/pframe/query/query_common.ts +821 -0
- package/src/drivers/pframe/query/query_data.ts +110 -0
- package/src/drivers/pframe/query/query_spec.ts +118 -0
- package/src/drivers/pframe/spec/selectors.ts +13 -1
- package/src/drivers/pframe/spec/spec.ts +32 -5
|
@@ -0,0 +1,791 @@
|
|
|
1
|
+
import type { PObjectId } from '../../../pool';
|
|
2
|
+
import type { JsonDataInfo } from '../data_info';
|
|
3
|
+
import type { AxisValueType, ColumnValueType } from '../spec';
|
|
4
|
+
/**
|
|
5
|
+
* Specification of column/frame structure.
|
|
6
|
+
*
|
|
7
|
+
* Defines the shape of data: which axes (dimensions) the data has
|
|
8
|
+
* and what value types are stored in columns.
|
|
9
|
+
*/
|
|
10
|
+
export type TypeSpec = {
|
|
11
|
+
/** List of axis value types defining the dimensions of the data */
|
|
12
|
+
axes: AxisValueType[];
|
|
13
|
+
/** List of column value types defining the data stored */
|
|
14
|
+
columns: ColumnValueType[];
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Unary mathematical operation kinds.
|
|
18
|
+
*
|
|
19
|
+
* These operations take a single numeric input and produce a numeric output.
|
|
20
|
+
* **Null handling**: If input is null, result is null.
|
|
21
|
+
*
|
|
22
|
+
* Operations:
|
|
23
|
+
* - `abs` - Absolute value: |x|
|
|
24
|
+
* - `ceil` - Round up to nearest integer
|
|
25
|
+
* - `floor` - Round down to nearest integer
|
|
26
|
+
* - `round` - Round to nearest integer (banker's rounding)
|
|
27
|
+
* - `sqrt` - Square root (returns NaN for negative inputs)
|
|
28
|
+
* - `log` - Natural logarithm (ln)
|
|
29
|
+
* - `log2` - Base-2 logarithm
|
|
30
|
+
* - `log10` - Base-10 logarithm
|
|
31
|
+
* - `exp` - Exponential function (e^x)
|
|
32
|
+
* - `negate` - Negation (-x)
|
|
33
|
+
*/
|
|
34
|
+
export type NumericUnaryOperand = 'abs' | 'ceil' | 'floor' | 'round' | 'sqrt' | 'log' | 'log2' | 'log10' | 'exp' | 'negate';
|
|
35
|
+
/**
|
|
36
|
+
* Binary mathematical operation kinds.
|
|
37
|
+
*
|
|
38
|
+
* These operations take two numeric inputs and produce a numeric result.
|
|
39
|
+
* **Null handling**: If either operand is null, result is null.
|
|
40
|
+
*
|
|
41
|
+
* Operations:
|
|
42
|
+
* - `add` - Addition: left + right
|
|
43
|
+
* - `sub` - Subtraction: left - right
|
|
44
|
+
* - `mul` - Multiplication: left * right
|
|
45
|
+
* - `div` - Division: left / right (division by zero returns Infinity or NaN)
|
|
46
|
+
* - `mod` - Modulo: left % right
|
|
47
|
+
*/
|
|
48
|
+
export type NumericBinaryOperand = 'add' | 'sub' | 'mul' | 'div' | 'mod';
|
|
49
|
+
/**
|
|
50
|
+
* Numeric comparison operation kinds.
|
|
51
|
+
*
|
|
52
|
+
* These operations compare two numeric inputs and produce a boolean result.
|
|
53
|
+
* **Null handling**: If either operand is null, result is null.
|
|
54
|
+
*
|
|
55
|
+
* Operations:
|
|
56
|
+
* - `eq` - Equal: left == right
|
|
57
|
+
* - `ne` - Not equal: left != right
|
|
58
|
+
* - `lt` - Less than: left < right
|
|
59
|
+
* - `le` - Less or equal: left <= right
|
|
60
|
+
* - `gt` - Greater than: left > right
|
|
61
|
+
* - `ge` - Greater or equal: left >= right
|
|
62
|
+
*/
|
|
63
|
+
export type NumericComparisonOperand = 'eq' | 'ne' | 'lt' | 'le' | 'gt' | 'ge';
|
|
64
|
+
/**
|
|
65
|
+
* 2D point coordinates.
|
|
66
|
+
*
|
|
67
|
+
* Used for geometric operations like point-in-polygon tests.
|
|
68
|
+
* Common use case: flow cytometry gating where points are tested
|
|
69
|
+
* against user-defined polygon regions.
|
|
70
|
+
*/
|
|
71
|
+
export type Point2D = {
|
|
72
|
+
x: number;
|
|
73
|
+
y: number;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Constant value expression.
|
|
77
|
+
*
|
|
78
|
+
* Represents a literal constant value in an expression tree.
|
|
79
|
+
* The value can be a string, number, or boolean.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* // Constant number
|
|
83
|
+
* { type: 'constant', value: 42 }
|
|
84
|
+
*
|
|
85
|
+
* // Constant string
|
|
86
|
+
* { type: 'constant', value: 'hello' }
|
|
87
|
+
*
|
|
88
|
+
* // Constant boolean
|
|
89
|
+
* { type: 'constant', value: true }
|
|
90
|
+
*/
|
|
91
|
+
export type ExprConstant = {
|
|
92
|
+
type: 'constant';
|
|
93
|
+
value: string | number | boolean;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Unary mathematical expression.
|
|
97
|
+
*
|
|
98
|
+
* Applies a unary mathematical function to a single input expression.
|
|
99
|
+
* **Input**: One expression that evaluates to a numeric value.
|
|
100
|
+
* **Output**: Numeric value.
|
|
101
|
+
* **Null handling**: If input is null, result is null.
|
|
102
|
+
*
|
|
103
|
+
* @template I - The expression type (for recursion)
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* // Absolute value of column "value"
|
|
107
|
+
* { type: 'unaryMath', operand: 'abs', input: columnRef }
|
|
108
|
+
*
|
|
109
|
+
* // Natural log of expression
|
|
110
|
+
* { type: 'unaryMath', operand: 'log', input: someExpr }
|
|
111
|
+
*
|
|
112
|
+
* @see NumericUnaryOperand for available operations
|
|
113
|
+
*/
|
|
114
|
+
export interface ExprNumericUnary<I> {
|
|
115
|
+
type: 'numericUnary';
|
|
116
|
+
/** The mathematical operation to apply */
|
|
117
|
+
operand: NumericUnaryOperand;
|
|
118
|
+
/** Input expression (must evaluate to numeric) */
|
|
119
|
+
input: I;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Binary mathematical expression.
|
|
123
|
+
*
|
|
124
|
+
* Applies a binary arithmetic operation to two input expressions.
|
|
125
|
+
* **Input**: Two expressions that evaluate to numeric values.
|
|
126
|
+
* **Output**: Numeric value.
|
|
127
|
+
* **Null handling**: If either operand is null, result is null.
|
|
128
|
+
*
|
|
129
|
+
* @template I - The expression type (for recursion)
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* // Addition: col_a + col_b
|
|
133
|
+
* { type: 'binaryMath', operand: 'add', left: colA, right: colB }
|
|
134
|
+
*
|
|
135
|
+
* // Division: col_a / 2
|
|
136
|
+
* { type: 'binaryMath', operand: 'div', left: colA, right: { type: 'constant', value: 2 } }
|
|
137
|
+
*
|
|
138
|
+
* @see NumericBinaryOperand for available operations
|
|
139
|
+
*/
|
|
140
|
+
export interface ExprNumericBinary<I> {
|
|
141
|
+
type: 'numericBinary';
|
|
142
|
+
/** The arithmetic operation to apply */
|
|
143
|
+
operand: NumericBinaryOperand;
|
|
144
|
+
/** Left operand expression */
|
|
145
|
+
left: I;
|
|
146
|
+
/** Right operand expression */
|
|
147
|
+
right: I;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Numeric comparison expression.
|
|
151
|
+
*
|
|
152
|
+
* Compares two numeric expressions and produces a boolean result.
|
|
153
|
+
* **Input**: Two expressions that evaluate to numeric values.
|
|
154
|
+
* **Output**: Boolean.
|
|
155
|
+
* **Null handling**: If either operand is null, result is null.
|
|
156
|
+
*
|
|
157
|
+
* @template I - The expression type (for recursion)
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* // Greater than: col_a > 10
|
|
161
|
+
* { type: 'numericComparison', operand: 'gt', left: colA, right: { type: 'constant', value: 10 } }
|
|
162
|
+
*
|
|
163
|
+
* // Equality: col_a == col_b
|
|
164
|
+
* { type: 'numericComparison', operand: 'eq', left: colA, right: colB }
|
|
165
|
+
*
|
|
166
|
+
* // Range check (combine with logical AND): 0 <= x && x < 100
|
|
167
|
+
* // { type: 'logical', operand: 'and', input: [
|
|
168
|
+
* // { type: 'numericComparison', operand: 'ge', left: colX, right: { type: 'constant', value: 0 } },
|
|
169
|
+
* // { type: 'numericComparison', operand: 'lt', left: colX, right: { type: 'constant', value: 100 } }
|
|
170
|
+
* // ]}
|
|
171
|
+
*
|
|
172
|
+
* @see NumericComparisonOperand for available operations
|
|
173
|
+
*/
|
|
174
|
+
export interface ExprNumericComparison<I> {
|
|
175
|
+
type: 'numericComparison';
|
|
176
|
+
/** The comparison operation to apply */
|
|
177
|
+
operand: NumericComparisonOperand;
|
|
178
|
+
/** Left operand expression */
|
|
179
|
+
left: I;
|
|
180
|
+
/** Right operand expression */
|
|
181
|
+
right: I;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* String equality check.
|
|
185
|
+
*
|
|
186
|
+
* Compares input string to a reference value.
|
|
187
|
+
* **Input**: Expression evaluating to a string.
|
|
188
|
+
* **Output**: Boolean.
|
|
189
|
+
* **Null handling**: Returns false if input is null.
|
|
190
|
+
*
|
|
191
|
+
* @template I - The expression type (for recursion)
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* // Check if name equals "John" (case-sensitive)
|
|
195
|
+
* // Matches only: "John"
|
|
196
|
+
* { type: 'stringEquals', input: nameColumn, value: 'John' }
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* // Check if name equals "John" (case-insensitive)
|
|
200
|
+
* // Matches: "john", "JOHN", "John", "jOhN"
|
|
201
|
+
* { type: 'stringEquals', input: nameColumn, value: 'John', caseInsensitive: true }
|
|
202
|
+
*/
|
|
203
|
+
export interface ExprStringEquals<I> {
|
|
204
|
+
type: 'stringEquals';
|
|
205
|
+
/** Input expression (must evaluate to string) */
|
|
206
|
+
input: I;
|
|
207
|
+
/** Reference string to compare against */
|
|
208
|
+
value: string;
|
|
209
|
+
/** If true, comparison ignores case */
|
|
210
|
+
caseInsensitive: boolean;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Regular expression match check.
|
|
214
|
+
*
|
|
215
|
+
* Tests if input string matches a regular expression pattern.
|
|
216
|
+
* **Input**: Expression evaluating to a string.
|
|
217
|
+
* **Output**: Boolean (true if pattern matches).
|
|
218
|
+
* **Null handling**: Returns false if input is null.
|
|
219
|
+
*
|
|
220
|
+
* @template I - The expression type (for recursion)
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* // Check if value matches email pattern
|
|
224
|
+
* { type: 'stringRegex', input: emailColumn, value: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$' }
|
|
225
|
+
*
|
|
226
|
+
* // Check if starts with "prefix"
|
|
227
|
+
* { type: 'stringRegex', input: valueColumn, value: '^prefix' }
|
|
228
|
+
*
|
|
229
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions | MDN Regular Expressions Guide}
|
|
230
|
+
*/
|
|
231
|
+
export interface ExprStringRegex<I> {
|
|
232
|
+
type: 'stringRegex';
|
|
233
|
+
/** Input expression (must evaluate to string) */
|
|
234
|
+
input: I;
|
|
235
|
+
/** Regular expression pattern */
|
|
236
|
+
value: string;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Substring containment check.
|
|
240
|
+
*
|
|
241
|
+
* Tests if input string contains a specified substring.
|
|
242
|
+
* **Input**: Expression evaluating to a string.
|
|
243
|
+
* **Output**: Boolean (true if substring is found).
|
|
244
|
+
* **Null handling**: Returns false if input is null.
|
|
245
|
+
*
|
|
246
|
+
* @template I - The expression type (for recursion)
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* // Case-sensitive contains
|
|
250
|
+
* { type: 'stringContains', input: descColumn, value: 'error', caseInsensitive: false }
|
|
251
|
+
*
|
|
252
|
+
* // Case-insensitive contains
|
|
253
|
+
* { type: 'stringContains', input: descColumn, value: 'ERROR', caseInsensitive: true }
|
|
254
|
+
*/
|
|
255
|
+
export interface ExprStringContains<I> {
|
|
256
|
+
type: 'stringContains';
|
|
257
|
+
/** Input expression (must evaluate to string) */
|
|
258
|
+
input: I;
|
|
259
|
+
/** Substring to search for */
|
|
260
|
+
value: string;
|
|
261
|
+
/** If true, comparison ignores case */
|
|
262
|
+
caseInsensitive: boolean;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Fuzzy string containment check with edit distance.
|
|
266
|
+
*
|
|
267
|
+
* Tests if input string approximately matches a pattern within a specified edit distance.
|
|
268
|
+
* Uses Levenshtein distance (or substitution-only distance) for fuzzy matching.
|
|
269
|
+
* **Input**: Expression evaluating to a string.
|
|
270
|
+
* **Output**: Boolean (true if approximate match found within maxEdits).
|
|
271
|
+
* **Null handling**: Returns false if input is null.
|
|
272
|
+
*
|
|
273
|
+
* @template I - The expression type (for recursion)
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* // Match "color" with up to 1 edit (catches "colour", "colr", etc.)
|
|
277
|
+
* {
|
|
278
|
+
* type: 'stringContainsFuzzy',
|
|
279
|
+
* input: textColumn,
|
|
280
|
+
* value: 'color',
|
|
281
|
+
* maxEdits: 1,
|
|
282
|
+
* caseInsensitive: true,
|
|
283
|
+
* substitutionsOnly: false,
|
|
284
|
+
* wildcard: null
|
|
285
|
+
* }
|
|
286
|
+
*
|
|
287
|
+
* // Match with wildcard (? matches any single character)
|
|
288
|
+
* {
|
|
289
|
+
* type: 'stringContainsFuzzy',
|
|
290
|
+
* input: textColumn,
|
|
291
|
+
* value: 'te?t',
|
|
292
|
+
* maxEdits: 0,
|
|
293
|
+
* caseInsensitive: false,
|
|
294
|
+
* substitutionsOnly: false,
|
|
295
|
+
* wildcard: '?'
|
|
296
|
+
* }
|
|
297
|
+
*/
|
|
298
|
+
export interface ExprStringContainsFuzzy<I> {
|
|
299
|
+
type: 'stringContainsFuzzy';
|
|
300
|
+
/** Input expression (must evaluate to string) */
|
|
301
|
+
input: I;
|
|
302
|
+
/** Pattern to match against */
|
|
303
|
+
value: string;
|
|
304
|
+
/**
|
|
305
|
+
* Maximum edit distance (Levenshtein distance).
|
|
306
|
+
* 0 = exact match only, 1 = one edit allowed, etc.
|
|
307
|
+
*/
|
|
308
|
+
maxEdits: number;
|
|
309
|
+
/** If true, comparison ignores case */
|
|
310
|
+
caseInsensitive: boolean;
|
|
311
|
+
/**
|
|
312
|
+
* If true, only substitutions count as edits (no insertions/deletions).
|
|
313
|
+
* Useful when you want to match strings of same length with typos.
|
|
314
|
+
*/
|
|
315
|
+
substitutionsOnly: boolean;
|
|
316
|
+
/**
|
|
317
|
+
* Optional wildcard character that matches any single character.
|
|
318
|
+
* Example: '?' in "te?t" matches "test", "text", "tent", etc.
|
|
319
|
+
* Set to null to disable wildcard matching.
|
|
320
|
+
*/
|
|
321
|
+
wildcard: null | string;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Logical NOT expression.
|
|
325
|
+
*
|
|
326
|
+
* Negates a boolean expression.
|
|
327
|
+
* **Input**: Expression evaluating to boolean.
|
|
328
|
+
* **Output**: Boolean (inverted).
|
|
329
|
+
* **Null handling**: NOT null = null.
|
|
330
|
+
*
|
|
331
|
+
* @template I - The expression type (for recursion)
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* // NOT (value > 10)
|
|
335
|
+
* { type: 'not', input: comparisonExpr }
|
|
336
|
+
*/
|
|
337
|
+
export interface ExprLogicalUnary<I> {
|
|
338
|
+
type: 'not';
|
|
339
|
+
/** Input boolean expression to negate */
|
|
340
|
+
input: I;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Logical AND/OR expression.
|
|
344
|
+
*
|
|
345
|
+
* Combines multiple boolean expressions using AND or OR logic.
|
|
346
|
+
* **Input**: Array of expressions evaluating to boolean (minimum 2).
|
|
347
|
+
* **Output**: Boolean.
|
|
348
|
+
*
|
|
349
|
+
* **Null handling**
|
|
350
|
+
* - AND: null AND true = null, null AND false = false
|
|
351
|
+
* - OR: null OR true = true, null OR false = null
|
|
352
|
+
*
|
|
353
|
+
* @template I - The expression type (for recursion)
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* // (a > 0) AND (b < 100)
|
|
357
|
+
* { type: 'and', input: [exprA, exprB] }
|
|
358
|
+
*
|
|
359
|
+
* // (status == 'active') OR (status == 'pending')
|
|
360
|
+
* { type: 'or', input: [statusActive, statusPending] }
|
|
361
|
+
*/
|
|
362
|
+
export interface ExprLogicalVariadic<I> {
|
|
363
|
+
/** Logical operation: 'and' or 'or' */
|
|
364
|
+
type: 'and' | 'or';
|
|
365
|
+
/** Array of boolean expressions to combine (minimum 2 elements) */
|
|
366
|
+
input: I[];
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Set membership check expression.
|
|
370
|
+
*
|
|
371
|
+
* Tests if a value is present in a predefined set of values.
|
|
372
|
+
* **Input**: Expression evaluating to string or number.
|
|
373
|
+
* **Output**: Boolean.
|
|
374
|
+
* **Null handling**: Returns false if input is null.
|
|
375
|
+
*
|
|
376
|
+
* @template I - The expression type (for recursion)
|
|
377
|
+
* @template T - The type of set elements (string or number)
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* // Check if status is in ['active', 'pending', 'review']
|
|
381
|
+
* {
|
|
382
|
+
* type: 'isIn',
|
|
383
|
+
* input: statusColumn,
|
|
384
|
+
* set: ['active', 'pending', 'review']
|
|
385
|
+
* }
|
|
386
|
+
*/
|
|
387
|
+
export interface ExprIsIn<I, T extends string | number> {
|
|
388
|
+
type: 'isIn';
|
|
389
|
+
/** Input expression to test */
|
|
390
|
+
input: I;
|
|
391
|
+
/** Set of allowed values */
|
|
392
|
+
set: T[];
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Axis reference expression.
|
|
396
|
+
*
|
|
397
|
+
* References an axis value for use in expressions (filtering, sorting, etc.).
|
|
398
|
+
* The axis identifier type varies by context (spec vs data layer).
|
|
399
|
+
*
|
|
400
|
+
* @template A - Axis identifier type (e.g., SingleAxisSelector for spec, number for data)
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* // Reference axis by selector (spec layer)
|
|
404
|
+
* { type: 'axisRef', value: { name: 'sample' } }
|
|
405
|
+
*
|
|
406
|
+
* // Reference axis by index (data layer)
|
|
407
|
+
* { type: 'axisRef', value: 0 }
|
|
408
|
+
*/
|
|
409
|
+
export interface ExprAxisRef<A> {
|
|
410
|
+
type: 'axisRef';
|
|
411
|
+
/** Axis identifier (selector or index depending on context) */
|
|
412
|
+
value: A;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Column reference expression.
|
|
416
|
+
*
|
|
417
|
+
* References a column value for use in expressions (filtering, arithmetic, etc.).
|
|
418
|
+
* The column identifier type varies by context (spec vs data layer).
|
|
419
|
+
*
|
|
420
|
+
* @template C - Column identifier type (e.g., PObjectId for spec, number for data)
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* // Reference column by ID (spec layer)
|
|
424
|
+
* { type: 'columnRef', value: 'col_abc123' }
|
|
425
|
+
*
|
|
426
|
+
* // Reference column by index (data layer)
|
|
427
|
+
* { type: 'columnRef', value: 0 }
|
|
428
|
+
*/
|
|
429
|
+
export interface ExprColumnRef<C> {
|
|
430
|
+
type: 'columnRef';
|
|
431
|
+
/** Column identifier (ID or index depending on context) */
|
|
432
|
+
value: C;
|
|
433
|
+
}
|
|
434
|
+
export type InferBooleanExpressionUnion<E> = [
|
|
435
|
+
E extends ExprNumericComparison<unknown> ? Extract<E, {
|
|
436
|
+
type: 'numericComparison';
|
|
437
|
+
}> : never,
|
|
438
|
+
E extends ExprStringEquals<unknown> ? Extract<E, {
|
|
439
|
+
type: 'stringEquals';
|
|
440
|
+
}> : never,
|
|
441
|
+
E extends ExprStringContains<unknown> ? Extract<E, {
|
|
442
|
+
type: 'stringContains';
|
|
443
|
+
}> : never,
|
|
444
|
+
E extends ExprStringContainsFuzzy<unknown> ? Extract<E, {
|
|
445
|
+
type: 'stringContainsFuzzy';
|
|
446
|
+
}> : never,
|
|
447
|
+
E extends ExprStringRegex<unknown> ? Extract<E, {
|
|
448
|
+
type: 'stringRegex';
|
|
449
|
+
}> : never,
|
|
450
|
+
E extends ExprLogicalUnary<unknown> ? Extract<E, {
|
|
451
|
+
type: 'not';
|
|
452
|
+
}> : never,
|
|
453
|
+
E extends ExprLogicalVariadic<unknown> ? Extract<E, {
|
|
454
|
+
type: 'and' | 'or';
|
|
455
|
+
}> : never,
|
|
456
|
+
E extends ExprIsIn<unknown, string | number> ? Extract<E, {
|
|
457
|
+
type: 'isIn';
|
|
458
|
+
}> : never
|
|
459
|
+
][number];
|
|
460
|
+
/**
|
|
461
|
+
* Selector for referencing an axis in queries.
|
|
462
|
+
*
|
|
463
|
+
* Used to identify a specific axis dimension in operations like:
|
|
464
|
+
* - Sorting by axis values
|
|
465
|
+
* - Partitioning for window functions
|
|
466
|
+
* - Filtering/slicing axes
|
|
467
|
+
*
|
|
468
|
+
* @template A - Axis identifier type (typically string name or numeric index)
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* // Select axis by name
|
|
472
|
+
* { type: 'axis', id: 'sample' }
|
|
473
|
+
*
|
|
474
|
+
* // Select axis by index
|
|
475
|
+
* { type: 'axis', id: 0 }
|
|
476
|
+
*/
|
|
477
|
+
export interface QueryAxisSelector<A> {
|
|
478
|
+
type: 'axis';
|
|
479
|
+
/** Axis identifier (name or index depending on context) */
|
|
480
|
+
id: A;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Selector for referencing a column in queries.
|
|
484
|
+
*
|
|
485
|
+
* Used to identify a specific column in operations like:
|
|
486
|
+
* - Sorting by column values
|
|
487
|
+
* - Partitioning for window functions
|
|
488
|
+
* - Aggregation expressions
|
|
489
|
+
*
|
|
490
|
+
* @template C - Column identifier type (typically string name or numeric index)
|
|
491
|
+
*
|
|
492
|
+
* @example
|
|
493
|
+
* // Select column by name
|
|
494
|
+
* { type: 'column', id: 'expression_value' }
|
|
495
|
+
*
|
|
496
|
+
* // Select column by index
|
|
497
|
+
* { type: 'column', id: 0 }
|
|
498
|
+
*/
|
|
499
|
+
export interface QueryColumnSelector<C> {
|
|
500
|
+
type: 'column';
|
|
501
|
+
/** Column identifier (name or index depending on context) */
|
|
502
|
+
id: C;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Left outer join query operation.
|
|
506
|
+
*
|
|
507
|
+
* Joins a primary query with one or more secondary queries using left outer join semantics.
|
|
508
|
+
* All records from the primary are preserved; matching records from secondaries are joined,
|
|
509
|
+
* non-matching positions are filled with nulls.
|
|
510
|
+
*
|
|
511
|
+
* **Join behavior**:
|
|
512
|
+
* - All records from `primary` are preserved
|
|
513
|
+
* - For each secondary, matching records (by axis keys) are joined
|
|
514
|
+
* - Missing matches from secondaries are filled with null values
|
|
515
|
+
* - Empty `secondary` array acts as identity (returns primary unchanged)
|
|
516
|
+
*
|
|
517
|
+
* **Null handling**: Null join keys don't match; positions without matches get null values.
|
|
518
|
+
*
|
|
519
|
+
* @template JE - Join entry type
|
|
520
|
+
*
|
|
521
|
+
* @example
|
|
522
|
+
* // Left join samples with optional annotations
|
|
523
|
+
* {
|
|
524
|
+
* type: 'outerJoin',
|
|
525
|
+
* primary: samplesQuery,
|
|
526
|
+
* secondary: [annotationsQuery, metadataQuery]
|
|
527
|
+
* }
|
|
528
|
+
* // Result has all samples; annotations/metadata are null where not available
|
|
529
|
+
*/
|
|
530
|
+
export interface QueryOuterJoin<JE extends QueryJoinEntry<unknown>> {
|
|
531
|
+
type: 'outerJoin';
|
|
532
|
+
/** Primary query - all its records are preserved */
|
|
533
|
+
primary: JE;
|
|
534
|
+
/** Secondary queries - joined where keys match, null where they don't */
|
|
535
|
+
secondary: JE[];
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Axis slicing query operation.
|
|
539
|
+
*
|
|
540
|
+
* Filters data by fixing one or more axes to specific constant values.
|
|
541
|
+
* Each filtered axis is removed from the resulting data shape (reduces dimensionality).
|
|
542
|
+
*
|
|
543
|
+
* **Behavior**:
|
|
544
|
+
* - Each axis filter selects records where that axis equals the constant
|
|
545
|
+
* - Filtered axes are removed from the output spec
|
|
546
|
+
* - Multiple filters apply conjunctively (AND)
|
|
547
|
+
*
|
|
548
|
+
* @template Q - Input query type
|
|
549
|
+
* @template A - Axis selector type
|
|
550
|
+
*
|
|
551
|
+
* @example
|
|
552
|
+
* // Slice 3D data [sample, gene, condition] to 1D [gene]
|
|
553
|
+
* {
|
|
554
|
+
* type: 'sliceAxes',
|
|
555
|
+
* input: fullDataQuery,
|
|
556
|
+
* axisFilters: [
|
|
557
|
+
* { type: 'constant', axisSelector: { type: 'axis', id: 'sample' }, constant: 'Sample1' },
|
|
558
|
+
* { type: 'constant', axisSelector: { type: 'axis', id: 'condition' }, constant: 'Treatment' }
|
|
559
|
+
* ]
|
|
560
|
+
* }
|
|
561
|
+
*/
|
|
562
|
+
export interface QuerySliceAxes<Q, A extends QueryAxisSelector<unknown>> {
|
|
563
|
+
type: 'sliceAxes';
|
|
564
|
+
/** Input query to slice */
|
|
565
|
+
input: Q;
|
|
566
|
+
/** List of axis filters to apply (at least one required) */
|
|
567
|
+
axisFilters: {
|
|
568
|
+
/** Selector identifying which axis to filter */
|
|
569
|
+
axisSelector: A;
|
|
570
|
+
/** The constant value to filter the axis to */
|
|
571
|
+
constant: string | number;
|
|
572
|
+
}[];
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Sort query operation.
|
|
576
|
+
*
|
|
577
|
+
* Reorders records by one or more axes or columns.
|
|
578
|
+
* Does not change data shape or values, only record order.
|
|
579
|
+
*
|
|
580
|
+
* **Behavior**:
|
|
581
|
+
* - Sort entries are applied in priority order (first entry = primary sort key)
|
|
582
|
+
* - Ties in first sort key are broken by second, etc.
|
|
583
|
+
* - All axes and columns pass through unchanged
|
|
584
|
+
* - Only the physical ordering of records changes
|
|
585
|
+
*
|
|
586
|
+
* @template Q - Input query type
|
|
587
|
+
* @template SE - Sort entry type
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* // Sort by score descending, then by name ascending for ties
|
|
591
|
+
* {
|
|
592
|
+
* type: 'sort',
|
|
593
|
+
* input: dataQuery,
|
|
594
|
+
* sortBy: [
|
|
595
|
+
* { axisOrColumn: { type: 'column', id: 'score' }, ascending: false, nullsFirst: null },
|
|
596
|
+
* { axisOrColumn: { type: 'axis', id: 'name' }, ascending: true, nullsFirst: null }
|
|
597
|
+
* ]
|
|
598
|
+
* }
|
|
599
|
+
*/
|
|
600
|
+
export interface QuerySort<Q, E> {
|
|
601
|
+
type: 'sort';
|
|
602
|
+
/** Input query to sort */
|
|
603
|
+
input: Q;
|
|
604
|
+
/** Sort criteria in priority order (at least one required) */
|
|
605
|
+
sortBy: {
|
|
606
|
+
data: E;
|
|
607
|
+
/** If true, sort ascending (A-Z, 0-9); if false, descending */
|
|
608
|
+
ascending: boolean;
|
|
609
|
+
/**
|
|
610
|
+
* Null placement control:
|
|
611
|
+
* - true: nulls sort before non-null values
|
|
612
|
+
* - false: nulls sort after non-null values
|
|
613
|
+
* - null: use default behavior (typically nulls last)
|
|
614
|
+
*/
|
|
615
|
+
nullsFirst: null | boolean;
|
|
616
|
+
}[];
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Filter query operation.
|
|
620
|
+
*
|
|
621
|
+
* Filters records based on a boolean predicate expression.
|
|
622
|
+
* Only records where predicate evaluates to true are kept.
|
|
623
|
+
*
|
|
624
|
+
* **Behavior**:
|
|
625
|
+
* - Evaluates predicate for each record
|
|
626
|
+
* - Keeps records where predicate is true
|
|
627
|
+
* - Discards records where predicate is false or null
|
|
628
|
+
* - Data shape (axes, columns) is preserved
|
|
629
|
+
*
|
|
630
|
+
* **Null handling**: Records with null predicate result are excluded (null ≠ true).
|
|
631
|
+
*
|
|
632
|
+
* @template Q - Input query type
|
|
633
|
+
* @template E - Expression type
|
|
634
|
+
*
|
|
635
|
+
* @example
|
|
636
|
+
* // Filter to records where value > 10 AND status == 'active'
|
|
637
|
+
* {
|
|
638
|
+
* type: 'filter',
|
|
639
|
+
* input: dataQuery,
|
|
640
|
+
* predicate: {
|
|
641
|
+
* type: 'logical',
|
|
642
|
+
* operand: 'and',
|
|
643
|
+
* input: [
|
|
644
|
+
* { type: 'numericComparison', operand: 'gt', left: valueRef, right: { type: 'constant', value: 10 } },
|
|
645
|
+
* { type: 'stringEquals', input: statusRef, value: 'active' }
|
|
646
|
+
* ]
|
|
647
|
+
* }
|
|
648
|
+
* }
|
|
649
|
+
*/
|
|
650
|
+
export interface QueryFilter<Q, E> {
|
|
651
|
+
type: 'filter';
|
|
652
|
+
/** Input query to filter */
|
|
653
|
+
input: Q;
|
|
654
|
+
/** Boolean predicate expression - only true records pass */
|
|
655
|
+
predicate: E;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Column reference query (leaf node).
|
|
659
|
+
*
|
|
660
|
+
* References an existing column by its unique identifier.
|
|
661
|
+
* This is a leaf node in the query tree that retrieves actual data.
|
|
662
|
+
*
|
|
663
|
+
* The column must exist in the dataset and its spec (axes, value type)
|
|
664
|
+
* becomes the output spec of this query node.
|
|
665
|
+
*
|
|
666
|
+
* @example
|
|
667
|
+
* // Reference column by ID
|
|
668
|
+
* { type: 'column', columnId: 'col_abc123' }
|
|
669
|
+
*/
|
|
670
|
+
export interface QueryColumn {
|
|
671
|
+
type: 'column';
|
|
672
|
+
/** Unique identifier of the column to reference */
|
|
673
|
+
columnId: PObjectId;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Inline column query (leaf node).
|
|
677
|
+
*
|
|
678
|
+
* Creates a column with inline/embedded data and type specification.
|
|
679
|
+
* Useful for creating constant columns or injecting computed data.
|
|
680
|
+
*
|
|
681
|
+
* The data is provided via dataInfo which contains the actual values
|
|
682
|
+
* or reference to where data is stored.
|
|
683
|
+
*
|
|
684
|
+
* @template T - Type spec type
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* // Create inline column with constant values
|
|
688
|
+
* {
|
|
689
|
+
* type: 'inlineColumn',
|
|
690
|
+
* spec: { axes: ['sample'], columns: ['Int'] },
|
|
691
|
+
* dataInfo: { ... } // JsonDataInfo object
|
|
692
|
+
* }
|
|
693
|
+
*/
|
|
694
|
+
export interface QueryInlineColumn<T> {
|
|
695
|
+
type: 'inlineColumn';
|
|
696
|
+
/** Type specification defining axes and column types */
|
|
697
|
+
spec: T;
|
|
698
|
+
/** Data information containing or referencing the actual values */
|
|
699
|
+
dataInfo: JsonDataInfo;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Sparse to dense column query operation.
|
|
703
|
+
*
|
|
704
|
+
* Expands a column across additional axes using Cartesian product.
|
|
705
|
+
* Creates all combinations of existing axis values with new axis values.
|
|
706
|
+
*
|
|
707
|
+
* **Use case**: When you need to repeat/broadcast a column across
|
|
708
|
+
* new dimensions that it doesn't originally have.
|
|
709
|
+
*
|
|
710
|
+
* **Behavior**:
|
|
711
|
+
* - Takes an existing column
|
|
712
|
+
* - Expands it across specified axes indices
|
|
713
|
+
* - Result has Cartesian product of original axes × new axes
|
|
714
|
+
*
|
|
715
|
+
* @template SO - Spec override type
|
|
716
|
+
*
|
|
717
|
+
* @example
|
|
718
|
+
* // Expand column across axes at indices 0 and 2
|
|
719
|
+
* {
|
|
720
|
+
* type: 'sparseToDenseColumn',
|
|
721
|
+
* columnId: 'col_abc123',
|
|
722
|
+
* axesIndices: [0, 2],
|
|
723
|
+
* specOverride: { ... } // optional spec modifications
|
|
724
|
+
* }
|
|
725
|
+
*/
|
|
726
|
+
export interface QuerySparseToDenseColumn<SO> {
|
|
727
|
+
type: 'sparseToDenseColumn';
|
|
728
|
+
/** ID of the column to cross-join */
|
|
729
|
+
columnId: PObjectId;
|
|
730
|
+
/** Optional override for the column specification */
|
|
731
|
+
specOverride?: SO;
|
|
732
|
+
/** Indices of axes to expand across */
|
|
733
|
+
axesIndices: number[];
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Symmetric join query operation (inner join or full outer join).
|
|
737
|
+
*
|
|
738
|
+
* Joins multiple queries symmetrically (order doesn't affect result semantics).
|
|
739
|
+
*
|
|
740
|
+
* **Inner Join** (`type: 'innerJoin'`):
|
|
741
|
+
* - Returns only records that exist in ALL entries
|
|
742
|
+
* - Null join keys don't match, so records with null keys are excluded
|
|
743
|
+
* - Result contains intersection of all entries by axis keys
|
|
744
|
+
*
|
|
745
|
+
* **Full Join** (`type: 'fullJoin'`):
|
|
746
|
+
* - Returns all records from ALL entries
|
|
747
|
+
* - Missing values are filled with nulls
|
|
748
|
+
* - Null join keys create separate groups
|
|
749
|
+
* - Result contains union of all entries by axis keys
|
|
750
|
+
*
|
|
751
|
+
* **Single entry**: Acts as identity (returns entry unchanged).
|
|
752
|
+
*
|
|
753
|
+
* @template JE - Join entry type
|
|
754
|
+
*
|
|
755
|
+
* @example
|
|
756
|
+
* // Inner join: only records present in all queries
|
|
757
|
+
* {
|
|
758
|
+
* type: 'innerJoin',
|
|
759
|
+
* entries: [query1Entry, query2Entry, query3Entry]
|
|
760
|
+
* }
|
|
761
|
+
*
|
|
762
|
+
* // Full join: all records from all queries, nulls for missing
|
|
763
|
+
* {
|
|
764
|
+
* type: 'fullJoin',
|
|
765
|
+
* entries: [query1Entry, query2Entry]
|
|
766
|
+
* }
|
|
767
|
+
*/
|
|
768
|
+
export interface QuerySymmetricJoin<JE extends QueryJoinEntry<unknown>> {
|
|
769
|
+
/** 'innerJoin' for intersection, 'fullJoin' for union with nulls */
|
|
770
|
+
type: 'innerJoin' | 'fullJoin';
|
|
771
|
+
/** Queries to join (at least one required) */
|
|
772
|
+
entries: JE[];
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Join entry wrapper.
|
|
776
|
+
*
|
|
777
|
+
* Wraps a query to be used as an entry in join operations.
|
|
778
|
+
* The wrapper allows for additional metadata or configuration
|
|
779
|
+
* on each joined query (e.g., specifying join keys, aliases).
|
|
780
|
+
*
|
|
781
|
+
* @template Q - Query type
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* // Wrap a query for use in join
|
|
785
|
+
* { entry: someQuery }
|
|
786
|
+
*/
|
|
787
|
+
export interface QueryJoinEntry<Q> {
|
|
788
|
+
/** The query to be joined */
|
|
789
|
+
entry: Q;
|
|
790
|
+
}
|
|
791
|
+
//# sourceMappingURL=query_common.d.ts.map
|