@pythia-software/query-table-core 0.5.0 → 0.6.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/index.d.ts CHANGED
@@ -1,143 +1,3 @@
1
- /** All filter operators across both source projects, unioned. Every value can
2
- * be NULL, so `is_null`/`is_not_null` are valid for every field type. */
3
- type FilterOp = "=" | "!=" | ">" | ">=" | "<" | "<=" | "contains" | "starts_with" | "ends_with" | "matches_regex" | "not_matches_regex" | "length_gt" | "length_lt" | "length_eq" | "includes" | "is_null" | "is_not_null";
4
- /** A single filter predicate (a "literal" in CNF terms). `value` is always the
5
- * raw string the UI captured; coercion to number/bool/date happens at
6
- * apply/compile time based on the field's declared type (never on the value's
7
- * runtime shape). Unused for the nullary ops (`is_null`/`is_not_null`).
8
- *
9
- * `negated` wraps the predicate in a logical NOT. It is only ever set for ops
10
- * that have no complementary operator (`contains`/`starts_with`/`ends_with`/
11
- * `includes`); ops with a complement negate by flipping the op itself (`>=`→`<`,
12
- * `=`→`!=`, `is_null`→`is_not_null`, `matches_regex`→`not_matches_regex`) — see
13
- * `negateClause` in ops.ts. NOT is null-exclusive: a NULL/empty value satisfies
14
- * neither the predicate nor its negation, matching `not_matches_regex`. */
15
- interface WhereClause {
16
- field: string;
17
- op: FilterOp;
18
- value: string;
19
- negated?: boolean;
20
- setFilter?: SetFilterMetadata;
21
- }
22
- type SetFilterMode = "any" | "all" | "none" | "empty";
23
- /** Presentation-only identity; execution always uses the accompanying predicates. */
24
- interface SetFilterMetadata {
25
- id: string;
26
- mode: SetFilterMode;
27
- values: string[];
28
- }
29
- /** A disjunction of predicates — the inner OR of conjunctive normal form. Every
30
- * member is a plain literal; nesting is intentionally not allowed yet (CNF
31
- * only), but the object shape leaves room to grow. */
32
- interface OrGroup {
33
- any: WhereClause[];
34
- setFilter?: SetFilterMetadata;
35
- }
36
- /** One conjunct of the WHERE clause: either a single predicate or an OR group.
37
- * `QueryState.where` is the AND of these terms, so the whole WHERE is
38
- * conjunctive normal form — `(a) AND (b OR c) AND (d)`. A bare literal is
39
- * equivalent to a one-element OR group; normalization flattens singleton groups
40
- * back to a literal so equality/encoding stay canonical. */
41
- type WhereTerm = WhereClause | OrGroup;
42
- /** Narrow a term to an OR group. A literal always carries `field`; a group never
43
- * does and always carries an `any` array. */
44
- declare function isOrGroup(term: WhereTerm): term is OrGroup;
45
- /** The predicate literals a term contributes, in order: the term itself for a
46
- * literal, or its members for a group. Handy for anything that must visit every
47
- * predicate regardless of grouping (field allowlisting, SELECT projection). */
48
- declare function predicatesOf(term: WhereTerm): WhereClause[];
49
- /** One ORDER BY term. Array order in `QueryState.orderBy` is the sort priority. */
50
- interface OrderByClause {
51
- field: string;
52
- dir: "asc" | "desc";
53
- /** NULL placement. Omitted = "last" (the historical default both projects used,
54
- * preserved so old `?q=` links round-trip identically). */
55
- nulls?: "first" | "last";
56
- /** Sort by the first capture group of a regex match (or by the whole match
57
- * when the pattern has no capture group). A non-match produces NULL. Regex
58
- * syntax is interpreted by the executor (JavaScript locally, PostgreSQL on
59
- * the bundled Go backend), so portable patterns should use their common
60
- * syntax subset. */
61
- extract?: {
62
- regex: string;
63
- };
64
- }
65
- /** One column in the SELECT list, plus the view state that travels with it.
66
- * Order in `QueryState.select` is the left-to-right display order. */
67
- interface SelectColumn {
68
- field: string;
69
- /** Pixel width override. Omitted = FieldDef.select.width, else the type default. */
70
- width?: number;
71
- }
72
- /** A single aggregate operation. `count` is the only op that needs no measure
73
- * column (it counts rows); the rest reduce one column's values. The server-side
74
- * matrix (backends/go aggOpAllowed + the TS AGG_OPS_BY_TYPE) decides which ops a
75
- * field's type permits. */
76
- type AggOp = "count" | "count_distinct" | "sum" | "avg" | "min" | "max";
77
- /** One optional "metric" pinned above the table: a single aggregate over a single
78
- * measure column, optionally broken down by one or more group columns.
79
- *
80
- * Scope is deliberately the *whole filtered set* — the same WHERE as the table,
81
- * but NOT its ORDER BY / LIMIT / OFFSET. It is always evaluated on the server
82
- * (a real GROUP BY), so it reflects every matching row, not just the visible
83
- * page. Lives inside QueryState so it round-trips through `?q=`, saved queries,
84
- * and undo/redo for free — a saved query is a saved dashboard. */
85
- interface AggregationClause {
86
- /** Stable id; keys the metric panel and survives a `?q=` round-trip. */
87
- id: string;
88
- op: AggOp;
89
- /** Measure column (FieldDef.name). Omit only for `count` (⇒ COUNT(*)). */
90
- field?: string;
91
- /** Group-by columns, in axis order. `[]` = a single grand-total value.
92
- * One ⇒ a list/bar breakdown; two ⇒ an x/y pivot; three+ ⇒ a flat table. */
93
- groupBy: string[];
94
- /** Panel header override; defaults to a derived label like "avg total". */
95
- label?: string;
96
- }
97
- interface QueryState {
98
- /** Ordered SELECT list + per-column widths. Empty = the schema's default columns. */
99
- select: SelectColumn[];
100
- /** WHERE in conjunctive normal form: the AND of these terms, each a single
101
- * predicate or an OR group. A flat list of literals (no groups) is the common
102
- * case and the legacy shape, decoded unchanged. */
103
- where: WhereTerm[];
104
- /** Multi-sort terms in priority order. Empty = the schema's default sort. */
105
- orderBy: OrderByClause[];
106
- /** Page size. */
107
- limit: number;
108
- /** Page offset (rows). */
109
- offset: number;
110
- /** Optional aggregate metrics shown above the table. Omitted/empty = none.
111
- * Each runs as its own server GROUP BY over the WHERE-filtered set (no paging). */
112
- aggregations?: AggregationClause[];
113
- }
114
- /** A row's stable identity, used for selection and per-row refresh. */
115
- type RowId = string | number;
116
- /** The query a fresh table starts from before schema defaults are layered on.
117
- * Empty `select`/`orderBy`/`where` mean "defer to the schema", which also keeps
118
- * encoded `?q=` tokens short (defaults are omitted). */
119
- declare const EMPTY_QUERY: QueryState;
120
- /** Structural limits applied whenever query state crosses a trust boundary
121
- * (URL, storage, an imperative setQuery call, or a server projection). Row
122
- * limits may use the full safe-integer range; consumers and their backends own
123
- * any smaller operational cap appropriate for their dataset. */
124
- declare const MAX_QUERY_LIMIT: number;
125
- declare const MAX_QUERY_OFFSET = 1000000;
126
- declare const MAX_SELECT_COLUMNS = 200;
127
- declare const MAX_WHERE_CLAUSES = 100;
128
- declare const MAX_ORDER_BY_TERMS = 20;
129
- declare const MAX_AGGREGATIONS = 20;
130
- declare const MAX_GROUP_BY_FIELDS = 20;
131
- declare const MAX_QUERY_TOKEN_LENGTH: number;
132
- /** Convert unknown input into a bounded, structurally valid QueryState.
133
- * Invalid members are dropped; invalid scalar paging values use the supplied
134
- * fallback. This function is intentionally schema-agnostic—field allowlisting
135
- * still happens in toServerQuery and in the backend compiler. */
136
- declare function normalizeQueryState(input: unknown, fallback?: QueryState): QueryState;
137
- /** Structural equality on two queries — used to decide whether a `?q=` write or a
138
- * refetch is actually needed (avoids history spam / redundant fetches). */
139
- declare function queriesEqual(a: QueryState, b: QueryState): boolean;
140
-
141
1
  type FieldType = "text" | "number" | "enum" | "datetime" | "bool" | "textarray";
