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,67 @@
# walk
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module exports `walkSurface` — the canonical depth-first traversal
helper for `ControlSurface` documents. Every cross-cutting check in the
package (duplicate-id detection, binding-reference collection, z-axis
discipline) consumes the same traversal so a future change to traversal
order updates one site rather than three.
## Features
- Pre-order DFS, visiting parent groups before their children.
- Provides the root-first parent stack to the visitor so consumers can
emit path-qualified diagnostics without re-deriving the path.
- Stack-safe for the bounded tree sizes the schema permits (depth and
width are bounded by what a renderer can sensibly draw).
- The visitor is read-only by contract; mutation during traversal is
undefined behaviour and not protected against.
## Usage: Basic Example
Count every node and print the id list:
```ts
import { walkSurface } from "@suaveplan/control-surface-schema";
const ids: string[] = [];
walkSurface(surface, (node) => ids.push(node.id));
console.log(ids.length, ids);
```
## Usage: Advanced Example
Emit path-qualified diagnostics by joining the parent stack:
```ts
import { walkSurface } from "@suaveplan/control-surface-schema";
walkSurface(surface, (node, parents) => {
const path = [...parents.map((p) => p.id), node.id].join(" / ");
if (node.type === "control" && node.binding?.kind === "pluginParam") {
console.log(`[${path}] -> ${node.binding.pluginId}/${node.binding.paramPath}`);
}
});
```
## API Reference
- `type SurfaceVisitor` — `(node: ControlNode, parents: ReadonlyArray<Group>) => void`.
- `walkSurface(surface: ControlSurface, visitor: SurfaceVisitor): void`.
## Implementation Notes
The visitor is called exactly once per node in pre-order DFS. Leaf
control nodes never receive a recursive visit because they have no
children; group nodes recurse via `node.children` in their declared
order. The parent stack is rebuilt at each level by spreading the
incoming stack with the current group appended, which trades a small
amount of allocation for visitor-side immutability. Callers that need
post-order traversal compose the visitor themselves; the package does
not expose a separate post-order helper because no consumer needed it
at v0.1.0.