/** * IR-expression → TypeScript renderer for the Convex functions surface. * * This turns Manifest guard/policy/constraint/action/reaction expressions into * the equivalent TypeScript that runs inside a Convex function. It is a PURE, * deterministic transform. * * DESIGN NOTE — fail CLOSED, never silently fail open. Unlike a permissive * codegen that returns `true` for anything it can't parse (which would make an * unparseable guard silently pass — a security bypass), this renderer records * every node it cannot map in `unresolved`. The caller decides what to do: * governance contexts (guards/policies/constraints) MUST treat a non-empty * `unresolved` as a hard error and emit a denying `throw`, so the gap is loud * at generation time rather than open at runtime. This honours the Manifest * house style ("no permissive defaults; never make an invalid program succeed"). */ import type { IRExpression } from '../../ir'; /** Identifier roots that always render as themselves (not members of `selfVar`). */ export declare const DEFAULT_GLOBALS: readonly string[]; /** How bare identifiers and `self`/`this` resolve. */ export interface RenderScope { /** Variable name that `self.x` / `this.x` / bare `x` resolve against (e.g. "doc"). */ selfVar: string; /** * When true, a bare identifier is treated as a member of `selfVar` * (`status` → `doc.status`). When false, bare identifiers render as * themselves (used for already-bound locals like command params). Default true. */ bareIdentifierIsSelf?: boolean; /** * Identifier roots that render verbatim (e.g. `user`, `context`). A member * access `user.role` thus becomes `user.role`, not `doc.user.role`. Defaults * to {@link DEFAULT_GLOBALS}. */ globals?: readonly string[]; /** Already-bound local names (e.g. command parameters) that render verbatim. */ locals?: readonly string[]; /** * Plan-derived relation locals. A mapped `self.person`, `this.person`, or * bare `person` renders as the separate hydrated local instead of a physical * document property. Chained access naturally continues from that local. */ relationVars?: Readonly>; /** * Convex document identity for `self.id` / `this.id` / bare `id` * (e.g. `_id` after insert, `docId` on updates). Schema has no `id` field — * only Convex `_id` — so without this, emit payloads serialize `undefined`. */ idExpr?: string; /** * Pre-update instance for `previous{Field}` emit fields (e.g. `doc`). * `previousStatus` → `${beforeVar}.status`. Post-update `selfVar` keeps * current fields (`status`, etc.). */ beforeVar?: string; /** * Fallback TypeScript type for lambda callback parameters when no collection * element type is known. Default {@link DEFAULT_LAMBDA_PARAM_TYPE}. */ lambdaParamType?: string; /** * Resolve the element type of a collection expression (e.g. `self.prepTasks` * → `Doc<"prepTasks">`) so `count_of` predicates get a named document type * when IR + table naming make that safe. */ resolveCollectionElementType?: (collection: IRExpression) => string | undefined; } /** Smallest explicit doc-shaped type used when no named Doc<> is available. */ export declare const DEFAULT_LAMBDA_PARAM_TYPE = "Record"; /** Map `previousStatus` → `status` (emit previous-value convention). */ export declare function previousPropertyName(property: string): string | undefined; export interface RenderResult { /** The rendered TypeScript expression. */ code: string; /** Human-readable descriptions of nodes that could not be mapped (empty ⇒ fully resolved). */ unresolved: string[]; } /** True for an IR `null` literal. */ export declare function isNullLiteral(e: IRExpression | undefined): boolean; /** * Render an IR expression to TypeScript. Collects unmappable nodes in * `unresolved` instead of guessing. */ /** Format `(p: T, q: T)` for a generated arrow callback. */ export declare function formatTypedLambdaParams(params: readonly string[], paramType?: string): string; export declare function renderExpression(expr: IRExpression | undefined, scope: RenderScope): RenderResult; //# sourceMappingURL=expression.d.ts.map