/** * The Postgres type catalog (Phase 0). * * Each Postgres type is described once, as a plain TS object that serves two * masters at the same time: * * - runtime → `oid` + `sqlType`: emit DDL and match columns against the live * database during a diff (Postgres speaks in OIDs, not names). * - compile → `tsType`: a *phantom* field carrying the corresponding TS type * so the shape can infer `number`/`string`/`Date`/... with zero * runtime cost. It is `undefined` at runtime. * * `tsLabel` is the runtime-visible string twin of `tsType` (e.g. "number"), * reserved for future codegen (edge validation / Zod) and debugging. */ /** Runtime-visible label of the TS type a column hydrates to. */ type TsLabel = "string" | "number" | "bigint" | "boolean" | "Date" | "Uint8Array" | "unknown"; /** * A single entry in the Postgres type catalog. * * @typeParam TName - the catalog key and discriminant (e.g. "int4"). * @typeParam TTs - the TS type a value of this column hydrates to. */ interface PgType { /** Catalog key + discriminant. Matches the short Postgres type name. */ readonly name: TName; /** Canonical SQL text emitted in DDL (e.g. "integer", "timestamp with time zone"). */ readonly sqlType: string; /** Stable Postgres OID (from `pg_type`), the robust key for diffing. */ readonly oid: number; /** Runtime-visible twin of `tsType`, for codegen/debug. */ readonly tsLabel: TsLabel; /** * Phantom carrier of the TS type. Always `undefined` at runtime — read it * only at the type level via {@link Infer}. */ readonly tsType: TTs; } /** * Column builder (Phase 1a; `hasDefault` added at the type level in Phase 2c). * * A `Column` wraps a {@link PgType} from the catalog and layers column-level * modifiers on top. It is **immutable**: every modifier returns a *new* column, * so type narrowing is correct and config never leaks between uses. * * Two facts are tracked at the type level: * - **nullability** (`TNotNull`): changes the *read* type (`T` vs `T | null`). * - **hasDefault** (`THasDefault`): changes the *insert* type — a notNull * column with a default becomes optional on insert (the DB fills it). */ /** Runtime description of a column, consumed by the DDL layer. */ interface ColumnConfig { /** Stable field id (UUID) — survives rename. Normally born from `weave gen`; absent for hand-written, id-less fields. */ readonly id?: string; /** The underlying catalog type. For arrays, the *element* type. */ readonly pgType: PgType; /** Whether this is `type[]` rather than a scalar `type`. */ readonly isArray: boolean; /** `NOT NULL` when true. */ readonly notNull: boolean; /** Whether a default was declared. */ readonly hasDefault: boolean; /** The declared default (literal value, or `[]` for arrays). Present iff `hasDefault`. */ readonly default?: unknown; /** Single-column `UNIQUE`. */ readonly unique: boolean; /** Single-column btree index. */ readonly index: boolean; } /** * A column over data type `TData`. * * @typeParam TData - the TS value type (e.g. `string`, `string[]`). * @typeParam TNotNull - `true` once `.notNull()` (or an array default) applies. * @typeParam THasDefault - `true` once a default exists (`.default()` or array). */ declare class Column { readonly config: ColumnConfig; /** Phantom carrier so the compiler can recover the type params. No runtime field. */ readonly _types: { data: TData; notNull: TNotNull; hasDefault: THasDefault; }; constructor(config: ColumnConfig); /** Mark the column `NOT NULL` — narrows the read type from `T | null` to `T`. */ notNull(): Column; /** Mark the column nullable — widens the read type back to `T | null`. */ nullable(): Column; /** Declare a default value — makes the column optional on insert. */ default(value: DefaultArg): Column; /** Add a single-column `UNIQUE`. */ unique(): Column; /** Add a single-column index. */ index(): Column; /** Pin a stable field id (survives rename). Normally emitted by `weave gen`. */ $id(id: string): Column; } /** Arg de `.default()`: o tipo da coluna — mais `number` p/ colunas backed por `bigint` * (int8), pra `int8().default(0)` funcionar como int2/int4 (sem exigir `0n`). */ type DefaultArg = TData extends bigint ? number | bigint : TData; /** The TS type a column reads as, accounting for nullability. */ type InferColumn = C extends Column ? TNotNull extends true ? TData : TData | null : never; type IsColumn$1 = V extends { _types: unknown; } ? true : false; type IsOwned$1 = V extends { kind: "owned"; } ? true : false; type IsRefOne$1 = V extends { _phantom: { cardinality: "one"; }; } ? true : false; type IsRefMany$1 = V extends { _phantom: { cardinality: "many"; }; } ? true : false; type ColumnData = V extends { _types: { data: infer D; }; } ? D : never; type RefTargetShape$1 = V extends { _phantom: { target: Entity; }; } ? TS : never; /** Orçamento de profundidade pra filtros aninhados (guarda contra ciclos). */ type WBudget = [unknown, unknown, unknown, unknown, unknown, unknown]; type WDrop = D extends [unknown, ...infer R] ? R : []; /** Operadores só-de-string, somados quando o tipo do dado é `string`. */ type StringOps

