3.7 KiB
Validation Utilities
(no submodules)
Purpose
Type guards and shape-checks shared across the @suaveplan/bitpacker-validation validators. These are the cheap, common predicates — "is this an object?", "is this an optional schema?", "is this a valid schema-shaped value?" — that every per-rule validator hits in its hot path. Centralizing them keeps the per-rule logic free of duplicated typeof ladders and ensures the predicates evolve in lockstep when new schema shapes ship.
The functions are pure and side-effect-free; they don't throw, they don't allocate, and they don't recurse. Schema-driven recursion is the caller's responsibility — these helpers answer one question at one level of the structure.
Features
isObject(value)— guards a non-nullobject(excluding arrays)isOptional(value)— recognizes the{ _optional: ... }schema shapeisValidSchema(schema)— quick structural check that a value matches one of the publishedBitPackerSchemashapes
Usage: Basic Example
import { isObject, isOptional } from "@suaveplan/bitpacker-validation";
if (isObject(value) && !isOptional(value)) {
// …treat value as a regular object schema or data record…
}
Usage: Advanced Example
import {
isObject,
isOptional,
isValidSchema,
} from "@suaveplan/bitpacker-validation";
function validateField(schema: unknown, data: unknown, path: string) {
if (!isValidSchema(schema)) {
throw new Error(`Schema at ${path} is malformed`);
}
if (isOptional(schema) && data === undefined) {
return; // missing optional field is fine
}
if (isObject(schema) && isObject(data)) {
// recurse into the nested object
for (const key of Object.keys(schema as Record<string, unknown>)) {
validateField(
(schema as Record<string, unknown>)[key],
(data as Record<string, unknown>)[key],
`${path}.${key}`
);
}
}
}
API Reference
isObject(value: unknown): value is object
Returns true if value is a non-null object that is not an Array. Used everywhere a per-key descent into a schema or data record is appropriate.
isOptional(value: unknown): boolean
Returns true if value is a non-null object with an _optional key. The function does NOT recursively validate the wrapped schema — that's the caller's job.
isValidSchema(schema: unknown): boolean
Returns true if schema matches one of the published BitPackerSchema shapes (number, string, boolean, null, bigint token, array, object, or one of the discriminated wrappers _enum/_optional/_oneOf/_if/_version/_ref/_bp/_customType). Returns false for malformed values like functions, symbols, or unrecognized shapes.
Implementation Notes
- No recursion. Each helper answers one question about one level. Nested validation is the caller's responsibility; making the helpers recursive would couple them to the validator's traversal strategy.
isOptionaldoes not validate the wrapped schema. A{ _optional: <garbage> }will passisOptionaland failisValidSchema(value._optional). Splitting these checks lets the caller produce more specific error messages.isValidSchemais structural, not semantic. It confirms the shape but does not check that referenced types in_refresolve, that_oneOfarrays are non-empty, or that_version._schemasis well-ordered. Semantic validation belongs to the validator class.- Performance. All three helpers are
O(1)in the size of the input. They are safe to call from inside hot-path loops without measurable overhead.