3.1 KiB
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
initialstate exists instates - Recursively collects all transition
targetreferences (including nested state trees) and confirms every target is a known state name - Ensures any state node that declares child
statesalso provides aninitialchild key - Ensures that declared
initialchildren actually exist within their parent'sstatesmap - Throws
FSMErrorwith codeFSM.INVALID_DEFINITIONand richcontextmetadata on any failure
Usage: Basic Example
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
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<TContext>(def: FSMDefinition<TContext>): 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.