= { like?: string | P; ilike?: string | P; }; /** Operadores de comparação/pertinência pra uma coluna escalar de tipo `T`. */ type ScalarOps = { eq?: T | null | P; ne?: T | null | P; gt?: T | P; gte?: T | P; lt?: T | P; lte?: T | P; in?: T[] | P; notIn?: T[] | P; isNull?: boolean; } & ([T] extends [string] ? StringOps

: {}); /** Filtro de uma coluna escalar: um valor cru (atalho de `eq`) ou um objeto de operadores. */ type Filter = T | P | ScalarOps; /** Operadores pra uma coluna de array escalar (`text[]`, `int4[]`, …). */ type ArrayFilter = { has?: E | P; hasSome?: E[] | P; hasEvery?: E[] | P; isEmpty?: boolean; /** Algum elemento casa estes operadores escalares (o "any …" da GUI). */ some?: ScalarOps; }; /** Filtro de uma coluna — operadores de array pra `type[]`, escalares senão. */ type ColumnFilter = ColumnData extends (infer E)[] ? ArrayFilter : Filter, P>; /** Quantificadores sobre um relacionamento to-many (owned 1:N / reference N:N). */ type Quantifier = { some?: W; every?: W; none?: W; }; type WhereShape = { id?: Filter; createdAt?: Filter; updatedAt?: Filter; and?: WhereShape[]; or?: WhereShape[]; not?: WhereShape; } & (D extends [] ? {} : { [K in keyof TShape as IsColumn$1 extends true ? K : never]?: ColumnFilter; } & { [K in keyof TShape as IsOwned$1 extends true ? K : never]?: TShape[K] extends Owned ? C extends "many" ? Quantifier, P>> : WhereShape, P> : never; } & { [K in keyof TShape as IsRefOne$1 extends true ? K : never]?: WhereShape, WDrop, P>; } & { [K in keyof TShape as IsRefOne$1 extends true ? `${K & string}Id` : never]?: Filter; } & { [K in keyof TShape as IsRefMany$1 extends true ? K : never]?: Quantifier, WDrop, P>>; }); /** * Filtro sobre uma entidade. Operadores escalares (`gt`/`in`/`ilike`/…), de array * (`has`/`hasSome`/…), lógicos `and`/`or`/`not`, e filtro **aninhado** sobre * `owned`/`reference` com quantificadores `some`/`every`/`none`. */ type WhereInput = E extends Entity ? WhereShape : never; /** * Igual ao `WhereInput`, mas cada folha escalar também aceita `{ param: "x" }` — o * filtro de linhas de um SCOPE, resolvido no request-time. Literal e param se misturam * livremente (`{ and: [{ company: { eq: { param: "co" } } }, { active: { eq: true } }] }`). * (Obs.: `not` não é suportado no storage do scope — usar `not` falha no push.) */ type ScopeWhereInput = E extends Entity ? WhereShape : never; /** Orçamento de profundidade pro dot-path (guarda contra ciclos). */ type PBudget = [unknown, unknown, unknown, unknown, unknown]; type PathOf = D extends [] ? never : { [K in keyof TShape & string]: IsColumn$1 extends true ? K : IsOwned$1 extends true ? TShape[K] extends Owned ? K | `${K}.${PathOf> & string}` : K : IsRefOne$1 extends true ? K | `${K}.${PathOf, WDrop> & string}` : IsRefMany$1 extends true ? K | `${K}.${PathOf, WDrop> & string}` : never; }[keyof TShape & string]; /** * Dot-path de campo de uma entity, pra a PROJEÇÃO de um scope (`fields.include/exclude`). * Folha (`"whatsapp"`), path aninhado (`"summaryForTheManager.expectedRoi"`) ou uma * subárvore inteira (`"customer"`). Typo/rename viram erro de compilação. */ type FieldPath = E extends Entity ? PathOf : never; /** * Union dos NOMES de param (`{ param: "x" }`) em qualquer lugar de uma árvore — o where * de um scope. Anda por objetos e arrays; a folha `{ param: L }` rende o literal `L`. * Requer que os literais sejam preservados (o `scopeRule` usa `const` no config). */ type ExtractParams = T extends { param: infer L; } ? L extends string ? L : never : T extends readonly (infer U)[] ? ExtractParams : T extends object ? { [K in keyof T]: ExtractParams; }[keyof T] : never; /** Direção de ordenação. */ type SortDir = "asc" | "desc"; type OrderByShape = { id?: SortDir; createdAt?: SortDir; updatedAt?: SortDir; } & (D extends [] ? {} : { [K in keyof TShape as IsColumn$1 extends true ? K : never]?: SortDir; } & { [K in keyof TShape as TShape[K] extends Owned ? K : never]?: TShape[K] extends Owned ? OrderByShape> : never; } & { [K in keyof TShape as IsRefOne$1 extends true ? K : never]?: OrderByShape, WDrop>; }); /** Ordena pelo `id`, timestamps, colunas escalares, ou um caminho aninhado (owned 1:1 / reference N:1). */ type OrderByInput = E extends Entity ? OrderByShape : never; /** Marcador de op que o compilador do accumulate lê pra montar o upsert. */ type AccumulateOp = { readonly op: "inc"; readonly by: number; } | { readonly op: "max"; readonly value: number; } | { readonly op: "min"; readonly value: number; } | { readonly op: "setOnInsert"; readonly value: unknown; }; /** Incrementa (soma) — contador/soma monotônico. Default `+1`. */ declare const inc: (by?: number) => AccumulateOp; /** Grava só na INSERÇÃO; no conflito preserva o valor existente (ex.: `ts` do bucket). */ declare const setOnInsert: (value: unknown) => AccumulateOp; /** Entrada do `accumulate(key, ops)`: `key` = colunas do `ON CONFLICT` (o unique * declarado); `ops` = `campo → op`. */ interface AccumulateInput { readonly key: Record; readonly ops: Record; } /** Opções comuns a todo acumulador. `where` recorta a métrica → `agg(…) FILTER (WHERE …)`. */ interface AggOpts { readonly where?: Record; } /** Acumulador: marcador que o compilador lê. `count()` não tem campo; o resto tem. */ type Accumulator = { readonly agg: "count"; readonly where?: Record; } | { readonly agg: "sum" | "avg" | "min" | "max" | "distinct"; readonly field: string; readonly where?: Record; } | { readonly agg: "percentile"; readonly field: string; readonly p: number; readonly where?: Record; } | { readonly agg: "histogram"; readonly field: string; readonly bounds: number[]; readonly where?: Record; } | { readonly agg: "first"; readonly field: string; readonly where?: Record; }; declare const count: (opts?: AggOpts) => Accumulator; declare const sum: (field: string, opts?: AggOpts) => Accumulator; declare const avg: (field: string, opts?: AggOpts) => Accumulator; declare function min(field: string, opts?: AggOpts): Accumulator; declare function min(value: number): AccumulateOp; declare function max(field: string, opts?: AggOpts): Accumulator; declare function max(value: number): AccumulateOp; /** Distintos EXATOS (`count(distinct …)`) — tier recente. */ declare const distinct: (field: string, opts?: AggOpts) => Accumulator; /** * One representative value of `field` per group — `(array_agg(field ORDER BY created_at))[1]`. * Deterministic (ordered by the element's `created_at`). Meant for metadata that is constant * within a group (e.g. under `unnest`, the description/weight tied to the group key): `first` * just picks the representative. Not a running-order pick — it's the earliest-created member. */ declare const first: (field: string, opts?: AggOpts) => Accumulator; /** Percentil EXATO (`percentile_cont`) sobre escalar cru. `p` é fração 0..1 (p95 → 0.95). */ declare const percentile: (field: string, p: number, opts?: AggOpts) => Accumulator; /** * Contagem por balde sobre escalar cru (as "barras" de latência). `bounds` * ESTRITAMENTE crescente com N fronteiras → **N+1 baldes**: `< b0`, `[b0,b1)`, …, * `>= b_{N-1}` (o último é o overflow, +∞). Devolve o array de contagens como UM valor. */ declare const histogram: (field: string, bounds: number[], opts?: AggOpts) => Accumulator; /** Expressão de grupo por tempo — trunca `field` em baldes de `interval` (epoch/UTC). */ type GroupExpr = { readonly timeBucket: { readonly field: string; readonly interval: string; }; }; declare const timeBucket: (field: string, interval: string) => GroupExpr; /** * Operando de uma expressão aritmética: **nome de um alias do select** (`"errors"`), * um **número** literal, um **acumulador inline** (`count(...)`), ou outra `Expr`. */ type ExprOperand = string | number | Accumulator | Expr; /** Expressão aritmética sobre agregados (Decisão 5/8). Vale em `orderBy`/`having`. */ interface Expr { readonly op: "div" | "mul" | "add" | "sub"; readonly left: ExprOperand; readonly right: ExprOperand; } /** `a / b` — com `nullif(b,0)` (divisão-por-zero → null) e cast numérico (sem trunc inteiro). */ declare const div: (left: ExprOperand, right: ExprOperand) => Expr; declare const mul: (left: ExprOperand, right: ExprOperand) => Expr; declare const add: (left: ExprOperand, right: ExprOperand) => Expr; declare const sub: (left: ExprOperand, right: ExprOperand) => Expr; /** * Uma faceta: sub-agregação independente que RODA SOB O MESMO `where` do pai. É o * `aggregate` sem `where`/`facets` (herda o do pai) e com `limit` (top-N por faceta — * pressupõe `orderBy`). Alimenta o caso dashboard: vários breakdowns numa passada. */ interface FacetInput> { groupBy?: string[] | Record; select: Record; having?: Record; orderBy?: Record; limit?: number; } /** * Entrada do `aggregate`. `groupBy`: array de campos (chaves homônimas) OU mapa * `alias → campo | expr`. `select`: `alias → acumulador`. `having`: filtro sobre os * ALIASES do select (agregados) → `HAVING`. `orderBy`: por alias do select OU chave * de grupo. `page`/`perPage`: top-N paginado (pressupõe `orderBy`). `facets`: mapa de * sub-agregações independentes (breakdowns) sob o mesmo `where`. `where` é o mesmo * `WhereInput` do find (filtra ANTES de agrupar). */ interface AggregateInput> { where?: WhereInput; /** * Unnest one `owned` list before grouping — the aggregate then runs over the list's * ELEMENTS (like Mongo's `$unwind`), one row per element. A dot-path to the array * (`"managerResult.anchors"`); the `groupBy`/accumulator `field`/FILTER paths then * address the element's fields (`"managerResult.anchors.name"`). `where` still filters * the PARENT rows; the accumulators' `{ where }` filter the elements. Counting parents * under `unnest` needs `distinct("id")` (the parent id repeats per element). */ unnest?: string; groupBy?: string[] | Record; select: Record; having?: Record; orderBy?: Record; page?: number; perPage?: number; facets?: Record>; } /** * Uma linha agregada: chaves de grupo + aliases do select. Tipagem precisa do * valor de cada alias (number para count/sum, tipo da coluna para a chave) é * fast-follow — o esqueleto devolve valores frouxos. */ type AggregateRow = Record; /** * Saída do `aggregate`, auto-ajustada ao input (igual o `expand`): sem `facets` no * input → `AggregateRow[]` puro; COM `facets` → `{ rows, facets: { : linhas } }`. * Assim o call-site que não pede breakdown não paga o embrulho. */ type AggregateOutput = I extends { facets: infer F; } ? { rows: AggregateRow[]; facets: { [K in keyof F]: AggregateRow[]; }; } : AggregateRow[]; /** * Entity declaration + inference. * * `defineEntity` captures the user's shape and, conceptually, owns three managed * system columns every (sub-)entity gets: `id` (uuid PK), `createdAt`, * `updatedAt`. Inference produces three views of a shape: * * - {@link InferRead} — the read object, parameterized by an `expand` map. * `owned` nests automatically; a `reference` surfaces * as `Id` always, plus `` when expanded. * - {@link InferEntity} — `InferRead` with no expand (the default read shape). * - {@link InferInsert} — the write object: notNull-without-default columns are * required, references are set via `Id`. */ /** A record of named fields — columns, owned relationships, and/or references. */ type ShapeRecord = Record | AnyOwned | AnyReference>; /** The managed system columns every (sub-)entity carries. */ interface SystemColumns { id: string; createdAt: Date; updatedAt: Date; } /** Flatten an intersection into a single object literal for readable hovers. */ type Prettify = { [K in keyof T]: T[K]; } & {}; /** * Constraints/índices no nível da ENTIDADE (multi-coluna). Cada grupo é uma lista * de nomes de campo: coluna → sua coluna; reference N:1 → a coluna FK `_id`. * (Owned e reference N:N não entram — não são colunas da tabela raiz.) */ interface EntityOptions { /** Grupos de UNIQUE composto (alvo de `ON CONFLICT` / chave de rollup). */ readonly unique?: string[][]; /** Grupos de índice composto (não-único). */ readonly index?: string[][]; /** * Particiona a tabela por tempo (RANGE nativo). `timeBucket(field, interval)` — o * campo tem que ser um `timestamptz().notNull()`. Torna a tabela **append-only** * (a PK passa a ser `(id, )`). Genérico: qualquer série-temporal de volume. */ readonly partitionBy?: GroupExpr; /** Retenção da partição (ex.: `"30d"`): partições cujo topo já passou são **dropadas**. */ readonly retention?: string; } /** A declared entity: a table name plus its shape (+ constraints de entidade). */ interface Entity { readonly name: TName; readonly columns: TShape; readonly options?: EntityOptions; } type IsColumn = V extends { _types: unknown; } ? true : false; type IsOwned = V extends { kind: "owned"; } ? true : false; type IsReference = V extends { kind: "reference"; } ? true : false; type IsRefOne = IsReference extends true ? (RefCard extends "one" ? true : false) : false; type IsRefMany = IsReference extends true ? (RefCard extends "many" ? true : false) : false; type RefTargetShape = V extends { _phantom: { target: Entity; }; } ? TS : never; type RefNotNull = V extends { _phantom: { notNull: infer NN; }; } ? NN : false; type RefCard = V extends { _phantom: { cardinality: infer C; }; } ? C : "one"; /** Recursion-depth budget for cyclic schemas (caps nested expand types). */ type Budget = [unknown, unknown, unknown, unknown, unknown, unknown]; type Drop = D extends [unknown, ...infer R] ? R : []; /** The sub-expand map for key `K` (or `{}` when absent / `true`). */ type ExpandFor = K extends keyof X ? X[K] extends true ? {} : X[K] : {}; type ReadBody = { [K in keyof TShape as IsColumn extends true ? K : never]: InferColumn; } & { [K in keyof TShape as IsOwned extends true ? K : never]: TShape[K] extends Owned ? C extends "many" ? Prettify>>[] : Prettify>> : never; } & { [K in keyof TShape as IsRefOne extends true ? `${K & string}Id` : never]: RefNotNull extends true ? string : string | null; } & { [K in keyof TShape as IsRefOne extends true ? K extends keyof X ? K : never : never]: RefNotNull extends true ? Prettify, ExpandFor>> : Prettify, ExpandFor>> | null; } & { [K in keyof TShape as IsRefMany extends true ? K extends keyof X ? K : never : never]: Prettify, ExpandFor>>[]; }; type ReadShape = Pick & ReadBody & Pick; /** The read object for an entity, given an `expand` map `X`. */ type InferRead = E extends Entity ? Prettify> : never; /** The default read object (no expand). */ type InferEntity = InferRead; type ExpandShape = D extends [] ? {} : { [K in keyof TShape as IsReference extends true ? K : IsOwned extends true ? K : never]?: IsReference extends true ? true | ExpandShape, Drop> : TShape[K] extends Owned ? ExpandShape> : never; }; /** The shape of the `expand` option for an entity. */ type ExpandInput = E extends Entity ? ExpandShape : never; /** Tipo de ESCRITA de uma coluna: o data-type, mais `number` p/ colunas `bigint` (int8). * Motivo: JSON não carrega `bigint`, então o valor de escrita trafega como `number` * (o SDK coage `bigint→number` antes de serializar). Espelha o `.default()` do int8. */ type WriteData = TData extends bigint ? number | bigint : TData; type InsertField = IsColumn extends true ? V extends Column ? NN extends true ? WriteData : WriteData | null : never : IsOwned extends true ? V extends Owned ? C extends "many" ? InsertOwned[] : InsertOwned : never : never; /** A column is required on insert only if it is `notNull` AND has no default. */ type RequiredColumn = V extends { _types: { notNull: true; hasDefault: false; }; } ? true : false; type InsertBody = Prettify<{ [K in keyof TShape as IsColumn extends true ? RequiredColumn extends true ? K : never : never]: InsertField; } & { [K in keyof TShape as IsColumn extends true ? RequiredColumn extends true ? never : K : never]?: InsertField; } & { [K in keyof TShape as IsOwned extends true ? K : never]?: InsertField; } & { [K in keyof TShape as IsRefOne extends true ? RefNotNull extends true ? `${K & string}Id` : never : never]: string; } & { [K in keyof TShape as IsRefOne extends true ? RefNotNull extends true ? never : `${K & string}Id` : never]?: string | null; } & { [K in keyof TShape as IsRefMany extends true ? `${K & string}Ids` : never]?: string[]; }>; type InsertOwned = Prettify<{ id?: string; } & InsertBody>; /** The object accepted by `save`: optional id (upsert), body, no managed timestamps. */ type InferInsert = E extends Entity ? Prettify<{ id?: string; } & InsertBody> : never; type SelectShape = { id?: true; createdAt?: true; updatedAt?: true; } & { [K in keyof TShape as IsColumn extends true ? K : never]?: true; } & { [K in keyof TShape as IsRefOne extends true ? `${K & string}Id` : never]?: true; } & (D extends [] ? {} : { [K in keyof TShape as IsOwned extends true ? K : never]?: true | (TShape[K] extends Owned ? SelectShape> : never); } & { [K in keyof TShape as IsRefOne extends true ? K : IsRefMany extends true ? K : never]?: true | SelectShape, Drop>; }); /** The shape of the `select` option for an entity. */ type SelectInput = E extends Entity ? SelectShape : never; /** Full read of a sub-shape (all fields, references as ids) — used by `true`. */ type FullRead = Prettify>; type SelectSub = Sel extends true ? FullRead : SelectResultShape; type SelectFieldType = K extends "id" ? string : K extends "createdAt" | "updatedAt" ? Date : K extends keyof TShape ? IsColumn extends true ? InferColumn : TShape[K] extends Owned ? C extends "many" ? SelectSub[] : SelectSub : IsRefOne extends true ? RefNotNull extends true ? SelectSub, Sel> : SelectSub, Sel> | null : IsRefMany extends true ? SelectSub, Sel>[] : never : K extends `${infer F}Id` ? F extends keyof TShape ? IsRefOne extends true ? RefNotNull extends true ? string : string | null : never : never : never; type SelectResultShape = Prettify<{ id: string; } & { -readonly [K in keyof S]: SelectFieldType; }>; /** The pruned read object for an entity, given a `select` map `S`. */ type InferSelect = E extends Entity ? SelectResultShape : never; /** Declare an entity (a first-class table). */ declare function defineEntity(name: TName, columns: TShape, options?: EntityOptions): Entity; /** * `reference` relationship — association (Phases 3 & 4). * * The target is an **independent** entity (its own table), possibly shared by * many. This side only **points and reads**: it never writes the target table. * * - `reference(city)` → N:1. FK column `city_id` (no cascade). * Reads `cityId` always, `city` on expand. * - `reference(array(city))` → N:N. A join table (`user_cities`), composite * PK, both FKs cascade the *link*. Reads nothing * by default; `cities: City[]` on expand. Writes * via `citiesIds: string[]` (replaces the set). */ type ReferenceCardinality = "one" | "many"; type AnyEntity = Entity; /** * Marcador de auto-referência: `reference(self())` / `reference(array(self()))`. * NÃO carrega a entity por valor — o alvo é resolvido pro nome da PRÓPRIA entity no * `toIR`. Isso destrava o self-ref sem o muro de inferência de `const` (o thunk * `() => users` referenciaria `users` no próprio initializer; o `self()` não). */ declare class SelfMarker { readonly kind: "self"; } /** Alvo de uma reference em runtime: entity eager, thunk lazy (ciclo/self), ou `self()`. */ type RefTargetRaw = AnyEntity | (() => AnyEntity) | SelfMarker; declare class Reference = Entity, TCard extends ReferenceCardinality = "one", TNotNull extends boolean = false> { /** * Alvo. TIPADO como entity (os consumidores do engine leem `.target.name/.columns` * pós-`fromIR`, onde é sempre entity real). Em RUNTIME, no caminho de definição do * client, pode carregar thunk/`self()` cru — resolvido só no `toIR`/revive. Nunca * chega ao engine cru (vira nome no IR). */ readonly target: TTarget; readonly cardinality: TCard; readonly isNotNull: boolean; /** Stable field id (UUID) — survives rename. Normally emitted by `weave gen`. */ readonly id?: string | undefined; readonly kind: "reference"; /** Phantom carrier so the compiler can recover target/cardinality/nullability. */ readonly _phantom: { target: TTarget; cardinality: TCard; notNull: TNotNull; }; constructor( /** * Alvo. TIPADO como entity (os consumidores do engine leem `.target.name/.columns` * pós-`fromIR`, onde é sempre entity real). Em RUNTIME, no caminho de definição do * client, pode carregar thunk/`self()` cru — resolvido só no `toIR`/revive. Nunca * chega ao engine cru (vira nome no IR). */ target: TTarget, cardinality: TCard, isNotNull: boolean, /** Stable field id (UUID) — survives rename. Normally emitted by `weave gen`. */ id?: string | undefined); /** Nome da entity-alvo, resolvendo thunk/self (`selfName` = nome de quem contém). */ targetName(selfName: string): string; /** Make the FK `NOT NULL` (only meaningful for N:1). */ notNull(): Reference; /** Pin a stable field id (survives rename). Normally emitted by `weave gen`. */ $id(id: string): Reference; } /** A reference of any target/cardinality/nullability. */ type AnyReference = Reference, ReferenceCardinality, boolean>; /** Marker produced by `array(entity)` / `array(() => entity)` / `array(self())` — N:N. */ declare class ReferenceArray> { readonly target: RefTargetRaw; readonly kind: "reference_array"; constructor(target: RefTargetRaw); } /** `self()` — alvo = a própria entity. Para self-ref (`reference(self())` ou N:N). */ declare function self(): SelfMarker; /** Declare an N:1 reference to an independent entity (nullable by default). */ declare function reference>(target: T): Reference; /** * N:1 lazy (thunk) — para ciclo mútuo entre entities: `reference(() => users)`. * Alvo FROUXO de propósito: capturar `typeof users` no phantom criaria um ciclo de * inferência de `const` (typeof company ↔ typeof users) que colapsa o TShape inteiro. * O `expand` desse campo vem frouxo (o FK id e as colunas irmãs continuam precisos). * Refs ACÍCLICOS usam o overload eager (`reference(x)`), que mantém o expand tipado. */ declare function reference(thunk: () => Entity): Reference, "one", false>; /** N:1 self-ref: `reference(self())`. Alvo frouxo (a própria entity). */ declare function reference(marker: SelfMarker): Reference, "one", false>; /** Declare an N:N reference (from `array(entity)` / `array(() => entity)` / `array(self())`). */ declare function reference>(set: ReferenceArray): Reference; /** * `owned` relationship — composition (Phase 2). * * An owned sub-shape is stored in a **dedicated child table**, prefixed by the * ownership path, with an FK to the immediate parent and `ON DELETE CASCADE`. * It can nest recursively (owned within owned). Cardinality: * * - `owned({...})` → 1:1, one child row. * - `owned(array({...}))` → 1:N, many child rows. * * Owned sub-entities get their own `id`/`createdAt`/`updatedAt`, like any table. */ type OwnedCardinality = "one" | "many"; /** A sub-shape: columns, further owned relationships, and/or references. */ type OwnedShape = Record | AnyOwned | AnyReference>; /** Options for an owned relationship. */ interface OwnedOptions { /** Override the generated child-table name (escape valve for deep nesting). */ table?: string; } /** An owned relationship node in a shape. */ declare class Owned { readonly shape: TShape; readonly cardinality: TCard; readonly options: OwnedOptions; /** Stable field id (UUID) — survives rename. Normally emitted by `weave gen`. */ readonly id?: string | undefined; /** Mirror target entity name — the base whose shape is copied in (snapshot). */ readonly mirrorName?: string | undefined; readonly kind: "owned"; constructor(shape: TShape, cardinality: TCard, options: OwnedOptions, /** Stable field id (UUID) — survives rename. Normally emitted by `weave gen`. */ id?: string | undefined, /** Mirror target entity name — the base whose shape is copied in (snapshot). */ mirrorName?: string | undefined); /** Pin a stable field id (survives rename). Normally emitted by `weave gen`. */ $id(id: string): Owned; } /** An owned relationship of any shape/cardinality. */ type AnyOwned = Owned; /** Marker produced by `array({...})` to signal a 1:N owned set. */ declare class OwnedArray { readonly shape: TShape; /** Mirror target name when built from `array(mirror(...))`. */ readonly mirrorName?: string | undefined; readonly kind: "owned_array"; constructor(shape: TShape, /** Mirror target name when built from `array(mirror(...))`. */ mirrorName?: string | undefined); } /** * Snapshot of another entity's shape into an owned child — a **mirror**. The base's * fields are copied in (materialized server-side), plus any local extras. Takes the * ENTITY (like `reference`), not its name. `TShape` is the type-level merged shape * (base ⋂ extras); at runtime it carries only the extras + the base's name. */ declare class Mirror { readonly mirrorName: string; /** Local extra fields (the base is resolved server-side). */ readonly extra: OwnedShape; readonly kind: "mirror"; constructor(mirrorName: string, /** Local extra fields (the base is resolved server-side). */ extra: OwnedShape); } /** Mirror an entity's shape into an owned child, optionally adding local fields. */ declare function mirror(entity: Entity, extra?: TExtra): Mirror; /** Declare an owned 1:1 relationship. */ declare function owned(shape: TShape, options?: OwnedOptions): Owned; /** Declare an owned 1:1 mirror (`owned(mirror(base, { extras }))`). */ declare function owned(m: Mirror, options?: OwnedOptions): Owned; /** Declare an owned 1:N relationship (from `array({...})` or `array(mirror(...))`). */ declare function owned(set: OwnedArray, options?: OwnedOptions): Owned; /** Função de transporte: recebe um `Request`, devolve um `Response` (WHATWG fetch). * Aceita retorno síncrono ou Promise (o `app.hono.fetch` pode ser síncrono). */ type FetchLike = (request: Request) => Response | Promise; interface ClientOptions { /** Base URL do Weave (ex.: `https://weave.minha-loja.com`). */ url: string; /** API key (`x-api-key`). */ key: string; /** O entities-as-code: `{ nome: defineEntity(...) }`. */ entities: S; /** Transporte. Default: `globalThis.fetch`. Nos testes: `app.hono.fetch`. */ fetch?: FetchLike; /** @internal — scope ativo (`x-weave-scope`), definido via `weave.as(...)`. */ scope?: string; /** @internal — params do scope (`x-weave-params`). */ params?: Record; } /** * Modificadores de leitura, **tipados pela entidade**: `orderBy` (`OrderByInput`), * `expand` (`ExpandInput`, dirige o tipo → `InferRead`) e `select` (`SelectInput`, * whitelist de leitura ENXUTA — dirige o tipo → `InferSelect`). O `where` NÃO vem * aqui — é o 1º argumento cru do método. */ interface ReadOpts, X, S> { orderBy?: OrderByInput; expand?: X & ExpandInput; /** * `select` — whitelist de leitura enxuta (subsume o `expand`): só hidrata o nomeado, * `id` sempre (timestamps se selecionados). Aninhado (espelha a árvore): `true` = * subárvore inteira, `{ … }` = parcial, omitido = pula. Pro caso de LISTA de entity * profunda (não puxa os owned que a tela não mostra). Ausente = leitura cheia de sempre * (owned + auto-expand). A forma é validada pela constraint `S extends SelectInput` * nos métodos — `select?: S` puro aqui pra o `S` inferir EXATAMENTE o argumento (a * intersecção `S & SelectInput` vazava o SelectInput pro S e alargava o InferSelect). */ select?: S; /** * Greatest-n-per-group: uma linha por combinação destes campos (`DISTINCT ON`). * O `orderBy` decide qual sobrevive (ex.: `{ ts: "desc" }` → a mais recente). * É o widget de métricas vivas ("o doc mais recente por worker/container"). */ latestPer?: (keyof E["columns"] & string)[]; /** * Máximo de linhas do `findMany`. Default **10 000** ({@link DEFAULT_LIMIT}) — a rede de * segurança pra você não puxar uma tabela inteira sem querer. Suba pra ler mais de uma * vez, ou baixe pra um teto menor; pra UI paginada / listas realmente grandes, use * `paginate`. Se o filtro casar MAIS linhas que o limite, o `findMany` **avisa** (o corte * nunca é mudo). Passar `limit` explícito cala o aviso — aí o teto é escolha sua. * (Ignorado por `findOne`, que é sempre 1; no `paginate`, quem manda é o `perPage`.) */ limit?: number; } interface PageOpts, X, S> extends ReadOpts { page?: number; perPage?: number; } /** Tipo do doc lido: `InferSelect` quando há `select` (whitelist), senão `InferRead` (expand). */ type ReadResult = [S] extends [never] ? InferRead : InferSelect; interface PageResult { docs: T[]; docsQuantity: number; pageQuantity: number; currentPage: number; } /** * Client tipado de UMA entidade. Uma linha se mira por **`where` cru** (1º arg) — * `{ id: "123" }` é açúcar pra `{ id: { eq: "123" } }`. Verbos com `One` pegam o * **primeiro match** (`orderBy` desempata); com `Many` operam em massa e devolvem * `{ count }`. Os reads se **auto-tipam pelo `expand`** (`const X` → `InferRead`). */ interface EntityClient> { create(input: InferInsert): Promise>; /** Cria em lote (ingest — uma transação). Devolve as linhas na ordem de entrada. */ createMany(inputs: InferInsert[]): Promise[]>; findOne = never>(where?: WhereInput, opts?: ReadOpts): Promise | null>; findMany = never>(where?: WhereInput, opts?: ReadOpts): Promise[]>; paginate = never>(where?: WhereInput, opts?: PageOpts): Promise>>; updateOne(where: WhereInput, patch: Partial>, opts?: { orderBy?: OrderByInput; }): Promise | null>; updateMany(where: WhereInput, patch: Partial>): Promise<{ count: number; }>; deleteOne(where: WhereInput, opts?: { orderBy?: OrderByInput; }): Promise | null>; deleteMany(where: WhereInput): Promise<{ count: number; }>; /** * Agrega (groupBy + acumuladores + having + orderBy). Sem `facets` no input, * devolve `AggregateRow[]`; COM `facets`, devolve `{ rows, facets }` — o tipo de * retorno se auto-ajusta ao input (igual o `expand`). */ aggregate>(input: I): Promise>; /** * Acumula no tier histórico: um upsert mergeável na `key` (o unique declarado da * entidade), aplicando `ops` (`inc`/`max`/`min`/`setOnInsert`) atomicamente no * Postgres. Devolve a linha resultante (inc-and-return). A média se deriva na * LEITURA (`sum/count`) — nunca se guarda média pronta. */ accumulate(key: Partial>, ops: Record): Promise>; } /** O client completo: uma propriedade por entidade do entities + `as` (scope). */ type WeaveClient>> = { [K in keyof S]: EntityClient; } & { /** * Client escopado: toda requisição leva `x-weave-scope` + `x-weave-params`. Aceita o * OBJETO do scope (`defineScope(...)`) — recomendado — ou o nome (string). Quando o * scope infere params (`{ param: "x" }` no where), o objeto de params vira OBRIGATÓRIO * e tipado (`.as(admin, { companyId })`); sem params, é opcional. */ as

(scope: ScopeDef

| string, ...rest: [P] extends [never] ? [params?: Record] : [params: { [K in P]: unknown; }]): WeaveClient; /** * Factory reset — **dev/test only**. Zera o banco pra estado virgem (apaga dados, * tabelas de entity e o schema todo); um `push` em seguida reconstrói. Só funciona * se o servidor tiver `WEAVE_DEV_MODE` setada — senão responde 403 e não faz nada. */ reset(): Promise; }; /** * Cria o client tipado a partir do entities-as-code. Casca fina sobre a API HTTP do * Weave: monta o request, manda o `x-api-key`, revive `obj↔json` (datas) pela forma * da entidade, e serializa o `expand` no param. O `fetch` é injetável — em teste, * `app.hono.fetch`. */ declare function createClient>>(options: ClientOptions): WeaveClient; type Verb = "read" | "create" | "update" | "delete"; /** Config de uma regra (sem a entity — ela vem por referência no `scopeRule`), TIPADA * contra a entity `E`: `where` é um `WhereInput` param-aware, `fields` são dot-paths * de `E`. Typo/rename num campo/path viram erro de compilação, nunca falha silenciosa. */ interface ScopeRuleConfig = Entity> { verbs: readonly Verb[]; /** Filtro de linhas: `WhereInput` onde qualquer folha aceita `{ param: "x" }`. */ where?: ScopeWhereInput; /** Projeção: dot-paths de `E` (`"whatsapp"`, `"summaryForTheManager.expectedRoi"`). */ fields?: { include?: FieldPath[]; exclude?: FieldPath[]; }; } /** Uma regra já resolvida (type-erased): o nome LÓGICO da entity (`entity.name`) + a * config frouxa. `Params` é um phantom com os nomes de param inferidos do `where`. */ interface ScopeRule { entity: string; verbs: Verb[]; where?: Record; fields?: { include?: string[]; exclude?: string[]; }; /** @internal phantom — nomes de param (`{ param: "x" }`) inferidos do `where`. */ readonly __params?: Params; } /** Nomes de param no `where` de uma config (vazio quando não há `where`). */ type WhereParams = C extends { where: infer W; } ? ExtractParams : never; interface ScopeEntityRule { verbs: Verb[]; where?: Record; fields?: { include?: string[]; exclude?: string[]; }; } /** `Params` = union dos nomes de param inferidos das regras — o `weave.as` tipa contra isso. */ interface ScopeDef { name: string; entities: Record; /** @internal phantom — carrega os nomes de param pro `weave.as`. */ readonly __params?: Params; } /** * Amarra uma regra a uma ENTITY por referência. O binding sai de `entity.name` (o nome * LÓGICO canônico — camelCase como você escreveu no `defineEntity`), não de uma string — * então typo/casing/snake_case não existem aqui. Espelha o `reference(entity)`. O `const` * na config preserva os literais dos `{ param: "x" }` pra inferência (Pedido 2d). */ declare function scopeRule, const C>(entity: E, config: C & ScopeRuleConfig): ScopeRule>; /** Union dos params de todas as regras de um scope. */ type RulesParams = NonNullable; /** * Helper pro scope-as-code (igual `defineEntity`): nome + regras amarradas por `scopeRule`. * Devolve `ScopeDef` com os nomes de param INFERIDOS das regras — o `weave.as` * usa isso pra tipar (e exigir) o objeto de params na chamada, sem você declarar nada. */ declare function defineScope(name: string, rules: R): ScopeDef>; interface PushScopesOptions { url: string; key: string; fetch?: FetchLike; } /** * Empurra scopes-as-code: converte cada regra (where + fields por NOME) pro formato * por-id e grava via `PUT /admin/scopes/:name`. Busca os IRs das entidades pra * resolver os ids (rename-proof no storage). */ declare function pushScopes(scopes: Record>, options: PushScopesOptions): Promise<{ pushed: string[]; }>; export { percentile as $, type AccumulateInput as A, count as B, Column as C, createClient as D, type Entity as E, type FetchLike as F, type GroupExpr as G, defineEntity as H, type InferEntity as I, defineScope as J, distinct as K, div as L, Mirror as M, first as N, type OwnedShape as O, type PageOpts as P, histogram as Q, ReferenceArray as R, type ShapeRecord as S, inc as T, max as U, type Verb as V, type WeaveClient as W, min as X, mirror as Y, mul as Z, owned as _, type ScopeDef as a, pushScopes as a0, reference as a1, scopeRule as a2, self as a3, setOnInsert as a4, sub as a5, sum as a6, timeBucket as a7, SelfMarker as b, OwnedArray as c, type ClientOptions as d, type OrderByInput as e, type InferInsert as f, type WhereInput as g, type AccumulateOp as h, type Accumulator as i, type AggOpts as j, type AggregateInput as k, type AggregateOutput as l, type AggregateRow as m, type EntityClient as n, type Expr as o, type ExprOperand as p, type FacetInput as q, type InferRead as r, type PageResult as s, type PushScopesOptions as t, type ReadOpts as u, type ScopeEntityRule as v, type ScopeRule as w, type ScopeRuleConfig as x, add as y, avg as z };