# `limiter/schemas` _(no submodules)_ ## Purpose Zod schemas validating the construction-time options of `LimiterPlugin` and the (currently empty) preset payload contract. 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, editors, or RPC validation) without importing the audio implementation. ## Features - `LimiterPluginOptionsSchema` — validates `initialCeilingDb` ∈ [-60, 0] and `initialReleaseMs` ∈ [1, 1000]. - `LimiterPresetDataSchema` — empty strict object: the limiter has no plugin-specific preset payload, so any extra keys are rejected by `.strict()`. - Both schemas are `z.object` / `z.number().finite()` based so `NaN` and `Infinity` cannot sneak through. ## Usage: Basic Example ```ts import { LimiterPluginOptionsSchema } from "@suaveplan/audio-fx-plugin-limiter"; const parsed = LimiterPluginOptionsSchema.parse({ initialCeilingDb: -3 }); ``` ## Usage: Advanced Example ```ts import { LimiterPluginOptionsSchema } from "@suaveplan/audio-fx-plugin-limiter"; // Drive an editor form from the schema's introspected shape. const fields = LimiterPluginOptionsSchema.keyof().options; for (const field of fields) { form.addRow(field); } ``` ## API Reference - `LimiterPluginOptionsSchema: z.ZodObject<{ initialCeilingDb?, initialReleaseMs? }>` - `LimiterPresetDataSchema: z.ZodObject<{}, "strict">` ## Implementation Notes The constructor in `limiter.ts` calls `LimiterPluginOptionsSchema.safeParse(options)` and throws `AudioFxError(INVALID_OPTIONS, ...)` on failure with the Zod `issues` array attached as `context`. This keeps the surface uniform with the other plugins (eq/compressor/reverb/filter/delay/gate) and makes log triage easy: a single grep for `audio-fx.limiter-invalid-options` finds every malformed-options site. `LimiterPresetDataSchema` is `.strict()` on purpose. The limiter has no preset-specific payload today, but `applyPreset` from `AbstractAudioFxPlugin` will still call the schema's `parse`. Using `.strict()` rejects accidentally-mixed payloads from sibling plugins (e.g., a `CompressorPresetData` blob applied to a `LimiterPlugin`), surfacing the mistake at the boundary rather than silently no-op'ing parameter restoration.