2.9 KiB
schemas/schemas.ts — Zod options schema
(no submodules)
Purpose
This module owns the runtime validation surface for @suaveplan/emblem-solver.
It exposes ConvertOptionsSchema, a Zod schema that mirrors the static
ConvertOptions interface, applies sensible defaults, and rejects unknown
keys. convert() runs every caller-supplied options object through
safeParse so typos or out-of-range values fail loudly with
EmblemSolverError(INVALID_OPTIONS) rather than silently degrading the
solver.
Features
layerOrderdefaults to"auto"and is validated as a closed enum over the five supported strategies.maxPermutationsdefaults to40320 = 8!— the threshold beyond which exhaustive permutation search is abandoned in favour of heuristics + random sampling. The schema enforcesint().min(1)so a zero or negative value is rejected at the boundary.rngis an optional() => numbervalidated withz.custom<…>(). It is the only injection point for the package — supplying it makes the heuristic + sampling path fully deterministic..strict()rejects unknown keys, so misspelled options never silently succeed.
Usage: Basic
import { ConvertOptionsSchema } from "@suaveplan/emblem-solver/schemas";
const parsed = ConvertOptionsSchema.parse({ layerOrder: "area-desc" });
parsed.maxPermutations; // 40320 (default applied)
Usage: Advanced
import { ConvertOptionsSchema } from "@suaveplan/emblem-solver/schemas";
import { EMBLEM_SOLVER_CODES, EmblemSolverError } from
"@suaveplan/emblem-solver/errors";
function safeOptions(raw: unknown) {
const r = ConvertOptionsSchema.safeParse(raw);
if (!r.success) {
throw new EmblemSolverError(
EMBLEM_SOLVER_CODES.INVALID_OPTIONS,
`bad options: ${r.error.issues
.map((i) => `${i.path.join(".")}: ${i.message}`)
.join("; ")}`
);
}
return r.data;
}
API Reference
| Symbol | Kind | Description |
|---|---|---|
ConvertOptionsSchema |
z.ZodObject |
Strict schema for ConvertOptions |
ConvertOptionsParsed |
type | Post-defaults shape of the parsed result |
Implementation Notes
The schema lives in its own module so the rest of the package does not pay
the Zod cost at import time when consumers do not need validation (e.g.
hot-loop callers that constructed options at startup). convert() always
runs through this schema, but downstream tooling can call
ConvertOptionsSchema.parse ahead of time and pass the parsed result into
its own caching layer. We use z.custom<() => number> rather than
z.function() because Zod 4 deprecated runtime function validation in
favour of a custom predicate; this matches the catalog zod ^4.x. The
rng field stays optional (rather than defaulting to Math.random) so the
test harness can detect whether a caller injected a deterministic source.