jssm
Version:
A Javascript finite state machine (FSM) with a terse DSL and a simple API. Most FSMs are one-liners. Fast, easy, powerful, well tested, typed with TypeScript, and visualizations. MIT License.
1,142 lines (1,141 loc) • 43 kB
TypeScript
declare type StateType = string;
import { JssmGenericState, JssmGenericConfig, JssmStateConfig, JssmTransition, JssmTransitionList, // JssmTransitionRule,
JssmMachineInternalState, JssmAllowsOverride, JssmStateDeclaration, JssmStateStyleKeyList, JssmLayout, JssmHistory, JssmSerialization, FslDirection, FslDirections, FslTheme, HookDescription, HookHandler, HookContext, HookResult, HookComplexResult, JssmRng } from './jssm_types';
import { arrow_direction, arrow_left_kind, arrow_right_kind } from './jssm_arrow';
import { compile, make, wrap_parse } from './jssm_compiler';
import { seq, unique, find_repeated, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, sleep } from './jssm_util';
import * as constants from './jssm_constants';
declare const shapes: string[], gviz_shapes: string[], named_colors: string[];
import { version, build_time } from './version';
/*********
*
* 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.
*
* @internal
*
*/
declare function transfer_state_properties(state_decl: JssmStateDeclaration): JssmStateDeclaration;
declare function state_style_condense(jssk: JssmStateStyleKeyList): JssmStateConfig;
declare class Machine<mDT> {
_state: StateType;
_states: Map<StateType, JssmGenericState>;
_edges: Array<JssmTransition<StateType, mDT>>;
_edge_map: Map<StateType, Map<StateType, number>>;
_named_transitions: Map<StateType, number>;
_actions: Map<StateType, Map<StateType, number>>;
_reverse_actions: Map<StateType, Map<StateType, number>>;
_reverse_action_targets: Map<StateType, Map<StateType, number>>;
_start_states: Set<StateType>;
_end_states: Set<StateType>;
_machine_author?: Array<string>;
_machine_comment?: string;
_machine_contributor?: Array<string>;
_machine_definition?: string;
_machine_language?: string;
_machine_license?: string;
_machine_name?: string;
_machine_version?: string;
_fsl_version?: string;
_raw_state_declaration?: Array<Object>;
_state_declarations: Map<StateType, JssmStateDeclaration>;
_data?: mDT;
_instance_name: string;
_rng_seed: number;
_rng: JssmRng;
_graph_layout: JssmLayout;
_dot_preamble: string;
_arrange_declaration: Array<Array<StateType>>;
_arrange_start_declaration: Array<Array<StateType>>;
_arrange_end_declaration: Array<Array<StateType>>;
_themes: FslTheme[];
_flow: FslDirection;
_has_hooks: boolean;
_has_basic_hooks: boolean;
_has_named_hooks: boolean;
_has_entry_hooks: boolean;
_has_exit_hooks: boolean;
_has_after_hooks: boolean;
_has_global_action_hooks: boolean;
_has_transition_hooks: boolean;
_has_forced_transitions: boolean;
_hooks: Map<string, HookHandler<mDT>>;
_named_hooks: Map<string, HookHandler<mDT>>;
_entry_hooks: Map<string, HookHandler<mDT>>;
_exit_hooks: Map<string, HookHandler<mDT>>;
_after_hooks: Map<string, HookHandler<mDT>>;
_global_action_hooks: Map<string, HookHandler<mDT>>;
_any_action_hook: HookHandler<mDT> | undefined;
_standard_transition_hook: HookHandler<mDT> | undefined;
_main_transition_hook: HookHandler<mDT> | undefined;
_forced_transition_hook: HookHandler<mDT> | undefined;
_any_transition_hook: HookHandler<mDT> | undefined;
_has_post_hooks: boolean;
_has_post_basic_hooks: boolean;
_has_post_named_hooks: boolean;
_has_post_entry_hooks: boolean;
_has_post_exit_hooks: boolean;
_has_post_global_action_hooks: boolean;
_has_post_transition_hooks: boolean;
_code_allows_override: JssmAllowsOverride;
_config_allows_override: JssmAllowsOverride;
_post_hooks: Map<string, HookHandler<mDT>>;
_post_named_hooks: Map<string, HookHandler<mDT>>;
_post_entry_hooks: Map<string, HookHandler<mDT>>;
_post_exit_hooks: Map<string, HookHandler<mDT>>;
_post_global_action_hooks: Map<string, HookHandler<mDT>>;
_post_any_action_hook: HookHandler<mDT> | undefined;
_post_standard_transition_hook: HookHandler<mDT> | undefined;
_post_main_transition_hook: HookHandler<mDT> | undefined;
_post_forced_transition_hook: HookHandler<mDT> | undefined;
_post_any_transition_hook: HookHandler<mDT> | undefined;
_property_keys: Set<string>;
_default_properties: Map<string, any>;
_state_properties: Map<string, any>;
_required_properties: Set<string>;
_history: JssmHistory<mDT>;
_history_length: number;
_state_style: JssmStateConfig;
_active_state_style: JssmStateConfig;
_hooked_state_style: JssmStateConfig;
_terminal_state_style: JssmStateConfig;
_start_state_style: JssmStateConfig;
_end_state_style: JssmStateConfig;
_state_labels: Map<string, string>;
_time_source: () => number;
_create_started: number;
_created: number;
_after_mapping: Map<string, [string, number]>;
_timeout_source: (Function: any, number: any) => number;
_clear_timeout_source: (h: any) => void;
_timeout_handle: number | undefined;
_timeout_target: string | undefined;
_timeout_target_time: number | undefined;
constructor({ start_states, end_states, initial_state, start_states_no_enforce, complete, transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, state_declaration, property_definition, state_property, fsl_version, dot_preamble, arrange_declaration, arrange_start_declaration, arrange_end_declaration, theme, flow, graph_layout, instance_name, history, data, default_state_config, default_active_state_config, default_hooked_state_config, default_terminal_state_config, default_start_state_config, default_end_state_config, allows_override, config_allows_override, rng_seed, time_source, timeout_source, clear_timeout_source }: JssmGenericConfig<StateType, mDT>);
/********
*
* Internal method for fabricating states. Not meant for external use.
*
* @internal
*
*/
_new_state(state_config: JssmGenericState): StateType;
/*********
*
* Get the current state of a machine.
*
* ```typescript
* import * as jssm from 'jssm';
*
* const lswitch = jssm.from('on <=> off;');
* console.log( lswitch.state() ); // 'on'
*
* lswitch.transition('off');
* console.log( lswitch.state() ); // 'off'
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
state(): StateType;
/*********
*
* Get the label for a given state, if any; return `undefined` otherwise.
*
* ```typescript
* import * as jssm from 'jssm';
*
* const lswitch = jssm.from('a -> b; state a: { label: "Foo!"; };');
* console.log( lswitch.label_for('a') ); // 'Foo!'
* console.log( lswitch.label_for('b') ); // undefined
* ```
*
* See also {@link display_text}.
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
label_for(state: StateType): string;
/*********
*
* Get whatever the node should show as text.
*
* Currently, this means to get the label for a given state, if any;
* otherwise to return the node's name. However, this definition is expected
* to grow with time, and it is currently considered ill-advised to manually
* parse this text.
*
* See also {@link label_for}.
*
* ```typescript
* import * as jssm from 'jssm';
*
* const lswitch = jssm.from('a -> b; state a: { label: "Foo!"; };');
* console.log( lswitch.display_text('a') ); // 'Foo!'
* console.log( lswitch.display_text('b') ); // 'b'
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
display_text(state: StateType): string;
/*********
*
* Get the current data of a machine.
*
* ```typescript
* import * as jssm from 'jssm';
*
* const lswitch = jssm.from('on <=> off;', {data: 1});
* console.log( lswitch.data() ); // 1
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
data(): mDT;
/*********
*
* Get the current value of a given property name.
*
* ```typescript
*
* ```
*
* @param name The relevant property name to look up
*
* @returns The value behind the prop name. Because functional props are
* evaluated as getters, this can be anything.
*
*/
prop(name: string): any;
/*********
*
* Get the current value of a given property name. If missing on the state
* and without a global default, throw, unlike {@link prop}, which would
* return `undefined` instead.
*
* ```typescript
*
* ```
*
* @param name The relevant property name to look up
*
* @returns The value behind the prop name. Because functional props are
* evaluated as getters, this can be anything.
*
*/
strict_prop(name: string): any;
/*********
*
* Get the current value of every prop, as an object. If no current definition
* exists for a prop - that is, if the prop was defined without a default and
* the current state also doesn't define the prop - then that prop will be listed
* in the returned object with a value of `undefined`.
*
* ```typescript
* const traffic_light = sm`
*
* property can_go default true;
* property hesitate default true;
* property stop_first default false;
*
* Off -> Red => Green => Yellow => Red;
* [Red Yellow Green] ~> [Off FlashingRed];
* FlashingRed -> Red;
*
* state Red: { property stop_first true; property can_go false; };
* state Off: { property stop_first true; };
* state FlashingRed: { property stop_first true; };
* state Green: { property hesitate false; };
*
* `;
*
* traffic_light.state(); // Off
* traffic_light.props(); // { can_go: true, hesitate: true, stop_first: true; }
*
* traffic_light.go('Red');
* traffic_light.props(); // { can_go: false, hesitate: true, stop_first: true; }
*
* traffic_light.go('Green');
* traffic_light.props(); // { can_go: true, hesitate: false, stop_first: false; }
* ```
*
*/
props(): object;
/*********
*
* Get the current value of every prop, as an object. Compare
* {@link prop_map}, which returns a `Map`.
*
* ```typescript
*
* ```
*
*/
/*********
*
* Get the current value of every prop, as an object. Compare
* {@link prop_map}, which returns a `Map`. Akin to {@link strict_prop},
* this throws if a required prop is missing.
*
* ```typescript
*
* ```
*
*/
/*********
*
* Check whether a given string is a known property's name.
*
* ```typescript
* const example = sm`property foo default 1; a->b;`;
*
* example.known_prop('foo'); // true
* example.known_prop('bar'); // false
* ```
*
* @param prop_name The relevant property name to look up
*
*/
known_prop(prop_name: string): boolean;
/*********
*
* List all known property names. If you'd also like values, use
* {@link props} instead. The order of the properties is not defined, and
* the properties generally will not be sorted.
*
* ```typescript
* ```
*
*/
known_props(): string[];
/********
*
* Check whether a given state is a valid start state (either because it was
* explicitly named as such, or because it was the first mentioned state.)
*
* ```typescript
* import { sm, is_start_state } from 'jssm';
*
* const example = sm`a -> b;`;
*
* console.log( final_test.is_start_state('a') ); // true
* console.log( final_test.is_start_state('b') ); // false
*
* const example = sm`start_states: [a b]; a -> b;`;
*
* console.log( final_test.is_start_state('a') ); // true
* console.log( final_test.is_start_state('b') ); // true
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The name of the state to check
*
*/
is_start_state(whichState: StateType): boolean;
/********
*
* Check whether a given state is a valid start state (either because it was
* explicitly named as such, or because it was the first mentioned state.)
*
* ```typescript
* import { sm, is_end_state } from 'jssm';
*
* const example = sm`a -> b;`;
*
* console.log( final_test.is_start_state('a') ); // false
* console.log( final_test.is_start_state('b') ); // true
*
* const example = sm`end_states: [a b]; a -> b;`;
*
* console.log( final_test.is_start_state('a') ); // true
* console.log( final_test.is_start_state('b') ); // true
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The name of the state to check
*
*/
is_end_state(whichState: StateType): boolean;
/********
*
* Check whether a given state is final (either has no exits or is marked
* `complete`.)
*
* ```typescript
* import { sm, state_is_final } from 'jssm';
*
* const final_test = sm`first -> second;`;
*
* console.log( final_test.state_is_final('first') ); // false
* console.log( final_test.state_is_final('second') ); // true
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The name of the state to check for finality
*
*/
state_is_final(whichState: StateType): boolean;
/********
*
* Check whether the current state is final (either has no exits or is marked
* `complete`.)
*
* ```typescript
* import { sm, is_final } from 'jssm';
*
* const final_test = sm`first -> second;`;
*
* console.log( final_test.is_final() ); // false
* state.transition('second');
* console.log( final_test.is_final() ); // true
* ```
*
*/
is_final(): boolean;
/********
*
* Serialize the current machine, including all defining state but not the
* machine string, to a structure. This means you will need the machine
* string to recreate (to not waste repeated space;) if you want the machine
* string embedded, call {@link serialize_with_string} instead.
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
serialize(comment?: string | undefined): JssmSerialization<mDT>;
graph_layout(): string;
dot_preamble(): string;
machine_author(): Array<string>;
machine_comment(): string;
machine_contributor(): Array<string>;
machine_definition(): string;
machine_language(): string;
machine_license(): string;
machine_name(): string;
machine_version(): string;
raw_state_declarations(): Array<Object>;
state_declaration(which: StateType): JssmStateDeclaration;
state_declarations(): Map<StateType, JssmStateDeclaration>;
fsl_version(): string;
machine_state(): JssmMachineInternalState<mDT>;
/*********
*
* List all the states known by the machine. Please note that the order of
* these states is not guaranteed.
*
* ```typescript
* import * as jssm from 'jssm';
*
* const lswitch = jssm.from('on <=> off;');
* console.log( lswitch.states() ); // ['on', 'off']
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
states(): Array<StateType>;
state_for(whichState: StateType): JssmGenericState;
/*********
*
* Check whether the machine knows a given state.
*
* ```typescript
* import * as jssm from 'jssm';
*
* const lswitch = jssm.from('on <=> off;');
*
* console.log( lswitch.has_state('off') ); // true
* console.log( lswitch.has_state('dance') ); // false
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The state to be checked for extance
*
*/
has_state(whichState: StateType): boolean;
/*********
*
* Lists all edges of a machine.
*
* ```typescript
* import { sm } from 'jssm';
*
* const lswitch = sm`on 'toggle' <=> 'toggle' off;`;
*
* lswitch.list_edges();
* [
* {
* from: 'on',
* to: 'off',
* kind: 'main',
* forced_only: false,
* main_path: true,
* action: 'toggle'
* },
* {
* from: 'off',
* to: 'on',
* kind: 'main',
* forced_only: false,
* main_path: true,
* action: 'toggle'
* }
* ]
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
list_edges(): Array<JssmTransition<StateType, mDT>>;
list_named_transitions(): Map<StateType, number>;
list_actions(): Array<StateType>;
get uses_actions(): boolean;
get uses_forced_transitions(): boolean;
/*********
*
* Check if the code that built the machine allows overriding state and data.
*
*/
get code_allows_override(): JssmAllowsOverride;
/*********
*
* Check if the machine config allows overriding state and data.
*
*/
get config_allows_override(): JssmAllowsOverride;
/*********
*
* Check if a machine allows overriding state and data.
*
*/
get allows_override(): JssmAllowsOverride;
all_themes(): FslTheme[];
get themes(): FslTheme | FslTheme[];
set themes(to: FslTheme | FslTheme[]);
flow(): FslDirection;
get_transition_by_state_names(from: StateType, to: StateType): number;
lookup_transition_for(from: StateType, to: StateType): JssmTransition<StateType, mDT>;
/********
*
* List all transitions attached to the current state, sorted by entrance and
* exit. The order of each sublist is not defined. A node could appear in
* both lists.
*
* ```typescript
* import { sm } from 'jssm';
*
* const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
*
* light.state(); // 'red'
* light.list_transitions(); // { entrances: [ 'yellow', 'off' ], exits: [ 'green', 'off' ] }
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The state whose transitions to have listed
*
*/
list_transitions(whichState?: StateType): JssmTransitionList;
/********
*
* List all entrances attached to the current state. Please note that the
* order of the list is not defined. This list includes both unforced and
* forced entrances; if this isn't desired, consider
* {@link list_unforced_entrances} or {@link list_forced_entrances} as
* appropriate.
*
* ```typescript
* import { sm } from 'jssm';
*
* const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
*
* light.state(); // 'red'
* light.list_entrances(); // [ 'yellow', 'off' ]
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The state whose entrances to have listed
*
*/
list_entrances(whichState?: StateType): Array<StateType>;
/********
*
* List all exits attached to the current state. Please note that the order
* of the list is not defined. This list includes both unforced and forced
* exits; if this isn't desired, consider {@link list_unforced_exits} or
* {@link list_forced_exits} as appropriate.
*
* ```typescript
* import { sm } from 'jssm';
*
* const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
*
* light.state(); // 'red'
* light.list_exits(); // [ 'green', 'off' ]
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The state whose exits to have listed
*
*/
list_exits(whichState?: StateType): Array<StateType>;
probable_exits_for(whichState: StateType): Array<JssmTransition<StateType, mDT>>;
probabilistic_transition(): boolean;
probabilistic_walk(n: number): Array<StateType>;
probabilistic_histo_walk(n: number): Map<StateType, number>;
/********
*
* List all actions available from this state. Please note that the order of
* the actions is not guaranteed.
*
* ```typescript
* import { sm } from 'jssm';
*
* const machine = sm`
* red 'next' -> green 'next' -> yellow 'next' -> red;
* [red yellow green] 'shutdown' ~> off 'start' -> red;
* `;
*
* console.log( machine.state() ); // logs 'red'
* console.log( machine.actions() ); // logs ['next', 'shutdown']
*
* machine.action('next'); // true
* console.log( machine.state() ); // logs 'green'
* console.log( machine.actions() ); // logs ['next', 'shutdown']
*
* machine.action('shutdown'); // true
* console.log( machine.state() ); // logs 'off'
* console.log( machine.actions() ); // logs ['start']
*
* machine.action('start'); // true
* console.log( machine.state() ); // logs 'red'
* console.log( machine.actions() ); // logs ['next', 'shutdown']
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The state whose actions to have listed
*
*/
actions(whichState?: StateType): Array<StateType>;
/********
*
* List all states that have a specific action attached. Please note that
* the order of the states is not guaranteed.
*
* ```typescript
* import { sm } from 'jssm';
*
* const machine = sm`
* red 'next' -> green 'next' -> yellow 'next' -> red;
* [red yellow green] 'shutdown' ~> off 'start' -> red;
* `;
*
* console.log( machine.list_states_having_action('next') ); // ['red', 'green', 'yellow']
* console.log( machine.list_states_having_action('start') ); // ['off']
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param whichState The action to be checked for associated states
*
*/
list_states_having_action(whichState: StateType): Array<StateType>;
list_exit_actions(whichState?: StateType): Array<StateType>;
probable_action_exits(whichState?: StateType): Array<any>;
is_unenterable(whichState: StateType): boolean;
has_unenterables(): boolean;
is_terminal(): boolean;
state_is_terminal(whichState: StateType): boolean;
has_terminals(): boolean;
is_complete(): boolean;
state_is_complete(whichState: StateType): boolean;
has_completes(): boolean;
set_hook(HookDesc: HookDescription<mDT>): void;
hook(from: string, to: string, handler: HookHandler<mDT>): Machine<mDT>;
hook_action(from: string, to: string, action: string, handler: HookHandler<mDT>): Machine<mDT>;
hook_global_action(action: string, handler: HookHandler<mDT>): Machine<mDT>;
hook_any_action(handler: HookHandler<mDT>): Machine<mDT>;
hook_standard_transition(handler: HookHandler<mDT>): Machine<mDT>;
hook_main_transition(handler: HookHandler<mDT>): Machine<mDT>;
hook_forced_transition(handler: HookHandler<mDT>): Machine<mDT>;
hook_any_transition(handler: HookHandler<mDT>): Machine<mDT>;
hook_entry(to: string, handler: HookHandler<mDT>): Machine<mDT>;
hook_exit(from: string, handler: HookHandler<mDT>): Machine<mDT>;
hook_after(from: string, handler: HookHandler<mDT>): Machine<mDT>;
post_hook(from: string, to: string, handler: HookHandler<mDT>): Machine<mDT>;
post_hook_action(from: string, to: string, action: string, handler: HookHandler<mDT>): Machine<mDT>;
post_hook_global_action(action: string, handler: HookHandler<mDT>): Machine<mDT>;
post_hook_any_action(handler: HookHandler<mDT>): Machine<mDT>;
post_hook_standard_transition(handler: HookHandler<mDT>): Machine<mDT>;
post_hook_main_transition(handler: HookHandler<mDT>): Machine<mDT>;
post_hook_forced_transition(handler: HookHandler<mDT>): Machine<mDT>;
post_hook_any_transition(handler: HookHandler<mDT>): Machine<mDT>;
post_hook_entry(to: string, handler: HookHandler<mDT>): Machine<mDT>;
post_hook_exit(from: string, handler: HookHandler<mDT>): Machine<mDT>;
get rng_seed(): number;
set rng_seed(to: number | undefined);
edges_between(from: string, to: string): JssmTransition<StateType, mDT>[];
/*********
*
* Replace the current state and data with no regard to the graph.
*
* ```typescript
* import { sm } from 'jssm';
*
* const machine = sm`a -> b -> c;`;
* console.log( machine.state() ); // 'a'
*
* machine.go('b');
* machine.go('c');
* console.log( machine.state() ); // 'c'
*
* machine.override('a');
* console.log( machine.state() ); // 'a'
* ```
*
*/
override(newState: StateType, newData?: mDT | undefined): void;
transition_impl(newStateOrAction: StateType, newData: mDT | undefined, wasForced: boolean, wasAction: boolean): boolean;
auto_set_state_timeout(): void;
/*********
*
* Get a truncated history of the recent states and data of the machine.
* Turned off by default; configure with `.from('...', {data: 5})` by length,
* or set `.history_length` at runtime.
*
* History *does not contain the current state*. If you want that, call
* `.history_inclusive` instead.
*
* ```typescript
* const foo = jssm.from(
* "a 'next' -> b 'next' -> c 'next' -> d 'next' -> e;",
* { history: 3 }
* );
*
* foo.action('next');
* foo.action('next');
* foo.action('next');
* foo.action('next');
*
* foo.history; // [ ['b',undefined], ['c',undefined], ['d',undefined] ]
* ```
*
* Notice that the machine's current state, `e`, is not in the returned list.
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get history(): [string, mDT][];
/*********
*
* Get a truncated history of the recent states and data of the machine,
* including the current state. Turned off by default; configure with
* `.from('...', {data: 5})` by length, or set `.history_length` at runtime.
*
* History inclusive contains the current state. If you only want past
* states, call `.history` instead.
*
* The list returned will be one longer than the history buffer kept, as the
* history buffer kept gets the current state added to it to produce this
* list.
*
* ```typescript
* const foo = jssm.from(
* "a 'next' -> b 'next' -> c 'next' -> d 'next' -> e;",
* { history: 3 }
* );
*
* foo.action('next');
* foo.action('next');
* foo.action('next');
* foo.action('next');
*
* foo.history_inclusive; // [ ['b',undefined], ['c',undefined], ['d',undefined], ['e',undefined] ]
* ```
*
* Notice that the machine's current state, `e`, is in the returned list.
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get history_inclusive(): [string, mDT][];
/*********
*
* Find out how long a history this machine is keeping. Defaults to zero.
* Settable directly.
*
* ```typescript
* const foo = jssm.from("a -> b;");
* foo.history_length; // 0
*
* const bar = jssm.from("a -> b;", { history: 3 });
* foo.history_length; // 3
* foo.history_length = 5;
* foo.history_length; // 5
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get history_length(): number;
set history_length(to: number);
/********
*
* Instruct the machine to complete an action. Synonym for {@link do}.
*
* ```typescript
* const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
*
* light.state(); // 'red'
* light.action('next'); // true
* light.state(); // 'green'
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param actionName The action to engage
*
* @param newData The data change to insert during the action
*
*/
action(actionName: StateType, newData?: mDT): boolean;
/********
*
* Get the standard style for a single state. ***Does not*** include
* composition from an applied theme, or things from the underlying base
* stylesheet; only the modifications applied by this machine.
*
* ```typescript
* const light = sm`a -> b;`;
* console.log(light.standard_state_style);
* // {}
*
* const light = sm`a -> b; state: { shape: circle; };`;
* console.log(light.standard_state_style);
* // { shape: 'circle' }
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get standard_state_style(): JssmStateConfig;
/********
*
* Get the hooked state style. ***Does not*** include
* composition from an applied theme, or things from the underlying base
* stylesheet; only the modifications applied by this machine.
*
* The hooked style is only applied to nodes which have a named hook in the
* graph. Open hooks set through the external API aren't graphed, because
* that would be literally every node.
*
* ```typescript
* const light = sm`a -> b;`;
* console.log(light.hooked_state_style);
* // {}
*
* const light = sm`a -> b; hooked_state: { shape: circle; };`;
* console.log(light.hooked_state_style);
* // { shape: 'circle' }
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get hooked_state_style(): JssmStateConfig;
/********
*
* Get the start state style. ***Does not*** include composition from an
* applied theme, or things from the underlying base stylesheet; only the
* modifications applied by this machine.
*
* Start states are defined by the directive `start_states`, or in absentia,
* are the first mentioned state.
*
* ```typescript
* const light = sm`a -> b;`;
* console.log(light.start_state_style);
* // {}
*
* const light = sm`a -> b; start_state: { shape: circle; };`;
* console.log(light.start_state_style);
* // { shape: 'circle' }
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get start_state_style(): JssmStateConfig;
/********
*
* Get the end state style. ***Does not*** include
* composition from an applied theme, or things from the underlying base
* stylesheet; only the modifications applied by this machine.
*
* End states are defined in the directive `end_states`, and are distinct
* from terminal states. End states are voluntary successful endpoints for a
* process. Terminal states are states that cannot be exited. By example,
* most error states are terminal states, but not end states. Also, since
* some end states can be exited and are determined by hooks, such as
* recursive or iterative nodes, there is such a thing as an end state that
* is not a terminal state.
*
* ```typescript
* const light = sm`a -> b;`;
* console.log(light.standard_state_style);
* // {}
*
* const light = sm`a -> b; end_state: { shape: circle; };`;
* console.log(light.standard_state_style);
* // { shape: 'circle' }
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get end_state_style(): JssmStateConfig;
/********
*
* Get the terminal state style. ***Does not*** include
* composition from an applied theme, or things from the underlying base
* stylesheet; only the modifications applied by this machine.
*
* Terminal state styles are automatically determined by the machine. Any
* state without a valid exit transition is terminal.
*
* ```typescript
* const light = sm`a -> b;`;
* console.log(light.terminal_state_style);
* // {}
*
* const light = sm`a -> b; terminal_state: { shape: circle; };`;
* console.log(light.terminal_state_style);
* // { shape: 'circle' }
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get terminal_state_style(): JssmStateConfig;
/********
*
* Get the style for the active state. ***Does not*** include
* composition from an applied theme, or things from the underlying base
* stylesheet; only the modifications applied by this machine.
*
* ```typescript
* const light = sm`a -> b;`;
* console.log(light.active_state_style);
* // {}
*
* const light = sm`a -> b; active_state: { shape: circle; };`;
* console.log(light.active_state_style);
* // { shape: 'circle' }
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
get active_state_style(): JssmStateConfig;
/********
*
* Gets the composite style for a specific node by individually imposing the
* style layers on a given object, after determining which layers are
* appropriate.
*
* The order of composition is base, then theme, then user content. Each
* item in the stack will be composited independently. First, the base state
* style, then the theme state style, then the user state style.
*
* After the three state styles, we'll composite the hooked styles; then the
* terminal styles; then the start styles; then the end styles; finally, the
* active styles. Remember, last wins.
*
* The base state style must exist. All other styles are optional.
*
* @typeparam mDT The type of the machine data member; usually omitted
*
*/
style_for(state: StateType): JssmStateConfig;
/********
*
* Instruct the machine to complete an action. Synonym for {@link action}.
*
* ```typescript
* const light = sm`
* off 'start' -> red;
* red 'next' -> green 'next' -> yellow 'next' -> red;
* [red yellow green] 'shutdown' ~> off;
* `;
*
* light.state(); // 'off'
* light.do('start'); // true
* light.state(); // 'red'
* light.do('next'); // true
* light.state(); // 'green'
* light.do('next'); // true
* light.state(); // 'yellow'
* light.do('dance'); // !! false - no such action
* light.state(); // 'yellow'
* light.do('start'); // !! false - yellow does not have the action start
* light.state(); // 'yellow'
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param actionName The action to engage
*
* @param newData The data change to insert during the action
*
*/
do(actionName: StateType, newData?: mDT): boolean;
/********
*
* Instruct the machine to complete a transition. Synonym for {@link go}.
*
* ```typescript
* const light = sm`
* off 'start' -> red;
* red 'next' -> green 'next' -> yellow 'next' -> red;
* [red yellow green] 'shutdown' ~> off;
* `;
*
* light.state(); // 'off'
* light.go('red'); // true
* light.state(); // 'red'
* light.go('green'); // true
* light.state(); // 'green'
* light.go('blue'); // !! false - no such state
* light.state(); // 'green'
* light.go('red'); // !! false - green may not go directly to red, only to yellow
* light.state(); // 'green'
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param newState The state to switch to
*
* @param newData The data change to insert during the transition
*
*/
transition(newState: StateType, newData?: mDT): boolean;
/********
*
* Instruct the machine to complete a transition. Synonym for {@link transition}.
*
* ```typescript
* const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
*
* light.state(); // 'red'
* light.go('green'); // true
* light.state(); // 'green'
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param newState The state to switch to
*
* @param newData The data change to insert during the transition
*
*/
go(newState: StateType, newData?: mDT): boolean;
/********
*
* Instruct the machine to complete a forced transition (which will reject if
* called with a normal {@link transition} call.)
*
* ```typescript
* const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
*
* light.state(); // 'red'
* light.transition('off'); // false
* light.state(); // 'red'
* light.force_transition('off'); // true
* light.state(); // 'off'
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param newState The state to switch to
*
* @param newData The data change to insert during the transition
*
*/
force_transition(newState: StateType, newData?: mDT): boolean;
current_action_for(action: StateType): number;
current_action_edge_for(action: StateType): JssmTransition<StateType, mDT>;
valid_action(action: StateType, _newData?: mDT): boolean;
valid_transition(newState: StateType, _newData?: mDT): boolean;
valid_force_transition(newState: StateType, _newData?: mDT): boolean;
instance_name(): string | undefined;
get creation_date(): Date;
get creation_timestamp(): number;
get create_start_time(): number;
set_state_timeout(next_state: StateType, after_time: number): void;
clear_state_timeout(): void;
state_timeout_for(which_state: StateType): [StateType, number] | undefined;
current_state_timeout(): [StateType, number] | undefined;
sm(template_strings: TemplateStringsArray, ...remainder: any[]): Machine<mDT>;
}
/*********
*
* Create a state machine from a template string. This is one of the two main
* paths for working with JSSM, alongside {@link 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.
*
*
* ```typescript
* import * as jssm from 'jssm';
*
* const lswitch = jssm.from('on <=> off;');
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param template_strings The assembled code
*
* @param remainder The mechanic for template argument insertion
*
*/
declare function sm<mDT>(template_strings: TemplateStringsArray, ...remainder: any[]): Machine<mDT>;
/*********
*
* Create a state machine from an implementation string. This is one of the
* two main paths for working with JSSM, alongside {@link 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.
*
* ```typescript
* import * as jssm from 'jssm';
*
* const lswitch = jssm.from('on <=> off;');
* ```
*
* @typeparam mDT The type of the machine data member; usually omitted
*
* @param MachineAsString The FSL code to evaluate
*
* @param ExtraConstructorFields Extra non-code configuration to pass at creation time
*
*/
declare function from<mDT>(MachineAsString: string, ExtraConstructorFields?: Partial<JssmGenericConfig<StateType, mDT>> | undefined): Machine<mDT>;
declare function is_hook_complex_result<mDT>(hr: unknown): hr is HookComplexResult<mDT>;
declare function is_hook_rejection<mDT>(hr: HookResult<mDT>): boolean;
declare function abstract_hook_step<mDT>(maybe_hook: HookHandler<mDT> | undefined, hook_args: HookContext<mDT>): HookComplexResult<mDT>;
declare function deserialize<mDT>(machine_string: string, ser: JssmSerialization<mDT>): Machine<mDT>;
export { version, build_time, transfer_state_properties, Machine, deserialize, make, wrap_parse as parse, compile, sm, from, arrow_direction, arrow_left_kind, arrow_right_kind, seq, unique, find_repeated, weighted_rand_select, histograph, weighted_sample_select, weighted_histo_key, sleep, constants, shapes, gviz_shapes, named_colors, is_hook_rejection, is_hook_complex_result, abstract_hook_step, state_style_condense, FslDirections };