3.6 KiB
fsm-error
(no submodules)
Purpose
Defines the stable error-code registry and typed error class for the @suaveplan/fsm package. Every error thrown by the FSM interpreter, definition validator, and context helpers extends FSMError, giving callers a single instanceof check and a machine-readable code property drawn from FSM_CODES.
The registry is built with defineCodes from @suaveplan/error, which guarantees that each code string is unique across the entire @suaveplan/* ecosystem and can be compared with === without string literals.
Features
- Five stable error codes covering all failure scenarios:
INVALID_DEFINITION,INVALID_TRANSITION,INVALID_STATE,GUARD_FAILED,ACTION_ERROR FSMErrorextendsSuaveplanError<FSMCode>for narrow discriminated-union typing- Supports optional
causeandcontextmetadata on every error instance - Fully compatible with the
@suaveplan/errorwire-format serialization
Usage: Basic Example
import { FSMError, FSM_CODES } from '@suaveplan/fsm/errors';
try {
machine.send('UNKNOWN_EVENT');
} catch (err) {
if (err instanceof FSMError) {
console.error(err.code, err.message);
// "FSM.INVALID_TRANSITION" "No valid transition for event in current state"
}
}
Usage: Advanced Example
import { FSMError, FSM_CODES } from '@suaveplan/fsm/errors';
function handleFSMError(err: unknown): void {
if (!(err instanceof FSMError)) throw err;
switch (err.code) {
case FSM_CODES.INVALID_DEFINITION:
console.error('Machine definition is malformed:', err.message);
break;
case FSM_CODES.INVALID_TRANSITION:
console.warn('Event not handled in current state');
break;
case FSM_CODES.GUARD_FAILED:
console.info('Transition blocked by guard');
break;
case FSM_CODES.ACTION_ERROR:
console.error('Action threw during transition:', err.cause);
break;
default:
throw err;
}
}
API Reference
FSM_CODES
const FSM_CODES: {
INVALID_DEFINITION: 'FSM.INVALID_DEFINITION';
INVALID_TRANSITION: 'FSM.INVALID_TRANSITION';
INVALID_STATE: 'FSM.INVALID_STATE';
GUARD_FAILED: 'FSM.GUARD_FAILED';
ACTION_ERROR: 'FSM.ACTION_ERROR';
}
Stable string constants for each FSM error domain. Use these instead of raw string comparisons to benefit from TypeScript narrowing.
type FSMCode
Union type of all values in FSM_CODES. Used as the generic parameter of FSMError.
class FSMError
class FSMError extends SuaveplanError<FSMCode> {
constructor(
code: FSMCode,
message: string,
options?: { cause?: Error; context?: Record<string, unknown> }
)
}
Parameters:
code— one of theFSM_CODESvalues; stored asthis.codemessage— human-readable description of the failureoptions.cause— underlying error that triggered this one (chained)options.context— arbitrary key/value metadata (state name, event type, etc.)
Throws: Never (constructor only).
Implementation Notes
The defineCodes helper from @suaveplan/error namespaces all codes under "FSM." to prevent collisions with codes from other packages sharing the same registry. The as const assertion on the descriptor object ensures the resulting type is a fully-discriminated union rather than string.
The noUselessConstructor biome lint suppression is intentional: the constructor is required to widen the protected base constructor to public, which is a documented pattern in this repository for all SuaveplanError subclasses.