142
2
  type Align = "left" | "right" | "center";
143
3
  /** A cell renderer is resolved by name against a `RenderRegistry` (in
@@ -257,27 +117,356 @@ interface FieldSchema<Row = any> {
257
117
  /** Page size for a fresh query. */
258
118
  defaultLimit?: number;
259
119
  }
260
- declare function isFilterable(f: FieldDef): boolean;
261
- declare function isPushdownFilter(f: FieldDef): boolean;
262
- declare function isSortable(f: FieldDef): boolean;
263
- declare function isSelectable(f: FieldDef): boolean;
264
- declare function filterValues(f: FieldDef): FilterValues;
265
- /** Index fields by name for O(1) lookup. */
266
- declare function indexFields<Row>(schema: FieldSchema<Row>): Map<string, FieldDef<Row>>;
267
- /** Resolve the ordered, selectable FieldDefs for a query, falling back to schema
268
- * defaults, then to every `select.default` field. Unknown/duplicate/unselectable
269
- * names in `select` are dropped. */
270
- declare function selectedFields<Row>(schema: FieldSchema<Row>, q: {
120
+ declare function isFilterable(f: FieldDef): boolean;
121
+ declare function isPushdownFilter(f: FieldDef): boolean;
122
+ declare function isSortable(f: FieldDef): boolean;
123
+ declare function isSelectable(f: FieldDef): boolean;
124
+ declare function filterValues(f: FieldDef): FilterValues;
125
+ /** Index fields by name for O(1) lookup. */
126
+ declare function indexFields<Row>(schema: FieldSchema<Row>): Map<string, FieldDef<Row>>;
127
+ /** Resolve the ordered, selectable FieldDefs for a query, falling back to schema
128
+ * defaults, then to every `select.default` field. Unknown/duplicate/unselectable
129
+ * names in `select` are dropped. */
130
+ declare function selectedFields<Row>(schema: FieldSchema<Row>, q: {
131
+ select: SelectColumn[];
132
+ }): FieldDef<Row>[];
133
+ /** Return the canonical name for a query token, or undefined when unresolved. */
134
+ declare function resolveFieldName<Row>(schema: FieldSchema<Row>, field: string): string | undefined;
135
+ /** Read a field's value from a row: derived `accessor` if present, else the
136
+ * backend `path` (dotted) / `name`. Returns null when any path segment is missing. */
137
+ declare function readFieldValue<Row, V = unknown>(field: FieldDef<Row, V>, row: Row): V | null;
138
+ /** Parse + validate a raw JSON schema document into a FieldSchema. The doc is the
139
+ * same one the Go backend loads; here we drop backend `bindings` (the frontend
140
+ * never sees SQL) and leave `render` as a string key the consumer maps to a
141
+ * renderer at runtime. Throws with a readable message on a malformed document. */
142
+ declare function loadSchema<Row = any>(doc: unknown): FieldSchema<Row>;
143
+
144
+ type FormulaType = Exclude<FieldType, "enum"> | "null";
145
+ type FormulaValue = string | number | boolean | string[] | null;
146
+ interface FormulaDiagnostic {
147
+ message: string;
148
+ from: number;
149
+ to: number;
150
+ }
151
+ type FormulaNode = {
152
+ kind: "literal";
153
+ value: FormulaValue;
154
+ from: number;
155
+ to: number;
156
+ } | {
157
+ kind: "field";
158
+ name: string;
159
+ valueType?: FormulaType;
160
+ from: number;
161
+ to: number;
162
+ } | {
163
+ kind: "call";
164
+ name: string;
165
+ args: FormulaNode[];
166
+ from: number;
167
+ to: number;
168
+ };
169
+ interface FormulaPlan {
170
+ ast: FormulaNode;
171
+ dependencies: string[];
172
+ type: FormulaType;
173
+ }
174
+ interface RegexInspection {
175
+ input: string;
176
+ start: number;
177
+ end: number;
178
+ groups: (string | null)[];
179
+ }
180
+ interface FormulaResult {
181
+ value: FormulaValue;
182
+ error?: string;
183
+ regex?: RegexInspection;
184
+ }
185
+ interface FormulaFunction {
186
+ name: string;
187
+ signature: string;
188
+ description: string;
189
+ min: number;
190
+ max: number;
191
+ result: FormulaType | "branch";
192
+ args: FormulaType[] | "any";
193
+ }
194
+ declare const FORMULA_FUNCTIONS: FormulaFunction[];
195
+ declare class FormulaError extends Error {
196
+ from: number;
197
+ to: number;
198
+ constructor(message: string, from?: number, to?: number);
199
+ }
200
+ declare function compileFormula(source: string, fields: readonly {
201
+ name: string;
202
+ type: FieldType;
203
+ }[], resolve?: (name: string) => FormulaPlan | undefined, extension?: (node: FormulaNode, check: (node: FormulaNode) => FormulaType) => FormulaType | undefined): FormulaPlan;
204
+ /** Self-contained runtime: serialized into the browser worker, never user code. */
205
+ declare function formulaRuntime(ast: FormulaNode, inputs: Record<string, FormulaValue>, extension?: (node: Extract<FormulaNode, {
206
+ kind: "call";
207
+ }>) => FormulaResult | undefined): FormulaResult;
208
+
209
+ type MetricValue = number | string | boolean | null;
210
+ type MetricKey = MetricValue;
211
+ type MetricScope = "allMatching" | "shownRows";
212
+ interface MetricValueFormat {
213
+ kind: "number" | "percent" | "duration" | "date" | "time" | "datetime";
214
+ decimals?: number;
215
+ sourceUnit?: "milliseconds" | "seconds" | "minutes" | "hours" | "days" | "iso" | "epochSeconds" | "epochMilliseconds" | "secondsOfDay" | "millisecondsOfDay";
216
+ style?: "human" | "long" | "clock" | "custom" | "iso";
217
+ pattern?: string;
218
+ timeZone?: string;
219
+ }
220
+ /** Bounds use raw result units; omitted bounds are inferred from the data. */
221
+ interface MetricAxisScale {
222
+ mode?: "linear" | "log";
223
+ min?: number;
224
+ max?: number;
225
+ }
226
+ interface MetricDisplay {
227
+ kind: "auto" | "value" | "table" | "list" | "bar-horizontal" | "bar-vertical" | "line" | "pie" | "donut" | "scatter" | "box" | "histogram";
228
+ valueLabel?: string;
229
+ xLabel?: string;
230
+ yLabel?: string;
231
+ format?: MetricValueFormat;
232
+ xFormat?: MetricValueFormat;
233
+ yFormat?: MetricValueFormat;
234
+ legendPosition?: "left" | "right" | "top" | "bottom" | "none";
235
+ list?: {
236
+ showBars?: boolean;
237
+ useGroupColors?: boolean;
238
+ showValues?: boolean;
239
+ };
240
+ pivot?: {
241
+ swap?: boolean;
242
+ rowDir?: "asc" | "desc";
243
+ columnDir?: "asc" | "desc";
244
+ };
245
+ boxMean?: boolean;
246
+ xScale?: MetricAxisScale;
247
+ yScale?: MetricAxisScale;
248
+ }
249
+ interface MetricLayout {
250
+ widthRem: number;
251
+ heightRem: number;
252
+ minWidthRem: number;
253
+ minHeightRem: number;
254
+ }
255
+ interface MetricDistribution {
256
+ kind: "box" | "histogram";
257
+ input: string;
258
+ whiskers?: "minmax" | "tukey";
259
+ bins?: number;
260
+ }
261
+ interface MetricSort {
262
+ key: "value" | "y" | "count" | "samples" | `group${number}`;
263
+ dir: "asc" | "desc";
264
+ nulls?: "first" | "last";
265
+ }
266
+ interface MetricBoxSummary {
267
+ n: number;
268
+ min: number;
269
+ q1: number;
270
+ median: number;
271
+ q3: number;
272
+ max: number;
273
+ mean: number;
274
+ low: number;
275
+ high: number;
276
+ outliers: number[];
277
+ outlierCount: number;
278
+ whiskers: "minmax" | "tukey";
279
+ method: "exact-linear";
280
+ }
281
+ type MetricDistributionResult = {
282
+ kind: "box";
283
+ summary: MetricBoxSummary | null;
284
+ } | {
285
+ kind: "histogram";
286
+ edges: number[];
287
+ counts: number[];
288
+ n: number;
289
+ };
290
+ interface MetricDiagnostic extends FormulaDiagnostic {
291
+ metricId?: string;
292
+ code?: string;
293
+ }
294
+ /** Host must enforce snapshot against the row response; this token alone does not pin data. */
295
+ interface MetricQuery {
296
+ snapshot?: string;
297
+ profile?: string;
298
+ expectedRevisions?: Record<string, string>;
299
+ planToken?: string;
300
+ version: 2;
301
+ where: WhereTerm[];
302
+ orderBy: OrderByClause[];
303
+ limit: number;
304
+ offset: number;
305
+ metrics: AggregationClause[];
306
+ diagnostics: MetricDiagnostic[];
307
+ }
308
+ interface MetricCapabilities {
309
+ version: 2;
310
+ expressions?: boolean;
311
+ shownRows?: boolean;
312
+ distributions?: boolean;
313
+ computedFields?: boolean;
314
+ maxGroups?: number;
315
+ profile?: string;
316
+ }
317
+
318
+ /** All filter operators across both source projects, unioned. Every value can
319
+ * be NULL, so `is_null`/`is_not_null` are valid for every field type. */
320
+ type FilterOp = "=" | "!=" | ">" | ">=" | "<" | "<=" | "contains" | "starts_with" | "ends_with" | "matches_regex" | "not_matches_regex" | "length_gt" | "length_lt" | "length_eq" | "includes" | "is_null" | "is_not_null";
321
+ /** A single filter predicate (a "literal" in CNF terms). `value` is always the
322
+ * raw string the UI captured; coercion to number/bool/date happens at
323
+ * apply/compile time based on the field's declared type (never on the value's
324
+ * runtime shape). Datetime comparisons also accept signed duration offsets
325
+ * such as "-1h" or "+8d2h10m", resolved relative to execution time.
326
+ * Unused for the nullary ops (`is_null`/`is_not_null`).
327
+ *
328
+ * `negated` wraps the predicate in a logical NOT. It is only ever set for ops
329
+ * that have no complementary operator (`contains`/`starts_with`/`ends_with`/
330
+ * `includes`); ops with a complement negate by flipping the op itself (`>=`→`<`,
331
+ * `=`→`!=`, `is_null`→`is_not_null`, `matches_regex`→`not_matches_regex`) — see
332
+ * `negateClause` in ops.ts. NOT is null-exclusive: a NULL/empty value satisfies
333
+ * neither the predicate nor its negation, matching `not_matches_regex`. */
334
+ interface WhereClause {
335
+ field: string;
336
+ op: FilterOp;
337
+ value: string;
338
+ negated?: boolean;
339
+ setFilter?: SetFilterMetadata;
340
+ }
341
+ type SetFilterMode = "any" | "all" | "none" | "empty";
342
+ /** Presentation-only identity; execution always uses the accompanying predicates. */
343
+ interface SetFilterMetadata {
344
+ id: string;
345
+ mode: SetFilterMode;
346
+ values: string[];
347
+ }
348
+ /** A disjunction of predicates — the inner OR of conjunctive normal form. Every
349
+ * member is a plain literal; nesting is intentionally not allowed yet (CNF
350
+ * only), but the object shape leaves room to grow. */
351
+ interface OrGroup {
352
+ any: WhereClause[];
353
+ setFilter?: SetFilterMetadata;
354
+ }
355
+ /** One conjunct of the WHERE clause: either a single predicate or an OR group.
356
+ * `QueryState.where` is the AND of these terms, so the whole WHERE is
357
+ * conjunctive normal form — `(a) AND (b OR c) AND (d)`. A bare literal is
358
+ * equivalent to a one-element OR group; normalization flattens singleton groups
359
+ * back to a literal so equality/encoding stay canonical. */
360
+ type WhereTerm = WhereClause | OrGroup;
361
+ /** Narrow a term to an OR group. A literal always carries `field`; a group never
362
+ * does and always carries an `any` array. */
363
+ declare function isOrGroup(term: WhereTerm): term is OrGroup;
364
+ /** The predicate literals a term contributes, in order: the term itself for a
365
+ * literal, or its members for a group. Handy for anything that must visit every
366
+ * predicate regardless of grouping (field allowlisting, SELECT projection). */
367
+ declare function predicatesOf(term: WhereTerm): WhereClause[];
368
+ /** One ORDER BY term. Array order in `QueryState.orderBy` is the sort priority. */
369
+ interface OrderByClause {
370
+ field: string;
371
+ dir: "asc" | "desc";
372
+ /** NULL placement. Omitted = "last" (the historical default both projects used,
373
+ * preserved so old `?q=` links round-trip identically). */
374
+ nulls?: "first" | "last";
375
+ /** Sort by the first capture group of a regex match (or by the whole match
376
+ * when the pattern has no capture group). A non-match produces NULL. Regex
377
+ * syntax is interpreted by the executor (JavaScript locally, PostgreSQL on
378
+ * the bundled Go backend), so portable patterns should use their common
379
+ * syntax subset. */
380
+ extract?: {
381
+ regex: string;
382
+ };
383
+ }
384
+ /** One column in the SELECT list, plus the view state that travels with it.
385
+ * Order in `QueryState.select` is the left-to-right display order. */
386
+ interface SelectColumn {
387
+ field: string;
388
+ /** Pixel width override. Omitted = FieldDef.select.width, else the type default. */
389
+ width?: number;
390
+ }
391
+ /** A single aggregate operation. `count` is the only op that needs no measure
392
+ * column (it counts rows); the rest reduce one column's values. The server-side
393
+ * matrix (backends/go aggOpAllowed + the TS AGG_OPS_BY_TYPE) decides which ops a
394
+ * field's type permits. */
395
+ type AggOp = "count" | "count_distinct" | "sum" | "avg" | "min" | "max";
396
+ /** One optional "metric" pinned above the table: a single aggregate over a single
397
+ * measure column, optionally broken down by one or more group columns.
398
+ *
399
+ * Scope is deliberately the *whole filtered set* — the same WHERE as the table,
400
+ * but NOT its ORDER BY / LIMIT / OFFSET. It is always evaluated on the server
401
+ * (a real GROUP BY), so it reflects every matching row, not just the visible
402
+ * page. Lives inside QueryState so it round-trips through `?q=`, saved queries,
403
+ * and undo/redo for free — a saved query is a saved dashboard. */
404
+ interface AggregationClause {
405
+ expression?: string;
406
+ expressionY?: string;
407
+ scope?: MetricScope;
408
+ sort?: MetricSort[];
409
+ groupLimit?: number;
410
+ display?: MetricDisplay;
411
+ layout?: MetricLayout;
412
+ distribution?: MetricDistribution;
413
+ diagnostics?: string[];
414
+ /** Preserved source operation when this client does not implement it. */
415
+ unsupportedOp?: string;
416
+ /** Stable id; keys the metric panel and survives a `?q=` round-trip. */
417
+ id: string;
418
+ op: AggOp;
419
+ /** Measure column (FieldDef.name). Omit only for `count` (⇒ COUNT(*)). */
420
+ field?: string;
421
+ /** Group-by columns, in axis order. `[]` = a single grand-total value.
422
+ * One ⇒ a list/bar breakdown; two ⇒ an x/y pivot; three+ ⇒ a flat table. */
423
+ groupBy: string[];
424
+ /** Panel header override; defaults to a derived label like "avg total". */
425
+ label?: string;
426
+ }
427
+ interface QueryState {
428
+ /** Ordered SELECT list + per-column widths. Empty = the schema's default columns. */
271
429
  select: SelectColumn[];
272
- }): FieldDef<Row>[];
273
- /** Read a field's value from a row: derived `accessor` if present, else the
274
- * backend `path` (dotted) / `name`. Returns null when any path segment is missing. */
275
- declare function readFieldValue<Row, V = unknown>(field: FieldDef<Row, V>, row: Row): V | null;
276
- /** Parse + validate a raw JSON schema document into a FieldSchema. The doc is the
277
- * same one the Go backend loads; here we drop backend `bindings` (the frontend
278
- * never sees SQL) and leave `render` as a string key the consumer maps to a
279
- * renderer at runtime. Throws with a readable message on a malformed document. */
280
- declare function loadSchema<Row = any>(doc: unknown): FieldSchema<Row>;
430
+ /** WHERE in conjunctive normal form: the AND of these terms, each a single
431
+ * predicate or an OR group. A flat list of literals (no groups) is the common
432
+ * case and the legacy shape, decoded unchanged. */
433
+ where: WhereTerm[];
434
+ /** Multi-sort terms in priority order. Empty = the schema's default sort. */
435
+ orderBy: OrderByClause[];
436
+ /** Page size. */
437
+ limit: number;
438
+ /** Page offset (rows). */
439
+ offset: number;
440
+ /** Optional aggregate metrics shown above the table. Omitted/empty = none.
441
+ * Each runs as its own server GROUP BY over the WHERE-filtered set (no paging). */
442
+ aggregations?: AggregationClause[];
443
+ }
444
+ /** A row's stable identity, used for selection and per-row refresh. */
445
+ type RowId = string | number;
446
+ /** The query a fresh table starts from before schema defaults are layered on.
447
+ * Empty `select`/`orderBy`/`where` mean "defer to the schema", which also keeps
448
+ * encoded `?q=` tokens short (defaults are omitted). */
449
+ declare const EMPTY_QUERY: QueryState;
450
+ /** Structural limits applied whenever query state crosses a trust boundary
451
+ * (URL, storage, an imperative setQuery call, or a server projection). Row
452
+ * limits may use the full safe-integer range; consumers and their backends own
453
+ * any smaller operational cap appropriate for their dataset. */
454
+ declare const MAX_QUERY_LIMIT: number;
455
+ declare const MAX_QUERY_OFFSET = 1000000;
456
+ declare const MAX_SELECT_COLUMNS = 200;
457
+ declare const MAX_WHERE_CLAUSES = 100;
458
+ declare const MAX_ORDER_BY_TERMS = 20;
459
+ declare const MAX_AGGREGATIONS = 20;
460
+ declare const MAX_GROUP_BY_FIELDS = 20;
461
+ declare const MAX_QUERY_TOKEN_LENGTH: number;
462
+ /** Convert unknown input into a bounded, structurally valid QueryState.
463
+ * Invalid members are dropped; invalid scalar paging values use the supplied
464
+ * fallback. This function is intentionally schema-agnostic—field allowlisting
465
+ * still happens in toServerQuery and in the backend compiler. */
466
+ declare function normalizeQueryState(input: unknown, fallback?: QueryState): QueryState;
467
+ /** Structural equality on two queries — used to decide whether a `?q=` write or a
468
+ * refetch is actually needed (avoids history spam / redundant fetches). */
469
+ declare function queriesEqual(a: QueryState, b: QueryState): boolean;
281
470
 
