API index and search · Build metadata
Source snapshot
packages/client/src/ast.ts
1// The Zero-wire query AST — the exact JSON shape the Rust `Ast` deserializes2// (src/ast.rs). The builder emits these; the wasm `Db.query` (and a remote server) parse3// them. camelCase keys, `type`-tagged unions, ops as SQL-ish strings, untagged literals.45export type Dir = "asc" | "desc";67/** One `(field, direction)` ordering — serializes as the 2-tuple `["id", "asc"]`. */8export type OrderPart = [field: string, dir: Dir];910/** An untagged literal (`null | bool | number | string | array`). Numbers are one f64. */11export type LitValue = null | boolean | number | string | LitValue[];1213/** A column reference or a literal — `type`-tagged. */14export type ValuePosition =15 | { type: "column"; name: string }16 | { type: "literal"; value: LitValue };1718/** The wire comparison operators (exact strings, `src/ast.rs` `Op`). */19export type SimpleOp =20 | "="21 | "!="22 | "<"23 | "<="24 | ">"25 | ">="26 | "IS"27 | "IS NOT"28 | "LIKE"29 | "NOT LIKE"30 | "ILIKE"31 | "NOT ILIKE"32 | "IN"33 | "NOT IN";3435export type ExistsOp = "EXISTS" | "NOT EXISTS";3637/** The filter tree — `type`-tagged; recursive. There is no generic NOT node (negation is38 * via the negated operators and `NOT EXISTS`, matching `src/ast.rs` `Condition`). */39export type Condition =40 | { type: "simple"; op: SimpleOp; left: ValuePosition; right: ValuePosition }41 | { type: "and"; conditions: Condition[] }42 | { type: "or"; conditions: Condition[] }43 | { type: "correlatedSubquery"; related: CorrelatedSubquery; op: ExistsOp; flip?: boolean; scalar?: boolean };4445export interface Correlation {46 parentField: string[];47 childField: string[];48}4950/** A paging lower bound (`Bound`, `src/ast.rs`). `row` is a *partial* wire row — the bound51 * columns by name (only the sort columns are read by the engine's `Skip` comparator).52 * `exclusive` ⇒ start *after* the bound row (`Basis::After`); else *at* it (`Basis::At`). */53export interface Bound {54 row: Record<string, LitValue>;55 exclusive: boolean;56}5758export interface CorrelatedSubquery {59 correlation: Correlation;60 subquery: Ast;61 system?: "client" | "permissions" | "test";62}6364/** An aggregate over a (correlated) subquery's rows (`REDUCE-DESIGN.md`). v1: `count(*)`.65 * Set on a `related` subquery (`Ast.aggregate`), it marks that relationship a count66 * aggregate the builder lowers to a scalar-projected singular relationship (§9). */67export type Aggregate = "count";6869/** The query AST. `table` is the only required field; the builder omits empty/false fields70 * (matching the Rust `skip_serializing_if`), which the deserializer treats as absent. */71export interface Ast {72 table: string;73 alias?: string;74 /** Projection (PROJECTION-SUPPORT-DESIGN.md §6). Absent ⇒ select all columns; present ⇒75 * project to just these (drives what syncs + what the view reports). Serializes only when76 * set, matching the Rust `Ast.select`'s `skip_serializing_if`. */77 select?: string[];78 where?: Condition;79 related?: CorrelatedSubquery[];80 start?: Bound;81 limit?: number;82 one?: boolean;83 /** Aggregate this (sub)query's rows instead of materializing them (`REDUCE-DESIGN.md`84 * §9). `count` on a `related` subquery surfaces a scalar `commentCount` field; the85 * builder lowers it to a scalar-projected singular relationship. Absent ⇒ ordinary rows. */86 aggregate?: Aggregate;87 /** The {@link Ast.aggregate} value is **precomputed** — supplied as rows of a (synthetic)88 * source table rather than reduced from child rows. Set by the normalized client's AST89 * rewrite (`AGGREGATE-SYNC-DESIGN.md` §3.3) so the local engine reads the server's count90 * with a plain singular join + the same projection instead of a `reduce`. Only meaningful91 * with `aggregate`; absent ⇒ `false`. */92 aggregatePrecomputed?: boolean;93 /** Top-level `GROUP BY` columns (names), meaningful only alongside a root {@link Ast.aggregate}94 * (`REDUCE-DESIGN.md` §8). Empty + `aggregate` set ⇒ a **global** aggregate (one `[count]` row);95 * non-empty ⇒ one `[group…, count]` row per distinct value-tuple. Distinct from a relationship96 * aggregate's implicit grouping (the correlation child key). Absent on the wire ⇒ empty. */97 groupBy?: string[];98 /** `HAVING` — a filter over the **post-aggregation** rows of a root {@link Ast.aggregate}99 * (`REDUCE-DESIGN.md` §4: a filter directly above the `reduce`). Its condition addresses the100 * aggregate's *output* columns — the {@link Ast.groupBy} columns and the synthetic `count`101 * column — not base-table columns (those go in {@link Ast.where}, which filters rows *below* the102 * reduce). Absent ⇒ no post-aggregation filter. */103 having?: Condition;104 orderBy?: OrderPart[];105}106