Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# `phaser/schemas`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Zod schemas validating the construction-time options and preset payload of `PhaserPlugin`. These run on the public boundary between user code and the plugin: any malformed object hitting the constructor or `applyPreset` is rejected with `AUDIO_FX.INVALID_OPTIONS` / `AUDIO_FX.INVALID_PRESET` before it can corrupt runtime state.
|
||||
|
||||
Separating schemas from the plugin module lets `index.ts` re-export them so callers can introspect the option surface (for forms, RPC validation, or storybook controls) without importing the audio implementation.
|
||||
|
||||
## Features
|
||||
|
||||
- `PhaserPluginOptionsSchema` — validates all six optional construction fields with their documented ranges.
|
||||
- `initialStages` is `z.number().int().min(2).max(12)` so non-integer stage counts cannot sneak through.
|
||||
- `PhaserPresetDataSchema` — empty strict object; the phaser has no plugin-specific preset payload, so any extra keys are rejected.
|
||||
- All numeric fields use `z.number().finite()` so `NaN` and `Infinity` cannot sneak through.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { PhaserPluginOptionsSchema } from "@suaveplan/audio-fx-plugin-phaser";
|
||||
|
||||
const parsed = PhaserPluginOptionsSchema.parse({ initialDepth: 0.6 });
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
PhaserPluginOptionsSchema,
|
||||
PhaserPresetDataSchema,
|
||||
} from "@suaveplan/audio-fx-plugin-phaser";
|
||||
|
||||
// Driver for an editor form: pull the keys + ranges from the schema.
|
||||
const optionFields = PhaserPluginOptionsSchema.keyof().options;
|
||||
for (const field of optionFields) {
|
||||
form.addRow(field);
|
||||
}
|
||||
|
||||
// Reject foreign preset payloads at the IPC boundary.
|
||||
function isPhaserPreset(blob: unknown): boolean {
|
||||
return PhaserPresetDataSchema.safeParse(blob).success;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `PhaserPluginOptionsSchema: z.ZodObject<{ initialRateHz?, initialDepth?, initialStages?, initialFeedback?, initialWet?, initialCenterHz? }>`
|
||||
- `PhaserPresetDataSchema: z.ZodObject<{}, "strict">`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`PhaserPresetDataSchema` is `.strict()` so unknown fields are rejected, matching the sibling-plugin policy. The phaser has no plugin-specific preset payload today: every parameter (`rate`, `depth`, `stages`, `feedback`, `wet`, `center`) travels through the universal parameter snapshot that `AbstractAudioFxPlugin` builds, and the empty `presetData` field is a marker that the plugin opts out of plugin-specific state.
|
||||
|
||||
The maximum feedback is `0.95`, not `1.0`. Allowing feedback at unity would create a marginally stable system whose output diverges for any non-zero input; clamping at 0.95 leaves enough headroom that even a noise-floor leak stays bounded over arbitrarily long renders. This boundary is the same as for the chorus, delay, and flanger plugins so all four feedback-bearing effects share one mental model.
|
||||
Reference in New Issue
Block a user