first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
# 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
```ts
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
```ts
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.