Initial Commit
This commit is contained in:
79
packages/media/image/emblem-solver/src/schemas/schemas.md
Normal file
79
packages/media/image/emblem-solver/src/schemas/schemas.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# `schemas/schemas.ts` — Zod options schema
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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
|
||||
|
||||
- `layerOrder` defaults to `"auto"` and is validated as a closed enum over
|
||||
the five supported strategies.
|
||||
- `maxPermutations` defaults to `40320 = 8!` — the threshold beyond which
|
||||
exhaustive permutation search is abandoned in favour of heuristics +
|
||||
random sampling. The schema enforces `int().min(1)` so a zero or negative
|
||||
value is rejected at the boundary.
|
||||
- `rng` is an optional `() => number` validated with `z.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
|
||||
|
||||
```ts
|
||||
import { ConvertOptionsSchema } from "@suaveplan/emblem-solver/schemas";
|
||||
|
||||
const parsed = ConvertOptionsSchema.parse({ layerOrder: "area-desc" });
|
||||
parsed.maxPermutations; // 40320 (default applied)
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user