import { V as ValidationError, P as PathSegment } from './errors-BahYESV_.js'; export { B as BUILT_IN_ERROR_CODES, a as BuiltInErrorParams, C as CreateErrorParams, b as CustomErrorParams, E as ErrorParams, c as ErrorParamsFor, S as SELF_LOCATING_ERROR_CODES, d as collectLeaves, e as createBranchError, f as createError, g as createLeafError, j as joinPath, w as walkErrors } from './errors-BahYESV_.js'; export { r as resolveJsonPointer } from './json-pointer-BAmxDd4C.js'; export { C as CallbackObject, n as ComponentsObject, D as DiscriminatorObject, k as ExampleObject, E as ExternalDocumentationObject, g as HeaderObject, H as HttpMethod, l as HttpRequest, m as HttpResponse, I as InfoObject, J as JsonValue, L as LinkObject, M as MediaTypeObject, O as OpenAPIDocument, c as OperationObject, e as ParameterLocation, d as ParameterObject, o as ParameterStyle, P as PathItem, h as ReferenceObject, R as RequestBodyObject, f as ResponseObject, i as SchemaObject, S as SchemaOrBoolean, b as SecurityRequirementObject, j as SecuritySchemeObject, a as ServerObject, T as TagObject } from './types-Dzi0PpYX.js'; /** * Options accepted by the text/flat formatters. * * @public */ interface FormatOptions { /** Maximum depth to render; nodes deeper than this are truncated with `…`. Defaults to Infinity. */ maxDepth?: number; /** String used for each level of indentation in `formatText`. Defaults to `" "`. */ indent?: string; } /** * Render validation errors as an indented human-readable string. * Accepts either a nested error tree (`output: "tree"`) or the flat leaf * list the default validator returns; a flat list renders one line per * leaf. * * @remarks * Every node renders as ` []`. Children are indented * under their parent. The output is meant for terminals and logs, not * programmatic consumption; use {@link toJsonObject} or * {@link formatSummary} for that. * * @param error - Root of the error tree, or a flat list of leaves. * @param options - Optional rendering settings. * @returns A multi-line string ready to print. * * @example * ```ts * const r = validator.validateRequest(httpRequest); * if (!r.valid) console.error(formatText(r.errors)); * ``` * * @public */ declare function formatText(error: ValidationError | readonly ValidationError[], options?: FormatOptions): string; /** * Return a {@link ValidationError} tree as a JSON-safe plain object. * * @remarks * The returned object has the same shape as the input but is freshly * constructed (deep-cloned `children`, `path`, and `params`), so it * round-trips losslessly through `JSON.stringify` / `JSON.parse`. * * Accepts either a single tree root or the flat leaf list the default * (flat-output) validator returns; a list round-trips to a list. * * @param error - Root of the error tree, or a flat list of errors. * @returns The same tree (or list), safe to hand to `JSON.stringify`. * * @example * ```ts * JSON.stringify(toJsonObject(rootError), null, 2); * JSON.stringify(toJsonObject(result.errors), null, 2); // flat output * ``` * * @public */ declare function toJsonObject(error: ValidationError): ValidationError; declare function toJsonObject(error: readonly ValidationError[]): ValidationError[]; /** * Leaf-selection policy for {@link formatSummary}. * * - `"first"`: the first leaf in tree-traversal order. Matches * `express-openapi-validator`'s top-level `message`. The default. * - `"deepest"`: the leaf with the longest path. More informative * on `oneOf` / composition trees where the structural cause sits * one or two levels in. Tiebreak: first encountered. * - `"all"`: every leaf, one per line, each prefixed with its path * and suffixed with its `[code]`. Use this when you want a flat * enumeration of every issue (e.g. eov-style flat error messages, * `grep`-friendly logs, CI diffs). * - `{ byCode }`: priority list of error codes. Returns the first * leaf whose `code` matches the highest-priority entry; if no leaf * matches any listed code, falls back to the `"first"` policy. * * @public */ type FormatSummarySelect = "first" | "deepest" | "all" | { byCode: readonly string[]; }; /** * Options for {@link formatSummary}. * * @public */ interface FormatSummaryOptions { /** How to pick which leaf (or leaves) to summarise. Defaults to `"first"`. */ select?: FormatSummarySelect; /** * Separator between leaves under `select: "all"`. Defaults to `"\n"`. * Set to `", "` for `eov`-style flat output. No effect on single-leaf * modes (`"first"`, `"deepest"`, `{ byCode }`). */ separator?: string; /** * Whether to suffix each leaf with ` []` under `select: "all"`. * Defaults to `true`. Set to `false` for `eov`-style output. No effect * on single-leaf modes (which never include the code). */ includeCode?: boolean; /** * Path-prefix policy. `"always"` (the default) prefixes every leaf * with its dotted path. `"auto"` drops the prefix for leaves whose * code is in {@link SELF_LOCATING_ERROR_CODES}, the HTTP-level codes * whose message already names the failing parameter / body / check, * so `query.persona missing required query parameter "persona"` * renders as `missing required query parameter "persona"`. * Schema-keyword leaves (`type`, `enum`, ...) keep the prefix; their * generic messages need it. Applies to single-leaf modes and to each * line under `select: "all"`. */ path?: "always" | "auto"; } /** * Render validation errors as a one-line string. The workhorse for * HTTP response-body `message` fields, log lines, error-monitoring * titles, and `Error.message`. Accepts either a nested error tree * (`output: "tree"`) or the flat leaf list the default validator * returns. * * Two output shapes depending on {@link FormatSummaryOptions.select}: * * - **Single-leaf modes** (`"first"`, `"deepest"`, `{ byCode }`) pick one * leaf and render it as ` ` (or just `` * when the path is empty). One line. * - **All-leaves mode** (`"all"`) enumerates every leaf, one per leaf, * joined by {@link FormatSummaryOptions.separator} (default `"\n"`), * each rendered as ` []`. The trailing * ` []` is suppressed when {@link FormatSummaryOptions.includeCode} * is `false`. Tune both for `eov`-style flat output. * * In both shapes, {@link FormatSummaryOptions.path} `: "auto"` drops the * dotted-path prefix on leaves whose message already names its location * (the {@link SELF_LOCATING_ERROR_CODES} family), avoiding renderings * like `query.persona missing required query parameter "persona"`. * * For the indented full-tree view, use {@link formatText}; for the raw * JSON-safe object, use {@link toJsonObject}. * * @example * ```ts * formatSummary(rootError); * // "body.users[0].email must match format \"email\"" * * formatSummary(rootError, { select: "deepest" }); * // The leaf with the longest path. Useful on oneOf trees. * * formatSummary(rootError, { select: "all" }); * // Every leaf, one per line: * // body.users[0].email must match format "email" [format] * // body.users[1].age must be >= 0 [minimum] * * formatSummary(rootError, { select: "all", separator: ", ", includeCode: false }); * // eov-shaped flat output. (Path style still differs: eov uses * // slash-separated paths.) * // body.users[0].email must match format "email", body.users[1].age must be >= 0 * * formatSummary(rootError, { select: { byCode: ["content-type", "required"] } }); * // The first content-type leaf if any, else the first required leaf, * // else the first leaf overall. * * formatSummary(missingParamError, { path: "auto" }); * // "missing required query parameter \"persona\"" (no `query.persona` * // prefix; the message locates itself). Value errors keep the prefix: * // "body.users[0].email must match format \"email\"". * ``` * * @public */ declare function formatSummary(error: ValidationError | readonly ValidationError[], options?: FormatSummaryOptions): string; /** * Count the nodes in a {@link ValidationError} tree (branches + leaves). * Accepts a flat list too, in which case it sums the node count of each * root. * * @param error - Root of the error tree, or a flat list of errors. * @returns The total node count. * * @example * ```ts * countErrors(rootError); // 7 * countErrors(result.errors); // flat output: one node per leaf * ``` * * @public */ declare function countErrors(error: ValidationError | readonly ValidationError[]): number; /** * Single source of truth for the CLI's `--format` flag. The * {@link OutputFormat} union and the Commander parser validator both * derive from this tuple; add a new name here and extend * {@link formatError} to wire it up end-to-end. Deprecated aliases * (accepted but not advertised in help text) live in * `DEPRECATED_OUTPUT_FORMATS` instead. * * @public */ declare const KNOWN_OUTPUT_FORMATS: readonly ["text", "json", "summary"]; declare const DEPRECATED_OUTPUT_FORMATS: readonly ["flat"]; /** * Supported built-in output formats. * * `"flat"` is a deprecated alias of `"summary"`, kept for one major. * It named a rendering style (one line per leaf) with the same word * that `ValidatorOptions.output: "flat"` uses for an unrelated result * shape (the errors-list shape vs a tree); `"summary"` pairs the * format name with {@link formatSummary}, the renderer behind it. * * @public */ type OutputFormat = (typeof KNOWN_OUTPUT_FORMATS)[number] | (typeof DEPRECATED_OUTPUT_FORMATS)[number]; /** * Type guard: narrows an arbitrary string to {@link OutputFormat} iff * it appears in {@link KNOWN_OUTPUT_FORMATS} or is a deprecated alias. * * @public */ declare function isOutputFormat(value: string): value is OutputFormat; /** * A programmatic renderer: any function that turns a * {@link ValidationError} tree into a string. * * @public */ type ErrorRenderer = (err: ValidationError) => string; /** * Format a {@link ValidationError} tree as a string in the requested style. * * `renderer` may be one of the built-in format names * ({@link OutputFormat}) or a caller-supplied function, which lets * library consumers plug in SARIF / RFC 7807 / JUnit renderers without * forking the dispatch switch. * * @remarks * Takes a single error tree, unlike {@link formatText}, * {@link formatSummary}, and {@link toJsonObject}, which also accept the * flat `ValidationError[]` the default validator returns. `formatError` * stays tree-only because a custom {@link ErrorRenderer} is typed * `(err: ValidationError) => string`, and widening that would break * existing renderers. For the default flat output, call those helpers * directly, or wrap the list with {@link createBranchError} before passing * it here. * * @param error - The error tree. * @param renderer - A built-in format name or a custom render function. * @param maxDepth - Optional max depth (applies to `"text"` format only). * @returns The rendered string. * * @public */ declare function formatError(error: ValidationError, renderer: OutputFormat | ErrorRenderer, maxDepth?: number): string; /** * A single validation issue flattened for client consumption. Produced * by {@link collectIssues} and embedded in {@link ProblemDetails.issues}. * * Maps 1:1 to a leaf in the {@link ValidationError} tree: you get the * same `code`, `message`, and `params`, plus the path in two forms: * the raw segments array (good for programmatic filtering) and an * RFC 6901 JSON Pointer (good for display and tools that follow the * JSON:API / RFC 9457 conventions). * * @public */ interface ValidationIssue { /** Stable error identifier (e.g. `"type"`, `"required"`, `"content-type"`). */ code: string; /** Raw path segments to the offending data location. */ path: PathSegment[]; /** RFC 6901 JSON Pointer form of `path`, e.g. `"/body/pets/3/name"`. */ pointer: string; /** Human-readable description. */ message: string; /** * Machine-readable details for this issue; shape per-code * documented in {@link BuiltInErrorParams}. Most code-specific * shapes include request-derived fields (e.g. `pattern.actual`, * `additionalProperties.unexpected`) or schema-derived metadata * (e.g. `enum.allowed`, `maximum.maximum`). See the security note * on {@link toProblemDetails} when serving untrusted clients. */ params: Record; } /** * [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457.html) "Problem * Details for HTTP APIs" response envelope with a typed `issues` * array as an extension member. Render as `application/problem+json`. * * @public */ interface ProblemDetails { /** URI reference identifying the problem type. Defaults to `"about:blank"`. */ type: string; /** Short human-readable summary. Defaults to `"Validation failed"`. */ title: string; /** HTTP status code for the response. Defaults to `400`. */ status: number; /** Human-readable explanation specific to this occurrence. */ detail: string; /** Optional URI reference for this occurrence (typically the request URL). */ instance?: string; /** * Flattened validation failures, one per leaf in the underlying * {@link ValidationError} tree. */ issues: ValidationIssue[]; } /** * Options for {@link toProblemDetails}. * * @public */ interface ProblemDetailsOptions { /** URI identifying the problem type. Default: `"about:blank"`. */ type?: string; /** Short title. Default: `"Validation failed"`. */ title?: string; /** HTTP status code. Default: `400`. */ status?: number; /** URI reference identifying this specific occurrence (e.g. the request URL). */ instance?: string; /** * Override the human-readable `detail`. Defaults to * {@link formatSummary}(error): a single line describing the first * failing leaf (e.g. `"body.users[0].email must match format \"email\""`). * The default summary interpolates the offending value for codes * such as `enum`, `format`, and `pattern`; APIs serving untrusted * clients should pass an explicit structural summary * (e.g. `` `${issues.length} validation error(s)` ``) so leaf data * does not appear in `detail`. See the security note on * {@link toProblemDetails} for the corresponding `issues[*].params` * concern. */ detail?: string; } /** * Flatten a {@link ValidationError} tree to a list of leaves annotated * with an RFC 6901 JSON Pointer. Useful when you want a client-friendly * issues array but don't need the {@link ProblemDetails} envelope. * * Leaf-only by design: branch-level `params` (e.g. `oneOf`'s `matchCount`) * are not in the result. Access the raw {@link ValidationError} if you * need the tree. * * @public */ declare function collectIssues(error: ValidationError | readonly ValidationError[]): ValidationIssue[]; /** * Convert a {@link ValidationError} tree to an RFC 9457 "Problem * Details for HTTP APIs" response body. Render as * `application/problem+json` in your HTTP layer. * * **Data exposure.** By design, the rendered response echoes input * values and schema metadata. `detail` defaults to a one-line * summary of the first failing leaf, which interpolates the * offending value for codes such as `enum`, `format`, and `pattern`. * Each `issues[*].params` carries the leaf's machine-readable * detail (see {@link BuiltInErrorParams}), including request-derived * fields (`pattern.actual`, `additionalProperties.unexpected`, * `required.missing`) and schema-derived metadata (`enum.allowed`, * `pattern.pattern`, `maximum.maximum`). This is the right default * for trusted clients and developer-facing APIs. APIs serving * untrusted clients, or APIs validating request bodies that contain * PII, should override `detail` with a structural summary (e.g. * `` `${pd.issues.length} validation error(s)` ``) and may want to * clear `issues[*].params` before sending. See the "Redacting field * values from problem-details responses" recipe in * `docs/integration.md`. * * @example * ```ts * // Express 5 * const result = validator.validateRequest(httpRequest); * if (!result.valid) { * res.status(400) * .type("application/problem+json") * .json(toProblemDetails(result.errors, { instance: req.originalUrl })); * } * ``` * * @public */ declare function toProblemDetails(error: ValidationError | readonly ValidationError[], options?: ProblemDetailsOptions): ProblemDetails; /** * Default mapping from {@link ValidationError} shape to HTTP status * code. Consumers can override any key via the second argument to * {@link httpStatusFor}. * * @public */ interface HttpStatusMap { /** Router couldn't match the request path to any declared route. */ route: number; /** Path matched but the requested method isn't declared on it. */ method: number; /** Request `Content-Type` isn't in the declared `requestBody.content` set. */ "content-type": number; /** Declared security scheme's credential location is missing or malformed. */ security: number; /** Response (response-side only): spec declares no entry for the received status. */ status: number; /** Anything else: schema violations, missing required fields, etc. */ default: number; } /** * Default HTTP status mapping used by {@link httpStatusFor}. * * @public */ declare const DEFAULT_HTTP_STATUS_MAP: HttpStatusMap; /** * Map a {@link ValidationError} to an HTTP status code. * * Handles the tree wrapping that bites consumers who write the * obvious switch: `route` and `method` appear as the top-level leaf * (router short-circuits), but `content-type`, `security`, and * response-side `status` are wrapped inside a top-level * `createBranchError("request", ...)` or `"response"` branch. This * helper inspects the top-level code for the unwrapped cases and * falls back to a leaf scan for the wrapped ones, then resolves to * a status from {@link DEFAULT_HTTP_STATUS_MAP} (or the caller's * overrides). * * Resolution order matches the HTTP gate semantics: 404 → 405 → * 415 → 401 → 500 → 400: * * ```ts * import { httpStatusFor } from "@aahoughton/oav"; * * const result = validator.validateRequest(httpRequest); * if (!result.valid) { * res.status(httpStatusFor(result.errors)).json(toProblemDetails(result.errors)); * } * ``` * * Override any slot, e.g. APIs that use 422 for schema errors: * * ```ts * httpStatusFor(error, { default: 422 }); * ``` * * @public */ declare function httpStatusFor(error: ValidationError | readonly ValidationError[], overrides?: Partial): number; /** * Return the comma-separated value for an `Allow` response header * when the error is a 405 (RFC 9110 §15.5.6 requires it), or * `undefined` otherwise. * * ```ts * const allow = allowHeaderFor(error); * if (allow !== undefined) res.setHeader("Allow", allow); * res.status(httpStatusFor(error)).json(toProblemDetails(error)); * ``` * * @public */ declare function allowHeaderFor(error: ValidationError | readonly ValidationError[]): string | undefined; /** * OpenAPI version detection and dialect identity. * * The OpenAPI Specification has two major variants that affect * validator behavior: * * - **3.0.x**: uses a draft-Wright-00-based JSON Schema dialect with * its own flavours of `type` (single string only), `nullable: true`, * boolean `exclusiveMaximum`/`Minimum`, no sibling keys for `$ref`, * and no `const` / `if`/`then`/`else` / `contains` / * `unevaluatedProperties` / `patternProperties`. * - **3.1.x** and **3.2.x**: use JSON Schema 2020-12. 3.2 is largely * additive over 3.1 (new methods like `QUERY`, tightened rules) and * shares 3.1's dialect. * * This module is intentionally tiny: it classifies a spec into one of * these buckets. Consumers (notably `@oav/validator`) use the bucket * to pick the right vocabulary set at validator construction. * * @packageDocumentation */ /** * The three supported OpenAPI major.minor lines. * * @public */ type OpenAPIVersion = "3.0" | "3.1" | "3.2"; /** * Inspect an OpenAPI document's `openapi` field and bucket it by * major.minor. Returns `undefined` when the field is missing, malformed, * or targets a line we don't recognize. * * @param spec - Anything shaped like an OpenAPI document. Safe on * arbitrary input; returns `undefined` without throwing. * @returns The matched version bucket, or `undefined`. * * @example * ```ts * detectOpenAPIVersion({ openapi: "3.1.0", info: { ... } }); // "3.1" * detectOpenAPIVersion({ openapi: "3.2.0-rc1" }); // "3.2" * detectOpenAPIVersion({ swagger: "2.0" }); // undefined * ``` * * @public */ declare function detectOpenAPIVersion(spec: unknown): OpenAPIVersion | undefined; /** * Why did {@link detectOpenAPIVersion} return `undefined`? Distinguishes * category errors (missing or non-string `openapi` field, wrong major) * from a valid-shaped 3.x spec with an unknown minor (forward-compat). * * @public */ type UnknownVersionReason = { kind: "missing-openapi"; message: string; } | { kind: "wrong-major"; message: string; } | { kind: "ok-unknown-minor"; raw: string; }; /** * Classify a spec's `openapi` field when {@link detectOpenAPIVersion} * returned `undefined`. Shared by `createValidator` (runtime) and * `compile-spec` (AOT) so both emit the same warning / error messages. * * @public */ declare function classifyUnknownVersion(rawOpenapi: unknown): UnknownVersionReason; export { DEFAULT_HTTP_STATUS_MAP, type ErrorRenderer, type FormatOptions, type FormatSummaryOptions, type FormatSummarySelect, type HttpStatusMap, KNOWN_OUTPUT_FORMATS, type OpenAPIVersion, type OutputFormat, PathSegment, type ProblemDetails, type ProblemDetailsOptions, type UnknownVersionReason, ValidationError, type ValidationIssue, allowHeaderFor, classifyUnknownVersion, collectIssues, countErrors, detectOpenAPIVersion, formatError, formatSummary, formatText, httpStatusFor, isOutputFormat, toJsonObject, toProblemDetails };