BehavioralFsm
Defined in: behavioral-fsm.ts:61
Defines FSM behavior (states + transitions) while tracking per-client state
in a WeakMap. A single BehavioralFsm instance can drive any number of
independent client objects simultaneously — each gets its own state,
deferred queue, and lifecycle.
Prefer createBehavioralFsm() over constructing this directly — the factory
infers all generic parameters from the config object.
All public methods silently no-op after dispose() is called.
Type Parameters
Section titled “Type Parameters”TClient
Section titled “TClient”TClient extends object
The client object type. Must be an object (non-primitive) so it can serve as a WeakMap key.
TStateNames
Section titled “TStateNames”TStateNames extends string
String literal union of valid state names.
TInputNames
Section titled “TInputNames”TInputNames extends string
String literal union of valid input names.
TBubbles
Section titled “TBubbles”TBubbles extends string = never
String literal union of inputs this FSM declares via
bubbles. Type-only — carried so BubblesOfInstance can extract it from
a constructed instance; nothing at runtime reads this generic.
TInputs
Section titled “TInputs”TInputs extends InputMapLike<TInputs> = InputMap
The input payload map (#195). Defaults to the wide
map, under which handle()’s signature reduces to exactly the untyped
behavior: keyof of the wide map is string, so the key intersection
is TInputNames and the payload lookup is unknown[]. The typed
factory forms pass the user’s map here.
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new BehavioralFsm<
TClient,TStateNames,TInputNames,TBubbles,TInputs>(config):BehavioralFsm<TClient,TStateNames,TInputNames,TBubbles,TInputs>
Defined in: behavioral-fsm.ts:92
Parameters
Section titled “Parameters”config
Section titled “config”FsmConfig<TClient, Record<string, Record<string, unknown>>>
Returns
Section titled “Returns”BehavioralFsm<TClient, TStateNames, TInputNames, TBubbles, TInputs>
Properties
Section titled “Properties”[MACHINA_TYPE]
Section titled “[MACHINA_TYPE]”
readonly[MACHINA_TYPE]:"BehavioralFsm"
Defined in: behavioral-fsm.ts:72
readonlyid:string
Defined in: behavioral-fsm.ts:69
initialState
Section titled “initialState”
readonlyinitialState:TStateNames
Defined in: behavioral-fsm.ts:70
states
Section titled “states”
readonlystates:Record<string,Record<string,unknown>>
Defined in: behavioral-fsm.ts:76
Methods
Section titled “Methods”canHandle()
Section titled “canHandle()”canHandle(
client,inputName):boolean
Defined in: behavioral-fsm.ts:172
Returns true if the client’s current state has a handler for inputName
(or a catch-all "*" handler), or if the current state’s _child chain
can handle it — the check recurses to the same depth handle()’s
delegation can actually reach, so a grandchild-only input answers true
from the root. Does NOT initialize the client — no _onEnter, no
events, no side effects. Unseen clients are treated as if they were
already in initialState. Returns false when disposed.
Parameters
Section titled “Parameters”client
Section titled “client”TClient
inputName
Section titled “inputName”string
Returns
Section titled “Returns”boolean
compositeState()
Section titled “compositeState()”compositeState(
client):string
Defined in: behavioral-fsm.ts:354
Returns the client’s state as a dot-delimited path including any active
child FSM states (e.g. "active.connecting.retrying"). Returns just the
current state name when no child is active. Returns "" for clients that
have never been initialized (unlike currentState() which returns undefined).
Parameters
Section titled “Parameters”client
Section titled “client”TClient
Returns
Section titled “Returns”string
currentState()
Section titled “currentState()”currentState(
client):TStateNames|undefined
Defined in: behavioral-fsm.ts:210
Returns the client’s current state, or undefined if the client has
never been initialized (i.e. handle(), transition(), or reset()
have never been called for it). Does NOT trigger initialization.
Parameters
Section titled “Parameters”client
Section titled “client”TClient
Returns
Section titled “Returns”TStateNames | undefined
dispose()
Section titled “dispose()”dispose(
options?):void
Defined in: behavioral-fsm.ts:741
Permanently shut down this FSM. Irreversible — all subsequent method
calls become silent no-ops. Runs the config’s onDispose hook once per
live client, tears down child subscriptions, cascades disposal to child
FSMs (unless preserveChildren is set), and clears all listeners. The
same child appearing in multiple states is disposed once.
A second call is a no-op: the hook never runs twice for one client.
Errors thrown by onDispose hooks or by child disposals do not stop
teardown. They are collected and rethrown together as one
AggregateError after the emitter clears.
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”void
emit()
Section titled “emit()”emit(
eventName,data?):void
Defined in: behavioral-fsm.ts:719
Emit a custom event through the FSM. Built-in lifecycle events are emitted automatically — this is for user-defined events from handlers. No-ops when disposed.
Parameters
Section titled “Parameters”eventName
Section titled “eventName”string
unknown
Returns
Section titled “Returns”void
handle()
Section titled “handle()”handle(
client, …call):void
Defined in: behavioral-fsm.ts:115
Dispatch an input to the given client’s current state handler.
Delegation order: if the current state has a _child FSM that can
handle the input, it is dispatched there. If the child emits nohandler,
the input bubbles up to this FSM’s local handler. If no handler exists
here either, nohandler is emitted on this FSM’s emitter.
No-ops silently when disposed.
Parameters
Section titled “Parameters”client
Section titled “client”TClient
…InputCall<TInputNames, TInputs>
Returns
Section titled “Returns”void
Call Signature
Section titled “Call Signature”on<
K>(eventName,callback):Subscription
Defined in: behavioral-fsm.ts:702
Subscribe to a built-in lifecycle event or the wildcard.
Named overload: typed payload includes { client: TClient } so you can
identify which client the event pertains to. Wildcard ("*") receives
(eventName, data) for every event. Returns a no-op Subscription
when disposed.
Type Parameters
Section titled “Type Parameters”K extends "transitioning" | "transitioned" | "handling" | "handled" | "nohandler" | "invalidstate" | "deferred"
Parameters
Section titled “Parameters”eventName
Section titled “eventName”K
callback
Section titled “callback”(data) => void
Returns
Section titled “Returns”Call Signature
Section titled “Call Signature”on(
eventName,callback):Subscription
Defined in: behavioral-fsm.ts:706
Subscribe to a built-in lifecycle event or the wildcard.
Named overload: typed payload includes { client: TClient } so you can
identify which client the event pertains to. Wildcard ("*") receives
(eventName, data) for every event. Returns a no-op Subscription
when disposed.
Parameters
Section titled “Parameters”eventName
Section titled “eventName”"*"
callback
Section titled “callback”(eventName, data) => void
Returns
Section titled “Returns”rehydrate()
Section titled “rehydrate()”Call Signature
Section titled “Call Signature”rehydrate(
client,compositeState):void
Defined in: behavioral-fsm.ts:393
Silently place client at compositeState with no lifecycle activity —
no _onEnter, no _onExit, no transitioning/transitioned events.
Designed to work with compositeState(), which produces the dot-path
string that the string form consumes.
The snapshot form (pass a ClientSnapshot from dehydrate()) additionally
requeues each level’s pending deferred inputs, so a client resumes with the
same replay-on-next-transition behavior it had when dehydrated. Both forms
validate the ENTIRE hierarchy before writing anything — a throw at any level
leaves every level, including this one, unwritten.
Throws synchronously for unknown state names, missing _child at an inner
level, or Fsm children in the hierarchy (Fsm owns its own context; nothing
per-client to rehydrate there).
No-ops silently when disposed.
Parameters
Section titled “Parameters”client
Section titled “client”TClient
compositeState
Section titled “compositeState”string
Returns
Section titled “Returns”void
Call Signature
Section titled “Call Signature”rehydrate(
client,snapshot):void
Defined in: behavioral-fsm.ts:394
Silently place client at compositeState with no lifecycle activity —
no _onEnter, no _onExit, no transitioning/transitioned events.
Designed to work with compositeState(), which produces the dot-path
string that the string form consumes.
The snapshot form (pass a ClientSnapshot from dehydrate()) additionally
requeues each level’s pending deferred inputs, so a client resumes with the
same replay-on-next-transition behavior it had when dehydrated. Both forms
validate the ENTIRE hierarchy before writing anything — a throw at any level
leaves every level, including this one, unwritten.
Throws synchronously for unknown state names, missing _child at an inner
level, or Fsm children in the hierarchy (Fsm owns its own context; nothing
per-client to rehydrate there).
No-ops silently when disposed.
Parameters
Section titled “Parameters”client
Section titled “client”TClient
snapshot
Section titled “snapshot”Returns
Section titled “Returns”void
reset()
Section titled “reset()”reset(
client):void
Defined in: behavioral-fsm.ts:198
Transition the client back to initialState, firing _onEnter and
lifecycle events as if entering it fresh. No-ops when disposed.
Parameters
Section titled “Parameters”client
Section titled “client”TClient
Returns
Section titled “Returns”void
transition()
Section titled “transition()”transition(
client,toState):void
Defined in: behavioral-fsm.ts:235
Directly transition client to toState, running the full lifecycle:
_onExit for the current state → transitioning event → update state →
_onEnter for new state → transitioned event → child reset → deferred
queue replay → bounce (if _onEnter returned a state name).
Same-state transitions are silently ignored. Transitions to unknown state
names emit invalidstate instead of throwing. Throws if the transition
depth exceeds MAX_TRANSITION_DEPTH (likely an _onEnter → transition loop).
No-ops when disposed. When _onExit, a transitioning listener,
_onEnter, or a transitioned listener calls dispose()
mid-transition, that callback runs to completion and the transition
stops as soon as it returns: no state write (for _onExit), no
_onEnter (for the first two), no child reset, no deferred replay,
no bounce. The same rule covers the initial _onEnter during lazy
client initialization, whether handle() or transition() triggered
it, and handling listeners in dispatch().
Parameters
Section titled “Parameters”client
Section titled “client”TClient
toState
Section titled “toState”TStateNames
Returns
Section titled “Returns”void