UNPKG

autotel

Version:
105 lines (104 loc) 4.53 kB
import { r as SchemaLike } from "./define-event-CreknLm3.js"; //#region src/validate.d.ts type ValidationMode = 'observe' | 'reject'; type ValidationSeverity = 'info' | 'warning' | 'error'; /** A single failing field, stripped of any payload values. */ interface ValidationIssue { /** Dotted field path, e.g. `items.0.price`. Never a value. */ path: string; /** Issue code (e.g. Zod's `invalid_type`, `too_small`). Never a value. */ code: string; /** Declared type/constraint summary, e.g. `string`. Never a received value. */ expected?: string; } /** Everything the recorder needs — already PII-stripped by the caller. */ interface ValidationMismatch { /** Contract id, e.g. `POST /orders` or `order.placed`. */ name: string; boundary: string; mode: ValidationMode; issues: ValidationIssue[]; hash?: string; severity?: ValidationSeverity; } type MismatchListener = (mismatch: ValidationMismatch) => void; /** * Register an explicit handler called on every recorded mismatch — the opt-in * seam for escalating to security events, a webhook, or a custom sink. There is * no automatic, package-presence-driven escalation: nothing fires here unless * you (or a package you wire up) register a handler. * * Multiple subscribers coexist: a package (e.g. `autotel-audit` bridging to * security events) and your own app code (a webhook, a logger) can both * register and all fire. Returns an unsubscribe fn that removes only this * handler; registering the same function twice is a no-op (Set semantics). */ declare function onValidationMismatch(handler: MismatchListener): () => void; /** * Record a validation mismatch as telemetry: `validation.*` attributes on the * active span (if any) and an increment on `autotel.validation.mismatches`. * Fail-open — never throws, so instrumentation can't break the boundary. */ declare function recordValidationMismatch(mismatch: ValidationMismatch): void; /** * Normalise an arbitrary validation error into PII-safe issues. Reads only * `path`, `code`, and (when it is a declared type name) `expected` — and never * `message`, `received`, or any value-bearing field. Understands the Zod shape * (`error.issues`) and a generic `error.errors` fallback; returns `[]` for * anything unrecognised. */ declare function formatValidationIssues(error: unknown): ValidationIssue[]; interface DefineValidatorOptions<S> { /** Where validation runs. Defaults to `input`. */ boundary?: string; /** `reject` (default): record then throw. `observe`: record then continue. */ onMismatch?: ValidationMode; /** Project the schema to JSON Schema for a stable `validation.hash`. */ toJsonSchema?: (schema: S) => unknown; severity?: ValidationSeverity; /** Build the error thrown in `reject` mode (defaults to a 400 structured error). */ onReject?: (issues: ValidationIssue[], name: string) => Error; } type ValidatorResult<T> = { success: true; data: T; } | { success: false; issues: ValidationIssue[]; }; interface Validator<T> { readonly name: string; readonly mode: ValidationMode; /** Validate and record on failure; never throws. */ safeParse(input: unknown): ValidatorResult<T>; /** * Validate, record on failure, then apply the mode: `reject` throws, * `observe` returns the raw input so the handler can continue. */ parse(input: unknown): T; } /** * Declare an expected input shape once and get a validator that records every * mismatch as telemetry. * * @example * ```ts * import { z } from 'zod'; * import { defineValidator } from 'autotel/validate'; * * const OrderBody = defineValidator('POST /orders', z.object({ * items: z.array(z.object({ sku: z.string(), qty: z.number().int() })), * }), { boundary: 'http', toJsonSchema: (s) => z.toJSONSchema(s) }); * * // reject mode (default): records + throws a 400-shaped structured error * const order = OrderBody.parse(req.body); * * // observe mode: records, returns the result, never throws * const result = OrderBody.safeParse(req.body); * if (!result.success) metrics.onDrift(result.issues); * ``` */ declare function defineValidator<T, S extends SchemaLike<T>>(name: string, schema: S, options?: DefineValidatorOptions<S>): Validator<T>; //#endregion export { DefineValidatorOptions, type SchemaLike, ValidationIssue, ValidationMismatch, ValidationMode, ValidationSeverity, Validator, ValidatorResult, defineValidator, formatValidationIssues, onValidationMismatch, recordValidationMismatch }; //# sourceMappingURL=validate.d.ts.map