Files
skills/docs/foundation/bitpacker/bitpacker-validation/src/validation/validate-data.md
2026-05-29 08:20:56 +01:00

3.8 KiB

validateData

Purpose

The recursive workhorse that drives every validator entry point in @suaveplan/bitpacker-validation. validateData(schema, data, path, options) walks schema and data in lockstep, accumulating ValidationReportItem rows into a passed-in collector array as it descends. Every other validation entry point — validateSchema, BitPackerValidator.validate, validateDataReport — ultimately delegates here.

The function is structured around the schema's discriminated union: the top-level switch/if-ladder dispatches by schema kind (object / array / _optional / _oneOf / _enum / etc.) and recurses into the matching branch. Each branch reports a stable code from ErrorCodes so consumers can switch on the failure mode without pattern-matching the message text.

Features

  • Single recursive entry point for all validators
  • Produces ValidationReportItem rows with stable codes (INVALID_TYPE, OUT_OF_RANGE, MISSING_FIELD, EXTRA_FIELD, ARRAY_TOO_LONG, …)
  • Honours maxErrors to short-circuit on heavily-malformed input
  • Honours checkExtraFields to opt into / out of extra-field detection
  • Composes with findExtraFields and findArrayLengthErrors for the per-rule detail checks
  • Path-aware reporting via dot-separated path field on each row

Usage: Basic Example

import { validateData, type ValidationReportItem } from "@suaveplan/bitpacker-validation";

const errors: ValidationReportItem[] = [];
validateData(
    { x: 255, name: "-32" },
    { x: 100, name: "ok" },
    "",
    { errors, warnings: [], maxErrors: 10, checkExtraFields: true, strictMode: false }
);
console.log(errors); // []

Usage: Advanced Example

import {
    validateData,
    ErrorCodes,
    type ValidationReportItem,
} from "@suaveplan/bitpacker-validation";

function describeViolations(schema: unknown, data: unknown) {
    const errors: ValidationReportItem[] = [];
    const warnings: ValidationReportItem[] = [];
    validateData(schema, data, "$", {
        errors,
        warnings,
        maxErrors: 50,
        checkExtraFields: true,
        strictMode: true,
    });
    return errors
        .filter((row) => row.code === ErrorCodes.OUT_OF_RANGE)
        .map((row) => `${row.path}: ${row.message}`);
}

API Reference

validateData(schema: BitPackerSchema, data: unknown, path: string, ctx: ValidationContext): void

Walks schema and data in lockstep, appending error/warning rows into ctx.errors / ctx.warnings. path is the dot-separated path to the current field ("" at root). ctx carries per-call options and the running accumulators.

The function returns void; results flow through the mutable arrays in ctx. This is hot-path machinery and is structured for minimal allocation per recursion frame.

Implementation Notes

  • Mutable accumulators. The function takes the error/warning arrays by reference and pushes into them. This is the cheapest pattern for hot-path validation — allocating a fresh array per recursion frame would dominate the cost.
  • maxErrors short-circuit. Once ctx.errors.length >= ctx.maxErrors, the function stops accumulating and returns immediately. This caps the cost of validating heavily-malformed input. The data is NOT fully traversed in this case.
  • strictMode promotes warnings. When strictMode === true, the function pushes warnings into ctx.errors instead of ctx.warnings. Downstream consumers see all rows as errors.
  • No throwing. The function never throws — it accumulates. The decision to throw is made by the caller based on throwOnError. This keeps the recursion stack-safe and lets callers decide their failure semantics.
  • Path format. path: "" for root, path: "x" for a top-level field, path: "users.3.email" for nested array element with dot+index notation.