import { FunctionInputError } from "./parser.ts"; export { FunctionInputError }; export type ValidationError = { message: string; pos: number; code: "SYNTAX_ERROR" | "CODEGEN_ERROR"; }; export type ValidationResult = { valid: boolean; errors: ValidationError[]; }; export declare class JsmqlInterpolationError extends Error { readonly slot: number; readonly key?: string; constructor(message: string, slot: number, key?: string); } export type JsmqlOps = Record<`$${string}`, (...args: any[]) => any>; type JsmqlFn = ($: any, ops: JsmqlOps) => unknown; export type JsmqlInput = string | JsmqlFn; type JsmqlCompileFn

= (params: P, $: any, ops: JsmqlOps) => unknown; export type JsmqlOutput = object | object[]; declare function jsmqlDispatch(input: JsmqlInput): JsmqlOutput; declare function jsmqlDispatch(strings: TemplateStringsArray, ...values: unknown[]): JsmqlOutput; /** * `jsmql.expr(input)` — compile a partial / "unfinished" expression in * aggregation-expression form, the shape used inside Pipeline stage bodies * (`$project`, `$addFields`, `$group`, …) and as the second argument to * `db.coll.updateOne(filter, update)` when the update is a update op. * * Differs from `jsmql()` only in the no-`;` bare-expression branch: instead of * Filter dispatch (`{ $expr: ... }` wrap for non-predicates), the expression * lowers directly to its aggregation-expression form. `;`-separated input is * still a Pipeline, update op chains still produce `$set`/`$unset`, and array- * literal Pipelines still pass through — the three other branches are shared * with `jsmql()` via `lowerProgram`. Same three input shapes as `jsmql()`. */ declare function exprDispatch(input: JsmqlInput): JsmqlOutput; declare function exprDispatch(strings: TemplateStringsArray, ...values: unknown[]): JsmqlOutput; /** * `jsmql.filter(input)` — compile to a Filter document only. * * Same three input shapes as `jsmql()` (string / arrow / template tag), but * rejects any input that would lower to a Pipeline. Use this when the call * site is `db.coll.find(filter)` (or `deleteOne` / `countDocuments` / etc.) * and you want a compile-time guarantee that you won't accidentally hand the * driver a stage array. `jsmql()` is the polymorphic counterpart — call it * when the same source string might legitimately produce either shape. * * Pipeline-shaped inputs that throw here: `;`-separated statements, update-op * chains (`$.x = …`, `delete $.x`), top-level stage calls (`$match(...)`), * single-key stage-object literals (`{ $match: ... }`), and array-literal * Pipelines (`[{ $stage: ... }, ...]`). Each error names the shape it found * and suggests the right call (`jsmql.pipeline()`, `jsmql.update()`, * `jsmql()`). */ declare function filterDispatch(input: JsmqlInput): object; declare function filterDispatch(strings: TemplateStringsArray, ...values: unknown[]): object; /** * `jsmql.pipeline(input)` — compile to a Pipeline (stage array) only. * * Same three input shapes as `jsmql()`, but rejects any bare expression that * would lower to a Filter document. Use this when the call site is * `db.coll.aggregate(pipeline)` and you want a compile-time guarantee that * you won't accidentally hand the driver a single document where it expects * a stage array. Accepts every shape that already produces a Pipeline through * `jsmql()`: * * - `;`-separated statements * - a single top-level stage call (`$match(...)`) — auto-wraps to one stage * - a single stage-object literal (`{ $match: ... }`) — auto-wraps too * - update-op chains (`$.x = …`) — compile to `$set` / `$unset` stages * - array-literal Pipelines (`[{ $stage: ... }, ...]`) * * A bare expression like `$.age > 18` throws — the error suggests `jsmql.filter()` * if you wanted a Filter, or wrapping in `$match(...)` to make it a Pipeline. */ declare function pipelineDispatch(input: JsmqlInput): object[]; declare function pipelineDispatch(strings: TemplateStringsArray, ...values: unknown[]): object[]; /** * `jsmql.update(input)` — compile to an aggregation-pipeline update (the * second argument to `db.coll.updateOne(filter, update)` / * `db.coll.updateMany(filter, update)` in its array form, called an * `UpdateFilter` in the Node.js MongoDB driver's typings). * * The shorter public name (`update` rather than `updateFilter`) avoids the * trap where developers read "filter" as the *query* document — the first * argument to `updateOne(filter, update)` — and reach for this when they * meant `jsmql.filter()`. The MongoDB driver type stays `UpdateFilter`; * we just don't repeat the confusing half of its name in the function. * * Output is always a stage array, never the legacy bare-document update form * — that form silently treats RHS expressions as object literals, which is * exactly the kind of footgun this entry point exists to avoid. Passing this * to the driver guarantees that expressions like `$.name.toUpperCase()` * evaluate server-side instead of landing in the document as the literal * object `{ $toUpper: "$name" }`. * * Accepts the same Pipeline-shaped inputs as `jsmql.pipeline()`, but * additionally rejects any stage outside MongoDB's update-pipeline whitelist * (`$addFields`, `$set`, `$project`, `$unset`, `$replaceRoot`, `$replaceWith`). * If you write `$match` or `$sort` inside an update pipeline, MongoDB rejects * it at runtime with a generic error; this entry point catches it at compile * time and names the offending stage. */ declare function updateDispatch(input: JsmqlInput): object[]; declare function updateDispatch(strings: TemplateStringsArray, ...values: unknown[]): object[]; /** * Compile a parameterised arrow function to a reusable MQL builder. * * The arrow's first slot is a destructure pattern naming the bindings: a * `Record` whose keys must be supplied as the params * object at call time. The returned function does no parsing on each * invocation — it walks the cached AST with the bound values substituted in * place of `ParamRef` nodes, emitting an inline MQL literal for each. * * The MQL output shape matches the template-tag form: each binding value * appears as a JSON literal, never wrapped in `$let`. This makes parameter * bindings compose uniformly across expression mode, pipeline mode, and * sub-pipelines (`$lookup`, `$unionWith`, `$facet`), and avoids `$$name` * collisions with lambda parameters. * * The input may also be a **string** containing the arrow source text — e.g. * `jsmql.compile("({ minAge }, $) => $.age > minAge")`. This is useful when * the query is stored externally (config, file, database) and the caller * still wants the parse-once-bind-many semantics. The destructure pattern is * the only parameter-declaration mechanism for both call shapes; placeholder * syntaxes like `${name}` are deliberately not supported (they would break * the strict-JS-subset rule and collide with real template literals). */ declare function compileFunction

