first commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user