/**
 * Restricted workflow expression evaluator (spec: workflow-dataflow-and-triggers-spec.md §A3–A4,
 * plan D6). Used to bind node params to upstream data.
 *
 * HARD SECURITY LINE: NO arbitrary JS eval. This is a tiny recursive-descent interpreter over a
 * fixed grammar — property/index path access + a whitelist of pure functions only. Unattended
 * triggers make eval an injection surface, so arbitrary script is explicitly out of v1.
 *
 * Supported:
 *   - context roots: $input · $json · $node("name") · $now · $vars · $trigger
 *   - accessors: `.prop` and `[index]` / `["key"]`
 *   - literals: string ('..' / ".."), number, true/false/null
 *   - whitelist functions: len, upper, lower, default, jsonpath, date
 *
 * fail-loud: unknown roots/functions, reads through null/undefined, and prototype-escape keys
 * all throw. Absent *leaf* keys evaluate to undefined (so `default(x, fb)` works).
 */
import type { PortMap } from "./data-item.js";
export interface ExpressionContext {
    /** $input — this node's input ports. */
    input?: PortMap;
    /** $json — shorthand for the current item's json (typically input.default[0].json). */
    json?: Record<string, unknown>;
    /** $node("X") — completed upstream node outputs, keyed by node id/name. */
    nodes?: Record<string, {
        output: PortMap;
    }>;
    /** $now — injectable clock for determinism; defaults to real time. */
    now?: () => Date;
    /** $vars — workflow-level variables. */
    vars?: Record<string, unknown>;
    /** $trigger — trigger payload. */
    trigger?: Record<string, unknown>;
}
/**
 * Evaluate a single expression body (the text inside `{{ }}`, braces stripped).
 * Returns the raw value (object/array/number/string/boolean/null/undefined).
 */
export declare function evaluateExpression(body: string, ctx: ExpressionContext): unknown;
/**
 * Static syntax+semantics gate: is `body` a valid expression of THIS language (no evaluation)?
 * Beyond the grammar, it statically enforces what evalNode would reject at run time anyway:
 * known context roots, whitelist function names, and "$node(...) is the only callable".
 * Returns null when valid, else the error message. The n8n expression converter uses this as
 * its single-track output gate — anything it emits must pass here.
 */
export declare function validateExpressionSyntax(body: string): string | null;
/**
 * Resolve a binding template:
 *   - exactly `{{ expr }}` (whole string) → returns the raw evaluated value (keeps type)
 *   - text with embedded `{{ }}` → string interpolation (each sub-expression stringified;
 *     a sub-expression resolving to null/undefined throws — fail-loud)
 *   - no `{{ }}` → returned unchanged
 */
export declare function resolveBinding(template: string, ctx: ExpressionContext): unknown;
/**
 * Recursively resolve every string value in a params object against the context.
 * Non-string leaves are returned untouched. Arrays and nested objects are walked.
 */
export declare function resolveParams(params: Record<string, unknown>, ctx: ExpressionContext): Record<string, unknown>;