>(fn: JsmqlCompileFn

): (params: P) => JsmqlOutput; declare function compileFunction(src: string): (params: Record) => JsmqlOutput; /** * Parse-and-validate any input shape `jsmql()` or `jsmql.compile()` accepts. * Returns a `ValidationResult` with structured errors instead of throwing, * so callers can drive editor tooling, form validation, and similar use cases. * * The overload set is the union of `jsmql.compile`'s and `jsmql()`'s — the * compile-form arrow comes first so IDEs contextually type `({ minAge }, $)` * against `(params: P, $: any, ops: JsmqlOps)` rather than the one-shot * `($: any, ops: JsmqlOps)` shape (which would mis-type the second slot as * `JsmqlOps`). */ declare function validateInput

>(fn: JsmqlCompileFn

): ValidationResult; declare function validateInput(input: JsmqlInput): ValidationResult; declare function validateInput(strings: TemplateStringsArray, ...values: unknown[]): ValidationResult; type Jsmql = typeof jsmqlDispatch & { compile: typeof compileFunction; validate: typeof validateInput; expr: typeof exprDispatch; filter: typeof filterDispatch; pipeline: typeof pipelineDispatch; update: typeof updateDispatch; }; export declare const jsmql: Jsmql; //# sourceMappingURL=index.d.ts.map