Files
skills/docs/media/audio/control-surface-schema/src/schemas/control-surface-schema.md
2026-05-29 08:20:56 +01:00

3.0 KiB

control-surface-schema (Zod)

(no submodules)

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:

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:

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.