Getting Started
Installation
Section titled “Installation”Your first FSM
Section titled “Your first FSM”Import createFsm and pass it a config object. That’s the whole setup.
A few things to note:
id— a label for debugging and events. Not required to be unique, but it helps.initialState— the state the FSM boots into._onEnterfires on first entry.context— a plain object scoped to this FSM instance. Mutate it freely; it’s yours.states— a map of state names to handler maps. Each key (other than lifecycle hooks like_onEnterand_onExit) is an input name.
Handlers are functions that receive { ctx, inputName, defer, emit }. Returning a valid state name triggers a transition. Returning undefined (or nothing) keeps the FSM in its current state.
Interacting with the FSM
Section titled “Interacting with the FSM”| Method | What it does |
|---|---|
handle(inputName, ...args) | Dispatch an input to the current state |
canHandle(inputName) | True if the current state has a handler (or "*") for this input |
currentState() | Returns the current state name as a string |
on(eventName, callback) | Subscribe to a lifecycle event — returns { off() } |
emit(eventName, data?) | Emit a custom event to subscribers |
reset() | Transition back to initialState |
dispose() | Permanently shut down the FSM |
String shorthand
Section titled “String shorthand”When a handler always transitions to the same state with no logic needed, use the string shorthand instead of a function:
Shorthand is validated by TypeScript — the target must be an actual key in your states config.
Next steps
Section titled “Next steps”- Concepts — the mental model behind states, inputs, and transitions
- createFsm — full API reference including hierarchical states, deferred input, and events
- createBehavioralFsm — define behavior once, apply it to many independent client objects
- Examples — real-world patterns you can steal