2.9 KiB
Capability Spec: Validation
Package: @suaveplan/validation
Version: 0.0.0 (genesis)
Status: ADDED
ADDED Requirements
VL-01 — Self-contained schema engine
@suaveplan/validation is its own schema parser — it does NOT depend on Zod. It exposes a Zod-compatible API surface (parse, safeParse, parseAsync, safeParseAsync, refine, transform, optional, nullable) but is implemented independently.
VL-02 — Never-throw contract
.parse() and .parseAsync() MUST throw ValidationError on failure (never raw errors). .safeParse() and .safeParseAsync() MUST return ParseResult<T> and NEVER throw.
VL-03 — ValidationError shape
ValidationError MUST extend SuaveplanError and carry an issues: ValidationIssue[] array. .flatten() MUST return FlattenedErrors with formErrors (top-level issues) and fieldErrors (keyed by path). .format() MUST return a nested error tree. Error codes under VALIDATION.* namespace.
VL-04 — String schema constraints
StringSchema MUST enforce: min, max, length, regex, email, url, uuid, startsWith, endsWith, includes. Transform helpers trim, toLowerCase, toUpperCase MUST mutate the output value, not fail.
VL-05 — Number schema constraints
NumberSchema MUST enforce: min, max, int, positive, negative, multipleOf, finite.
VL-06 — Object schema modes
ObjectSchema MUST support three unknown-key modes: strip (default, drops unknown keys), strict (fails on unknown keys), passthrough (includes unknown keys). .pick(), .omit(), .partial(), .required(), .extend(), .merge() MUST each return a new ObjectSchema without mutating the original.
VL-07 — Union short-circuit
UnionSchema MUST attempt each arm in order and return the result of the first successful parse. If no arm matches, it MUST return ParseFailure with all arm errors listed as issues.
VL-08 — Async refinements
.refine(fn) MUST accept both synchronous and async predicate functions. Async refinements are only awaited via .parseAsync() / .safeParseAsync().
VL-09 — Coerce utilities
coerce(schema) MUST coerce string inputs to the target type before parsing. coerceString, coerceNumber, coerceBoolean, coerceDate are pure functions; a failed coercion returns ParseFailure rather than throwing.
VL-10 — Hooks
Schemas MUST support optional lifecycle hooks { beforeValidate, afterValidate, onError } settable via a .withHooks(hooks) method. Hooks are called synchronously (or awaited in async paths).
VL-11 — OTel instrumentation
validation.parse.success, validation.parse.failure counters and validation.parse.duration_ms histogram MUST be emitted via @opentelemetry/api. All are no-ops without an exporter.
VL-12 — sideEffects: false + coverage 100%
"sideEffects": false with tree-shake test. Vitest thresholds at 100/100/100/100. No .skip / .only in src/.