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

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-null object (excluding arrays)
  • isOptional(value) — recognizes the { _optional: ... } schema shape
  • isValidSchema(schema) — quick structural check that a value matches one of the published BitPackerSchema shapes

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.
  • isOptional does not validate the wrapped schema. A { _optional: <garbage> } will pass isOptional and fail isValidSchema(value._optional). Splitting these checks lets the caller produce more specific error messages.
  • isValidSchema is structural, not semantic. It confirms the shape but does not check that referenced types in _ref resolve, that _oneOf arrays are non-empty, or that _version._schemas is 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.