282
471
  /** The logical negation of a predicate. Prefers flipping to the complementary
283
472
  * operator (nicer to read, and the server's op allowlist already covers it);
@@ -320,7 +509,7 @@ declare function opAllowedForType(type: FieldType, op: FilterOp): boolean;
320
509
  /** Coerce a raw string value to the type the field expects, for client-side
321
510
  * comparison. Throws on invalid input (e.g. a non-numeric value on a number
322
511
  * field) so callers can surface it rather than silently mis-filtering. */
323
- declare function coerceValue(type: FieldType, raw: string): string | number | boolean;
512
+ declare function coerceValue(type: FieldType, raw: string, now?: number): string | number | boolean;
324
513
 
325
514
  /** Default aggregate ops per field type. A FieldDef.aggregate.ops overrides this.
326
515
  * `count`/`count_distinct` work on anything countable; sum/avg are numeric-only;
@@ -371,22 +560,40 @@ declare function toServerQuery<Row>(q: QueryState, schema: FieldSchema<Row>): Se
371
560
  * metrics describe every matching row, not the visible page. Mirrors the Go
372
561
  * AggSpec list. */
373
562
  interface AggregationRequest {
563
+ diagnostics?: MetricDiagnostic[];
374
564
  where: WhereTerm[];
375
565
  aggregations: AggregationClause[];
376
566
  }
