# definition-validator ## Purpose Validates an `FSMDefinition` object before the interpreter begins executing. Early structural validation prevents subtle runtime bugs such as transitions leading to undefined states or machines that can never leave their initial state due to a misconfigured `initial` key. The validator is called automatically by `FSMInterpreter`'s constructor and by `createMachine()`. It can also be called standalone to check definitions at authoring time, in build pipelines, or within test suites that assert that certain configurations are correct. ## Features - Verifies the top-level `initial` state exists in `states` - Recursively collects all transition `target` references (including nested state trees) and confirms every target is a known state name - Ensures any state node that declares child `states` also provides an `initial` child key - Ensures that declared `initial` children actually exist within their parent's `states` map - Throws `FSMError` with code `FSM.INVALID_DEFINITION` and rich `context` metadata on any failure ## Usage: Basic Example ```ts import { validateDefinition } from '@suaveplan/fsm'; validateDefinition({ initial: 'idle', context: {}, states: { idle: { on: { START: { target: 'active' } } }, active: { on: { STOP: { target: 'idle' } } }, }, }); // No error — definition is valid ``` ## Usage: Advanced Example ```ts import { validateDefinition } from '@suaveplan/fsm'; import { FSMError, FSM_CODES } from '@suaveplan/fsm/errors'; // Catch and inspect validation errors try { validateDefinition({ initial: 'ghost', // "ghost" is not in states context: {}, states: { idle: {} }, }); } catch (err) { if (err instanceof FSMError && err.code === FSM_CODES.INVALID_DEFINITION) { // err.context?.initial === 'ghost' console.error('Bad definition:', err.message); } } // Hierarchical definition with nested initial validateDefinition({ initial: 'form', context: { step: 1 }, states: { form: { initial: 'step1', states: { step1: { on: { NEXT: { target: 'step2' } } }, step2: { on: { BACK: { target: 'step1' } } }, }, }, }, }); ``` ## API Reference ### `validateDefinition(def: FSMDefinition): void` **Parameters:** - `def` — the complete FSM definition to validate **Returns:** `void` (pure side-effect: throws on invalid input) **Throws:** `FSMError` with code `FSM.INVALID_DEFINITION` and a `context` object containing the offending state/target names. **Generic parameter:** - `TContext` — the machine's extended context type; used only for correct typing of the definition shape. ## Implementation Notes State name collection is done with a recursive depth-first traversal of the `states` map. Both fully-qualified dotted names (e.g. `"form.step1"`) and short names (e.g. `"step1"`) are added to the lookup set so that authors can use either convention in their `target` strings. The validator deliberately does **not** check guard function arity or action return types — those are runtime concerns enforced by TypeScript at compile time. The focus here is purely structural integrity of the state graph.