The type of the machine data member; usually omitted.
The everything-hook handler, or undefined when none
is installed.
The everything-hook context object. Differs from a
normal hook context in that it also includes hook_name.
A HookComplexResult describing whether the hook passed and any data replacements it requested.
Invoke an optional transition/action hook and normalize its return value into a HookComplexResult.
This is the central adapter the transition pipeline uses to run every
non-"everything" hook kind (basic, named, entry, exit, after, action, etc).
It accepts undefined for the hook slot because most hooks are not set on
most machines; when no hook is installed the step is a no-op pass.
The valid return shapes from a hook and their normalized meanings are:
undefined → { pass: true }true → { pass: true }false → { pass: false }null → { pass: false }Anything else is a programmer error and throws.
The type of the machine data member; usually omitted.
The hook handler to call, or undefined for the
"no hook installed" case.
The context object passed to the hook. Includes the current and proposed state, current and proposed data, action name, and transition kind.
A HookComplexResult describing whether the hook passed and, optionally, any data replacements it requested.
Return the direction of an arrow - right, left, or both.
import { arrow_direction } from 'jssm';
arrow_direction('->'); // 'right'
arrow_direction('<~=>'); // 'both'
The arrow to be evaluated
Return the direction of an arrow - right, left, or both.
import { arrow_left_kind } from 'jssm';
arrow_left_kind('<-'); // 'legal'
arrow_left_kind('<='); // 'main'
arrow_left_kind('<~'); // 'forced'
arrow_left_kind('<->'); // 'legal'
arrow_left_kind('->'); // 'none'
The arrow to be evaluated
Return the direction of an arrow - right, left, or both.
import { arrow_left_kind } from 'jssm';
arrow_left_kind('->'); // 'legal'
arrow_left_kind('=>'); // 'main'
arrow_left_kind('~>'); // 'forced'
arrow_left_kind('<->'); // 'legal'
arrow_left_kind('<-'); // 'none'
The arrow to be evaluated
Compile a machine's JSON intermediate representation to a config object. If you're using this (probably don't,) you're probably also using parse to get the IR, and the object constructor {@link Machine.construct} to turn the config object into a workable machine.
import { parse, compile, Machine } from 'jssm';
const intermediate = parse('a -> b;');
// [ {key:'transition', from:'a', se:{kind:'->',to:'b'}} ]
const cfg = compile(intermediate);
// { start_states:['a'], transitions: [{ from:'a', to:'b', kind:'legal', forced_only:false, main_path:false }] }
const machine = new Machine(cfg);
// Machine { _instance_name: undefined, _state: 'a', ...
This method is mostly for plugin and intermediate tool authors, or people who need to work with the machine's intermediate representation.
Most people looking at this want either the sm operator or method from,
which perform all the steps in the chain. The library's author mostly uses
operator sm, and mostly falls back to .from when needing to parse
strings dynamically instead of from template literals.
Operator sm:
import { sm } from 'jssm';
const lswitch = sm`on <=> off;`;
Method from:
import * as jssm from 'jssm';
const toggle = jssm.from('up <=> down;');
The type of the machine data member; usually omitted
The parse tree to be boiled down into a machine config
Deserializes a previously serialized machine state.
This function recreates a machine from a serialization object, restoring its state, data, and history. For security and compatibility reasons, it will refuse to deserialize data from future versions of the library.
The type of the machine data member
The FSL string defining the machine structure
The serialization object to restore from
Create a state machine from an implementation string. This is one of the two main paths for working with JSSM, alongside sm.
Use this method when you want to conveniently pull a state machine from a
string dynamically. Use operator sm when you just want to work with a
template expression.
import * as jssm from 'jssm';
const lswitch = jssm.from('on <=> off;');
The type of the machine data member; usually omitted
The FSL code to evaluate
Extra non-code configuration to pass at creation time
Type guard that narrows an unknown value to a HookComplexResult.
A hook complex result is an object with at minimum a boolean pass field,
and may optionally also carry replacement data / next_data fields that
the machine should adopt if the hook passes. This helper is used by the
hook-dispatch machinery to tell "hook returned a complex object" from
"hook returned a bare boolean / null / undefined".
is_hook_complex_result({ pass: true }); // true
is_hook_complex_result({ pass: false, data: { x: 1 }}); // true
is_hook_complex_result(true); // false
is_hook_complex_result(null); // false
is_hook_complex_result({ other: 'thing' }); // false
The type of the machine data member; usually omitted.
The value to test.
true if hr is a non-null object with a boolean pass field;
false otherwise. When true, TypeScript narrows hr to
HookComplexResult<mDT>.
Normalize any legal hook return value to a single "did it reject?" boolean.
Hooks in jssm may return any of the following to indicate success:
true, undefined, or a complex result whose pass field is true.
They may return any of the following to indicate rejection:
false, or a complex result whose pass field is false. This helper
collapses all of those shapes into one boolean so callers don't have to
re-implement the matrix.
is_hook_rejection(true); // false (pass)
is_hook_rejection(undefined); // false (pass)
is_hook_rejection(false); // true (reject)
is_hook_rejection({ pass: true }); // false (pass)
is_hook_rejection({ pass: false }); // true (reject)
The type of the machine data member; usually omitted.
A hook result of any legal shape.
true if the hook rejected the transition; false if it passed.
The type of the machine data member; usually omitted
The FSL code to be evaluated and built into a machine config
This method wraps the parser call that comes from the peg grammar, parse. Generally neither this nor that should be used directly unless you mean to develop plugins or extensions for the machine.
Parses the intermediate representation of a compiled string down to a machine configuration object. If you're using this (probably don't,) you're probably also using compile and Machine.constructor.
import { parse, compile, Machine } from 'jssm';
const intermediate = wrap_parse('a -> b;', {});
// [ {key:'transition', from:'a', se:{kind:'->',to:'b'}} ]
const cfg = compile(intermediate);
// { start_states:['a'], transitions: [{ from:'a', to:'b', kind:'legal', forced_only:false, main_path:false }] }
const machine = new Machine(cfg);
// Machine { _instance_name: undefined, _state: 'a', ...
This method is mostly for plugin and intermediate tool authors, or people who need to work with the machine's intermediate representation.
Most people looking at this want either the sm operator or method from,
which perform all the steps in the chain. The library's author mostly uses
operator sm, and mostly falls back to .from when needing to parse
strings dynamically instead of from template literals.
Operator sm:
import { sm } from 'jssm';
const lswitch = sm`on <=> off;`;
Method from:
import * as jssm from 'jssm';
const toggle = jssm.from('up <=> down;');
wrap_parse itself is an internal convenience method for alting out an
object as the options call. Not generally meant for external use.
The FSL code to be evaluated
Things to control about the instance
Create a state machine from a template string. This is one of the two main paths for working with JSSM, alongside from.
Use this method when you want to work directly and conveniently with a
constant template expression. Use .from when you want to pull from
dynamic strings.
import * as jssm from 'jssm';
const lswitch = jssm.from('on <=> off;');
The type of the machine data member; usually omitted
The assembled code
The mechanic for template argument insertion
Collapse a list of individual state-style key/value pairs into a single JssmStateConfig object, remapping FSL-style kebab-case keys to the camelCase field names the runtime uses.
The parser emits state styling as a flat array like
[{ key: 'color', value: 'red' }, { key: 'line-style', value: 'dashed' }]
because that is the most natural shape for the grammar to produce. This
helper runs once per style bucket during Machine construction to turn
those arrays into the compact { color, lineStyle, ... } objects the
graph-rendering code expects.
state_style_condense([
{ key: 'color', value: 'red' },
{ key: 'shape', value: 'oval' },
{ key: 'line-style', value: 'dashed' }
]);
// => { color: 'red', shape: 'oval', lineStyle: 'dashed' }
state_style_condense(undefined);
// => {}
The list of style keys to condense. undefined is accepted
and yields an empty config.
Optional Machine reference, used only so that any
JssmError thrown can point at the offending machine in its
diagnostic message.
A JssmStateConfig object containing every key from jssk
remapped into its camelCase field.
An internal method meant to take a series of declarations and fold them into a single multi-faceted declaration, in the process of building a state. Not generally meant for external use.
Generated using TypeDoc
Invoke an optional "everything" hook and normalize its return value into a HookComplexResult.
Mechanically identical to abstract_hook_step, but typed for the everything-hook family (
pre_everything_hookandeverything_hook), whose context object carries an extrahook_namefield identifying which bracket of the pipeline is firing. Separated fromabstract_hook_stepso TypeScript can enforce that the hook handler and the context object agree on shape.The valid return shapes and their meanings are the same as for
abstract_hook_step:undefinedortrue→{ pass: true }falseornull→{ pass: false }{TypeError} If the hook returns a value outside the legal shapes.