377
567
  /** One group's result. `keys` has one entry per AggregationClause.groupBy field,
378
568
  * in axis order (`[]` for a grand total); a null key is the NULL/empty bucket. */
379
569
  interface AggregationBucket {
380
- keys: (string | null)[];
570
+ keys: MetricKey[];
571
+ error?: string;
572
+ y?: MetricValue;
573
+ yError?: string;
574
+ components?: {
575
+ expression: string;
576
+ value: MetricValue;
577
+ }[];
578
+ nullCount?: number;
579
+ inputErrorCount?: number;
580
+ distribution?: MetricDistributionResult;
381
581
  /** The metric: a number for count/sum/avg, or the column's value for min/max
382
582
  * (which may be a string for text/datetime). null when undefined (e.g. avg of
383
583
  * an all-null column). */
384
- value: number | string | null;
584
+ value: MetricValue;
385
585
  /** COUNT(*) of rows in the group — always present, even when `value` isn't a
386
586
  * count, so the panel can show group sizes / shares. */
387
587
  count: number;
388
588
  }
389
589
  interface AggregationResultEntry {
590
+ /** Exact omitted additive quantity; unavailable for ratios/averages/distinct. */
591
+ other?: AggregationBucket;
592
+ error?: string;
593
+ scope?: MetricScope;
594
+ processedRows?: number;
595
+ groupCount?: number;
596
+ coverage?: "exact" | "partial";
390
597
  /** Echoes AggregationClause.id. */
391
598
  id: string;
392
599
  buckets: AggregationBucket[];
@@ -401,6 +608,145 @@ interface AggregationResult {
401
608
  * unknown field are dropped — the server has no SQL for them. */
402
609
  declare function toAggregationQuery<Row>(q: QueryState, schema: FieldSchema<Row>): AggregationRequest;
403
610
 
611
+ /** Reserved field token namespace. Query state stores IDs, never formula source. */
612
+ declare const COMPUTED_PREFIX = "@computed/";
613
+ declare const computedFieldName: (id: string) => string;
614
+ declare const isComputedField: (name: string) => boolean;
615
+ interface ComputedColumn {
616
+ id: string;
617
+ label: string;
618
+ expression: {
619
+ language: "qt-expr";
620
+ version: 1;
621
+ source: string;
622
+ };
623
+ /** Optimistic concurrency token issued by the store. */
624
+ revision: string;
625
+ }
626
+ type ComputedColumnDraft = Omit<ComputedColumn, "revision">;
627
+ interface ComputedColumnStore {
628
+ /** Return the complete authorized catalogue for this dataset. */
629
+ list(dataset: string, signal?: AbortSignal): Promise<ComputedColumn[]>;
630
+ /** null creates a new ID; updates must match the current revision. */
631
+ save(dataset: string, column: ComputedColumnDraft, expectedRevision: string | null): Promise<ComputedColumn>;
632
+ /** Optional push invalidation, including changes from other sessions. */
633
+ subscribe?(dataset: string, listener: () => void): () => void;
634
+ }
635
+ declare function validateComputedColumn(input: unknown): ComputedColumn;
636
+ declare function memoryComputedColumnStore(seed?: Record<string, ComputedColumn[]>): ComputedColumnStore;
637
+ /** REST adapter. The implementing server owns authorization and DB persistence.
638
+ * GET base?dataset=… → ComputedColumn[]
639
+ * PUT base?dataset=… → {column, expectedRevision} → ComputedColumn
640
+ * Return HTTP 409 for a stale revision. No formula evaluation happens there. */
641
+ declare function httpComputedColumnStore(base: string, fetcher?: typeof fetch): ComputedColumnStore;
642
+ interface ComputedCellError {
643
+ computedError: string;
644
+ }
645
+ declare function isComputedCellError(value: unknown): value is ComputedCellError;
646
+ interface PreviewGroup {
647
+ inputs: FormulaValue[];
648
+ result: FormulaResult;
649
+ count: number;
650
+ }
651
+ interface ColumnPreview {
652
+ dependencies: string[];
653
+ groups: PreviewGroup[];
654
+ processed: number;
655
+ total: number;
656
+ nulls: number;
657
+ errors: number;
658
+ }
659
+ declare function groupPreview(dependencies: string[], inputs: Record<string, FormulaValue>[], results: FormulaResult[], total: number): ColumnPreview;
660
+ /** Server-issued capabilities are hints for client planning, never authorization. */
661
+ interface ComputedFieldCapabilities {
662
+ type: FieldType;
663
+ select: boolean;
664
+ sort: boolean;
665
+ measure: boolean;
666
+ group: boolean;
667
+ reason?: string;
668
+ }
669
+ interface ComputedExecution {
670
+ profile: string;
671
+ planToken: string;
672
+ resolvedRevisions: Record<string, string>;
673
+ fields: Record<string, ComputedFieldCapabilities>;
674
+ fingerprint?: string;
675
+ snapshot?: string;
676
+ }
677
+ type RowComputedValues = Record<string, {
678
+ value: MetricValue;
679
+ error?: {
680
+ code: string;
681
+ };
682
+ }>;
683
+
684
+ /** Portable datetime/offset bound in milliseconds (also below MAX_SAFE_INTEGER). */
685
+ declare const MAX_RELATIVE_TIME_MS = 8640000000000000;
686
+ /** A signed elapsed offset, e.g. -1h or +8d2h10m. The sign applies to the
687
+ * complete sum. Returns null for absolute values or invalid duration syntax.
688
+ * Units are lowercase; amounts are whole integers. No whitespace, calendar
689
+ * arithmetic, locale, or Date.parse heuristics are used. */
690
+ declare function parseRelativeDuration(value: string): number | null;
691
+ /** Local execution only. The server independently owns its execution clock. */
692
+ interface QueryEvaluationOptions {
693
+ now?: number;
694
+ }
695
+
696
+ interface MetricPlan extends FormulaPlan {
697
+ aggregates: Extract<FormulaNode, {
698
+ kind: "call";
699
+ }>[];
700
+ aggregateTypes: FormulaType[];
701
+ }
702
+ declare function compileMetric(expression: string, schema: FieldSchema | readonly FieldDef[], resolve?: (name: string) => FormulaPlan | undefined): MetricPlan;
703
+ /** Row plans for worker evaluation. Null denotes COUNT(), which requires only row count. */
704
+ declare function metricAggregatePlans(plan: MetricPlan): (FormulaPlan | null)[];
705
+ /** Reduce exact per-row worker results; errors are not silently treated as NULL. */
706
+ interface MetricReductionOptions {
707
+ /** Retained distinct entries, independently bounded from row count. */
708
+ maxDistinctValues?: number;
709
+ /** Conservative UTF-16 payload plus per-entry storage estimate. */
710
+ maxDistinctBytes?: number;
711
+ }
712
+ declare function reduceMetricValues(node: Extract<FormulaNode, {
713
+ kind: "call";
714
+ }>, results: readonly FormulaResult[], options?: MetricReductionOptions): FormulaResult;
715
+ /** Evaluate the group AST lazily from reductions indexed like plan.aggregates.
716
+ * A dead IF/COALESCE branch does not observe a failed aggregate in that branch. */
717
+ declare function evaluateMetricReductions(plan: MetricPlan, reductions: readonly FormulaResult[]): FormulaResult;
718
+ declare function metricExpression(clause: AggregationClause): string;
719
+ declare function hasRegex(plan: FormulaPlan): boolean;
720
+ declare function metricPlans(c: AggregationClause, schema: FieldSchema, resolve?: (name: string) => FormulaPlan | undefined): FormulaPlan[];
721
+ declare function validateMetric(c: AggregationClause, schema: FieldSchema, resolve?: (name: string) => FormulaPlan | undefined): FormulaDiagnostic[];
722
+ declare function metricDependencies(c: AggregationClause, schema: FieldSchema, resolve?: (name: string) => FormulaPlan | undefined): string[];
723
+ declare function metricComputationKey(clauses: readonly AggregationClause[]): string;
724
+ declare function toMetricQuery<Row>(q: QueryState, schema: FieldSchema<Row>, execution?: ComputedExecution): MetricQuery;
725
+ /** Safe pre-worker page selection. A supplied committed page needs no query execution.
726
+ * Query regex is never executed here; all-matching regex filtering is unsupported. */
727
+ declare function selectMetricShownRows<Row>(rows: Row[], q: QueryState, schema: FieldSchema<Row>, options?: MetricEvaluationOptions<Row>): Row[];
728
+ interface MetricEvaluationOptions<Row = unknown> extends QueryEvaluationOptions, MetricReductionOptions {
729
+ resolveComputed?: (name: string) => FormulaPlan | undefined;
730
+ /** Called only for regex row ASTs, using cached results from a terminable worker. */
731
+ evaluateInput?: (node: FormulaNode, row: Row, plan: FormulaPlan) => FormulaResult;
732
+ /** Exact committed page supplied by the host after filters/order/window. */
733
+ /** Escaped tuple length bound, in UTF-16 code units (default 65,536). */
734
+ maxGroupKeyLength?: number;
735
+ /** Retained group keys, map/bucket overhead and row references, plus key scratch space (default 16 MB). */
736
+ maxGroupBytes?: number;
737
+ shownRows?: Row[];
738
+ maxRows?: number;
739
+ maxGroups?: number;
740
+ /** Per-metric operation budget (default 10,000,000, allowing simple paired
741
+ * aggregates across the default one-million-row population limit). */
742
+ maxOperations?: number;
743
+ /** @deprecated Regex requires cached evaluateInput; this flag grants no execution permission. */ allowRegex?: boolean;
744
+ signal?: AbortSignal;
745
+ }
746
+ /** Typed lexicographic ordering with null placement independent of direction. */
747
+ declare function compareMetricValues(a: MetricValue, b: MetricValue): number;
748
+ declare function evaluateMetrics<Row>(rows: Row[], q: QueryState, schema: FieldSchema<Row>, options?: MetricEvaluationOptions<Row>): AggregationResult;
749
+
404
750
  interface ApplyResult<Row> {
405
751
  /** The page slice (after filter + sort + offset/limit). */
406
752
  rows: Row[];
@@ -408,17 +754,42 @@ interface ApplyResult<Row> {
408
754
  total: number;
409
755
  }
410
756
  /** Filter + multi-sort + paginate `rows` per `q`, resolving field types/paths
411
- * from `schema`. Pure; never mutates `rows`. Clauses/sorts on unknown fields are
757
+ * from `schema`. Never mutates `rows`. Relative predicates use options.now or
758
+ * one captured Date.now(). Clauses/sorts on unknown fields are
412
759
  * ignored (the backend already enforced its own allowlist). */
413
- declare function applyQuery<Row>(rows: Row[], q: QueryState, schema: FieldSchema<Row>): ApplyResult<Row>;
760
+ declare function applyQuery<Row>(rows: Row[], q: QueryState, schema: FieldSchema<Row>, options?: QueryEvaluationOptions): ApplyResult<Row>;
414
761
  /** Does one row satisfy one clause? Exposed for the CellMenu preview + tests. */
415
- declare function matchesClause<Row>(row: Row, clause: WhereClause, schema: FieldSchema<Row>): boolean;
762
+ declare function matchesClause<Row>(row: Row, clause: WhereClause, schema: FieldSchema<Row>, options?: QueryEvaluationOptions): boolean;
416
763
  /** Client-side mirror of the backend GROUP BY (the executor for `clientRows`
417
764
  * mode / the demo). Scope matches the server contract: the WHERE-filtered set
418
765
  * only — ORDER BY / LIMIT / OFFSET are intentionally ignored, so a metric
419
766
  * reflects every matching row, not the visible page. Must agree with
420
767
  * backends/go's aggregate compile on op semantics. */
421
- declare function applyAggregations<Row>(rows: Row[], q: QueryState, schema: FieldSchema<Row>): AggregationResult;
768
+ declare function applyAggregations<Row>(rows: Row[], q: QueryState, schema: FieldSchema<Row>, options?: MetricEvaluationOptions<Row>): AggregationResult;
769
+
770
+ /** Versioned row projection keeps server-computed payload separate from host row fields. */
771
+ interface ServerQueryV2 extends ServerQuery {
772
+ version: 2;
773
+ profile: string;
774
+ expectedRevisions: Record<string, string>;
775
+ planToken?: string;
776
+ /** Host must enforce this binding against the row response. */
777
+ snapshot?: string;
778
+ diagnostics: MetricDiagnostic[];
779
+ }
780
+ interface FetchRowsResultV2<Row> {
781
+ version: 2;
782
+ rows: Row[];
783
+ total: number;
784
+ computed: {
785
+ id: RowId;
786
+ values: RowComputedValues;
787
+ }[];
788
+ execution: ComputedExecution;
789
+ }
790
+ /** Project with a previously resolved server capability envelope. This does not
791
+ * authorize definitions or upload their source; the backend revalidates revisions. */
792
+ declare function toServerQueryV2<Row>(q: QueryState, schema: FieldSchema<Row>, execution: ComputedExecution): ServerQueryV2;
422
793
 
423
794
  interface FetchRowsResult<Row> {
424
795
  rows: Row[];
@@ -452,6 +823,9 @@ interface FieldStats {
452
823
  max?: string | number;
453
824
  }
454
825
  interface Transport<Row = any> {
826
+ fetchRowsV2?(query: ServerQueryV2, signal?: AbortSignal): Promise<FetchRowsResultV2<Row>>;
827
+ metricCapabilities?: MetricCapabilities;
828
+ fetchMetrics?(query: MetricQuery, signal?: AbortSignal): Promise<AggregationResult>;
455
829
  /** Run a server query. The only required method — a purely client-side table
456
830
  * can omit a Transport entirely and rely on applyQuery over local rows. */
457
831
  fetchRows(query: ServerQuery, signal?: AbortSignal): Promise<FetchRowsResult<Row>>;
@@ -506,119 +880,6 @@ declare function memoryStorageAdapter(): StorageAdapter;
506
880
  * datasets. Falls back to no persistence when storage is unavailable. */
507
881
  declare function localStorageAdapter(): StorageAdapter;
508
882
 
509
- type FormulaType = Exclude<FieldType, "enum"> | "null";
510
- type FormulaValue = string | number | boolean | string[] | null;
511
- interface FormulaDiagnostic {
512
- message: string;
513
- from: number;
514
- to: number;
515
- }
516
- type FormulaNode = {
517
- kind: "literal";
518
- value: FormulaValue;
519
- from: number;
520
- to: number;
521
- } | {
522
- kind: "field";
523
- name: string;
524
- valueType?: FormulaType;
525
- from: number;
526
- to: number;
527
- } | {
528
- kind: "call";
529
- name: string;
530
- args: FormulaNode[];
531
- from: number;
532
- to: number;
533
- };
534
- interface FormulaPlan {
535
- ast: FormulaNode;
536
- dependencies: string[];
537
- type: FormulaType;
538
- }
539
- interface RegexInspection {
540
- input: string;
541
- start: number;
542
- end: number;
543
- groups: (string | null)[];
544
- }
545
- interface FormulaResult {
546
- value: FormulaValue;
547
- error?: string;
548
- regex?: RegexInspection;
549
- }
550
- interface FormulaFunction {
551
- name: string;
552
- signature: string;
553
- description: string;
554
- min: number;
555
- max: number;
556
- result: FormulaType | "branch";
557
- args: FormulaType[] | "any";
558
- }
559
- declare const FORMULA_FUNCTIONS: FormulaFunction[];
560
- declare class FormulaError extends Error {
561
- from: number;
562
- to: number;
563
- constructor(message: string, from?: number, to?: number);
564
- }
565
- declare function compileFormula(source: string, fields: readonly {
566
- name: string;
567
- type: FieldType;
568
- }[], resolve?: (name: string) => FormulaPlan | undefined): FormulaPlan;
569
- /** Self-contained runtime: serialized into the browser worker, never user code. */
570
- declare function formulaRuntime(ast: FormulaNode, inputs: Record<string, FormulaValue>): FormulaResult;
571
-
572
- /** Reserved field token namespace. Query state stores IDs, never formula source. */
573
- declare const COMPUTED_PREFIX = "@computed/";
574
- declare const computedFieldName: (id: string) => string;
575
- declare const isComputedField: (name: string) => boolean;
576
- interface ComputedColumn {
577
- id: string;
578
- label: string;
579
- expression: {
580
- language: "qt-expr";
581
- version: 1;
582
- source: string;
583
- };
584
- /** Optimistic concurrency token issued by the store. */
585
- revision: string;
586
- }
587
- type ComputedColumnDraft = Omit<ComputedColumn, "revision">;
588
- interface ComputedColumnStore {
589
- /** Return the complete authorized catalogue for this dataset. */
590
- list(dataset: string, signal?: AbortSignal): Promise<ComputedColumn[]>;
591
- /** null creates a new ID; updates must match the current revision. */
592
- save(dataset: string, column: ComputedColumnDraft, expectedRevision: string | null): Promise<ComputedColumn>;
593
- /** Optional push invalidation, including changes from other sessions. */
594
- subscribe?(dataset: string, listener: () => void): () => void;
595
- }
596
- declare function validateComputedColumn(input: unknown): ComputedColumn;
597
- declare function memoryComputedColumnStore(seed?: Record<string, ComputedColumn[]>): ComputedColumnStore;
598
- /** REST adapter. The implementing server owns authorization and DB persistence.
599
- * GET base?dataset=… → ComputedColumn[]
600
- * PUT base?dataset=… → {column, expectedRevision} → ComputedColumn
601
- * Return HTTP 409 for a stale revision. No formula evaluation happens there. */
602
- declare function httpComputedColumnStore(base: string, fetcher?: typeof fetch): ComputedColumnStore;
603
- interface ComputedCellError {
604
- computedError: string;
605
- }
606
- declare function isComputedCellError(value: unknown): value is ComputedCellError;
607
- interface PreviewGroup {
608
- inputs: FormulaValue[];
609
- result: FormulaResult;
610
- count: number;
611
- }
612
- interface ColumnPreview {
613
- dependencies: string[];
614
- groups: PreviewGroup[];
615
- processed: number;
616
- total: number;
617
- nulls: number;
618
- errors: number;
619
- }
620
- declare function groupPreview(dependencies: string[], inputs: Record<string, FormulaValue>[], results: FormulaResult[], total: number): ColumnPreview;
621
-
622
883
  /** Compile an explicitly identified editor into existing CNF predicates. */
623
884
  declare function createSetFilter(field: string, mode: SetFilterMode, values: string[], id: string): WhereTerm[];
624
885
  /** Remove presentation metadata at transport boundaries, including inner literals. */
@@ -632,4 +893,23 @@ declare function readSetFilter(where: WhereTerm[], index: number): {
632
893
  /** Canonicalize consumer-owned value aliases without disconnecting editor metadata. */
633
894
  declare function mapSetFilterValues(where: WhereTerm[], canonicalize: (field: string, value: string) => string): WhereTerm[];
634
895
 
635
- export { AGG_OPS_BY_TYPE, AGG_OPS_NEEDING_FIELD, type AggOp, type AggregateConfig, type AggregationBucket, type AggregationClause, type AggregationRequest, type AggregationResult, type AggregationResultEntry, type Align, type ApplyResult, type BackendField, COMPUTED_PREFIX, type CellRenderer, type ColumnPreview, type ComputedCellError, type ComputedColumn, type ComputedColumnDraft, type ComputedColumnStore, type DerivedField, type DistinctValuesQuery, type DistinctValuesResult, EMPTY_QUERY, FORMULA_FUNCTIONS, type FetchRowsResult, type FieldDef, type FieldSchema, type FieldSource, type FieldStats, type FieldType, type FilterConfig, type FilterOp, type FilterValues, type FormulaDiagnostic, FormulaError, type FormulaFunction, type FormulaNode, type FormulaPlan, type FormulaResult, type FormulaType, type FormulaValue, MAX_AGGREGATIONS, MAX_GROUP_BY_FIELDS, MAX_ORDER_BY_TERMS, MAX_QUERY_LIMIT, MAX_QUERY_OFFSET, MAX_QUERY_TOKEN_LENGTH, MAX_SELECT_COLUMNS, MAX_WHERE_CLAUSES, NULLARY_OPS, OPS_BY_TYPE, type OpChoice, type OpPair, type OrGroup, type OrderByClause, type PreviewGroup, type QueryState, type RegexInspection, type RowId, type SavedQuery, type SelectColumn, type SelectConfig, type ServerQuery, type SetFilterMetadata, type SetFilterMode, type SortConfig, type StorageAdapter, type Transport, type WhereClause, type WhereTerm, aggOpAllowedForType, aggOpNeedsField, aggOpsForField, applyAggregations, applyQuery, coerceValue, compileFormula, computedFieldName, createSetFilter, decodeQuery, encodeQuery, filterValues, formulaRuntime, groupPreview, httpComputedColumnStore, indexFields, isComputedCellError, isComputedField, isFilterable, isGroupable, isMeasurable, isNegativePredicate, isOrGroup, isPushdownFilter, isSelectable, isSortable, loadSchema, localStorageAdapter, mapSetFilterValues, matchesClause, memoryComputedColumnStore, memoryStorageAdapter, negateClause, normalizeQueryState, opAllowedForType, opPairsForField, opsForField, predicatesOf, queriesEqual, readFieldValue, readSetFilter, selectedFields, stripSetFilter, toAggregationQuery, toServerQuery, validateComputedColumn };
896
+ declare function percentile(sorted: number[], p: number): number | null;
897
+ declare function boxSummary(values: number[], whiskers?: "minmax" | "tukey"): {
898
+ n: number;
899
+ min: number;
900
+ q1: number;
901
+ median: number;
902
+ q3: number;
903
+ max: number;
904
+ mean: number;
905
+ low: number;
906
+ high: number;
907
+ outliers: number[];
908
+ outlierCount: number;
909
+ whiskers: "minmax" | "tukey";
910
+ method: "exact-linear";
911
+ } | null;
912
+ declare function histogramEdges(values: number[], bins: number): number[];
913
+ declare function histogramCounts(values: number[], edges: number[]): number[];
914
+
915
+ export { AGG_OPS_BY_TYPE, AGG_OPS_NEEDING_FIELD, type AggOp, type AggregateConfig, type AggregationBucket, type AggregationClause, type AggregationRequest, type AggregationResult, type AggregationResultEntry, type Align, type ApplyResult, type BackendField, COMPUTED_PREFIX, type CellRenderer, type ColumnPreview, type ComputedCellError, type ComputedColumn, type ComputedColumnDraft, type ComputedColumnStore, type ComputedExecution, type ComputedFieldCapabilities, type DerivedField, type DistinctValuesQuery, type DistinctValuesResult, EMPTY_QUERY, FORMULA_FUNCTIONS, type FetchRowsResult, type FetchRowsResultV2, type FieldDef, type FieldSchema, type FieldSource, type FieldStats, type FieldType, type FilterConfig, type FilterOp, type FilterValues, type FormulaDiagnostic, FormulaError, type FormulaFunction, type FormulaNode, type FormulaPlan, type FormulaResult, type FormulaType, type FormulaValue, MAX_AGGREGATIONS, MAX_GROUP_BY_FIELDS, MAX_ORDER_BY_TERMS, MAX_QUERY_LIMIT, MAX_QUERY_OFFSET, MAX_QUERY_TOKEN_LENGTH, MAX_RELATIVE_TIME_MS, MAX_SELECT_COLUMNS, MAX_WHERE_CLAUSES, type MetricAxisScale, type MetricBoxSummary, type MetricCapabilities, type MetricDiagnostic, type MetricDisplay, type MetricDistribution, type MetricDistributionResult, type MetricEvaluationOptions, type MetricKey, type MetricLayout, type MetricPlan, type MetricQuery, type MetricReductionOptions, type MetricScope, type MetricSort, type MetricValue, type MetricValueFormat, NULLARY_OPS, OPS_BY_TYPE, type OpChoice, type OpPair, type OrGroup, type OrderByClause, type PreviewGroup, type QueryEvaluationOptions, type QueryState, type RegexInspection, type RowComputedValues, type RowId, type SavedQuery, type SelectColumn, type SelectConfig, type ServerQuery, type ServerQueryV2, type SetFilterMetadata, type SetFilterMode, type SortConfig, type StorageAdapter, type Transport, type WhereClause, type WhereTerm, aggOpAllowedForType, aggOpNeedsField, aggOpsForField, applyAggregations, applyQuery, boxSummary, coerceValue, compareMetricValues, compileFormula, compileMetric, computedFieldName, createSetFilter, decodeQuery, encodeQuery, evaluateMetricReductions, evaluateMetrics, filterValues, formulaRuntime, groupPreview, hasRegex, histogramCounts, histogramEdges, httpComputedColumnStore, indexFields, isComputedCellError, isComputedField, isFilterable, isGroupable, isMeasurable, isNegativePredicate, isOrGroup, isPushdownFilter, isSelectable, isSortable, loadSchema, localStorageAdapter, mapSetFilterValues, matchesClause, memoryComputedColumnStore, memoryStorageAdapter, metricAggregatePlans, metricComputationKey, metricDependencies, metricExpression, metricPlans, negateClause, normalizeQueryState, opAllowedForType, opPairsForField, opsForField, parseRelativeDuration, percentile, predicatesOf, queriesEqual, readFieldValue, readSetFilter, reduceMetricValues, resolveFieldName, selectMetricShownRows, selectedFields, stripSetFilter, toAggregationQuery, toMetricQuery, toServerQuery, toServerQueryV2, validateComputedColumn, validateMetric };