first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
# control-surface-schema (Zod)
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module owns the Zod schemas that mirror every TypeScript type in the
package: `TransformSchema`, `BindingSchema`, `RangeSchema`,
`AppearanceSchema`, `BehaviourSchema`, `GroupLayoutSchema`,
`ControlNodeSchema`, `ControlSurfaceSchema`, and the loose
`ControlSurfaceVersionedSchema` used inside the upgrade pipeline. The
schemas are the runtime source of truth for `validateSurface` and
`upgradeSurface`.
## Features
- One schema per exported type — symmetrical with the type module.
- Discriminated unions on `kind` (`Binding`, `GroupLayout`, `Action`)
and on `type` (`ControlNode`), so parse errors point at the precise
variant that failed.
- Recursive `ControlNodeSchema` via `z.lazy` so groups can nest to any
depth without exploding the schema graph.
- MIDI / DMX numeric ranges encoded with `.int().min().max()` matching
the hardware envelope; the validator rejects out-of-range channel and
CC values at parse time.
- Compound bindings use `LeafBindingSchema` (no nested compound) to
enforce the flat-only invariant declaratively.
- `ControlSurfaceSchema` pins `version` to `CURRENT_SCHEMA_VERSION` so a
document at a different version fails parse; `ControlSurfaceVersionedSchema`
loosens this to any non-empty string for use inside migrations.
## Usage: Basic Example
Parse an unknown document via `safeParse`:
```ts
import { ControlSurfaceSchema } from "@suaveplan/control-surface-schema";
const result = ControlSurfaceSchema.safeParse(raw);
if (!result.success) {
for (const issue of result.error.issues) {
console.error(issue.path.join("."), issue.message);
}
}
```
## Usage: Advanced Example
Compose a sub-schema for an editor that only wants to validate the root
group, not the full surface envelope:
```ts
import { ControlNodeSchema, GroupLayoutSchema } from "@suaveplan/control-surface-schema";
import z from "zod";
const RootGroupOnlySchema = z.object({
layout: GroupLayoutSchema,
children: z.array(ControlNodeSchema),
});
const parsed = RootGroupOnlySchema.parse(payload);
```
## API Reference
- `TransformSchema`, `RangeSchema`, `AppearanceSchema`, `BehaviourSchema`,
`BindingSchema`, `GroupLayoutSchema`, `ControlKindSchema`,
`ControlNodeSchema`, `ControlSurfaceSchema`,
`ControlSurfaceVersionedSchema` — Zod schemas mirroring the
corresponding types in `src/types/`.
## Implementation Notes
Validators downstream call `safeParse`, never `parse`, so a malformed
input becomes a typed `SchemaError("INVALID_DOCUMENT")` rather than a
raw thrown Zod error. The recursive `ControlNodeSchema` is typed as
`z.ZodType<unknown>` so the `exactOptionalPropertyTypes` mismatch
between Zod's `.optional()` (which yields `T | undefined`) and the
schema's `T?` fields doesn't force the lazy boundary to a less precise
type; the runtime check still rejects malformed nodes, and the consumer
casts `parsed.data` to `ControlSurface` after the structural checks
(z-axis, duplicate ids, binding refs) confirm the document is valid.