# gen-statem

> StateM ======

Latest version **1.3.1** (published 2018-10-24) · MIT license · 0 weekly downloads

## Install

```sh
npm install gen-statem
pnpm add gen-statem
yarn add gen-statem
bun add gen-statem
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.3.1 |
| Published | 2018-10-24 |
| First published | 2018-09-24 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 9 |
| Unpacked size | 1.1 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 23 |
| Author | Venkat Peri |
| Maintainers | venkatperi |

## Links

- npm: https://www.npmjs.com/package/gen-statem
- Repository: https://github.com/venkatperi/statem
- Homepage: https://github.com/venkatperi/statem#readme
- Issues: https://github.com/venkatperi/statem/issues
- npm.io page: https://npm.io/package/gen-statem

## Dependencies (9)

- [wtlog](https://npm.io/package/wtlog.md) ^1.0.0
- [ntimer](https://npm.io/package/ntimer.md) ^0.5.3
- [uniqid](https://npm.io/package/uniqid.md) ^5.0.3
- [emittery](https://npm.io/package/emittery.md) ^0.4.1
- [p-timeout](https://npm.io/package/p-timeout.md) ^2.0.1
- [route-parser](https://npm.io/package/route-parser.md) 0.0.5
- [object-inspect](https://npm.io/package/object-inspect.md) ^1.6.0
- [immutability-helper](https://npm.io/package/immutability-helper.md) ^2.8.1
- [stablepriorityqueue](https://npm.io/package/stablepriorityqueue.md) ^0.1.0

## Recent versions

- 1.3.1 (latest) — 2018-10-24
- 1.3.0 — 2018-10-11
- 1.2.7 — 2018-10-09
- 1.2.6 — 2018-10-09
- 1.2.5 — 2018-10-09
- 1.2.4 — 2018-10-09
- 1.2.3 — 2018-10-06
- 1.2.2 — 2018-10-06
- 1.2.1 — 2018-10-05
- 1.2.0 — 2018-10-05
- 1.1.0 — 2018-10-02
- 1.0.5 — 2018-09-29
- 1.0.4 — 2018-09-29
- 1.0.3 — 2018-09-28
- 1.0.2 — 2018-09-28
- … 2 more at https://npm.io/package/gen-statem/versions

## README

StateM
======

Introduction
------------

StateM is framework for Javascript state machines.

> StateM is largely based on Erlang OTP’s [gen_statem](http://erlang.org/doc/design_principles/statem.html "gen_statem") behavior.

[![](https://img.shields.io/badge/demo-online-green.svg)](https://hotel-safe.netlify.com/#/)

State machines are ideal for programming tasks that involve a) a sequence of operations and b) logic that dictates which operation will be executed after the current one based, for example, on:

*   data you’re managing
*   inputs from the user
*   responses from pending tasks
*   timeouts

Typically, state machine implementations are structured as forest of trees, with:

*   states as root nodes,
*   inputs/transitions as intermediate nodes,
*   handlers and actions as leaf nodes. Inputs are handled by walking down the tree from the root of node of current state.

> Note: A tree specification can grow very quickly as the number of states and events increase.

In contrast, StateM uses:

*   A flat list with composite keys of `event + state`;
*   Pattern matching on keys collapses the search space.

In StateM, state machines are specified as an ordered list of handlers keyed by `Event x State` patterns. Events drive the state machine and are externally triggered or internally generated by the state machine. Pending events are tracked on a priority queue that preserves entry order. State machines can hold arbitrary [data](#) which is provided to, and can be mutated by, its event handlers.

Features
--------

*   **Co-located code**: Event, states, transitions and actions in one place.
*   **Inserted Events**: Insert events from within the specification.
*   **State Entry Events**: Automatically generates Entry events on state change.
*   **Timeouts**: Install timeouts for state transitions, new events, or just plain timeouts.

Installation
------------

Install with `npm`:

```bash
npm install --save gen-statem
```

Usage
-----

State machines implement the [`IStateMachine`](docs/interfaces/istatemachine.md) interface.

### Create a StateMachine

You can create a state machine by calling `StateMachine's` constructor and passing it a list of handlers, the initial state and optional data.

> Note: The state machine’s data type `TData` is a type argument (`StateMachine<TData>`).

For example, the state machine below toggles states `ONE` and `TWO` on event `next`. ![](https://documents.lucidchart.com/documents/eef39cb2-9656-4c52-88d8-eb6c9f6a5cec/pages/YGcM5DNywbTK?a=1152&x=85&y=151&w=360&h=181&store=1&accept=image/*&auth=LCA%20a77efaa9c861072b1008c96fd065a7b008f5aa33-ts=1538363749)

```ts
let sm = new StateMachine<void>({
    handlers: [
        ['cast#next#ONE', 'TWO'],
        ['cast#next#TWO', () => nextState('ONE')],
    ],
    initialState: "ONE",
})

sm.startSM()

sm.on('stateChanged', (state, old, data, event) => {
    console.log(`${old} --> ${state} on ${event ? event.toString() : ''}`)
})

sm.cast('next')
// ONE --> TWO on Cast@Low { context: 'next' }

sm.cast('next')
// TWO --> ONE on Cast@Low { context: 'next' }
```

### Subclassing StateMachine

Extending the `StateMachine` class lets you:

*   Declare and implement a public API for your state machine (and wrap call/cast dispatch calls).
*   Provide helper functions.

> Note: Handler functions are called with `this` set to the state machine instance.

```ts
class PingPong extends StateMachine<void> {
    handlers: Handlers<void> = [
        ['cast#next#ONE', 'TWO'],
        ['cast#next#TWO', 'ONE'],
    ]

    initialState = "ONE"

    // Define our public API
    next() {
        this.cast('next')
    }
}

let sm = new PingPong()
sm.startSM()

sm.on('stateChanged', (state, old, data, event) => {
    console.log(`${old} --> ${state} on ${event ? event.toString() : ''}`)
})

sm.next()
// ONE --> TWO on Cast@Low { context: 'next' }

sm.next()
// TWO --> ONE on Cast@Low { context: 'next' }
```

### In the Browser

Fetch it from npm via unpkg:

```html
<script src="https://unpkg.com/gen-statem/dist/umd/gen-statem.js"></script>
```

### React State Management

StateM accepts a `DataProxy` object to synchronize its internal data with external objects such as React components.

> Terminology: State machine data == React component state

```js
class App extends React.Component {

  constructor() {
    this.sm = new StateMachine( {
      dataProxy: {
        get: () => this.state,
        set: ( data, state ) => this.setState( { ...data, currentState: state } ),
      },
    } )
  }
}
```

Details
-------

### Routes

StateM uses the url path to parameterized route matching seen in [express](www.expressjs.com) et. al.

#### Current Event Routes

The current event and current state are mapped to a route string as:

```
<current event>#<event context>#<current state>
```

For example:

Event

Event Context

Current State

Route

cast

`"flip"`

off

`"cast#flip#off"`

cast

`{button: 2}`

locked

`"cast#button/2#off"`

call

`"getInfo"`

one

`"call/internalId#getInfo/2#one"`

#### Event Handler Routes

In addition to string literals, handler routes can include:

*   Parameter capture patterns (`:param`) capture up to the next `/`, `#` or the end of the route.
*   Splats (`*param`) capture from up to `#` or the end of the route.
*   Parts of the route can be marked optional by wrapping in parenthesis. Optional parts can include parameter capture and splats.

For example:

*   `cast#flip#:state` will match a `cast(flip)` event in any state and provide the current state as an argument (`args.param`) to the handler.
*   `call/:from#getInfo#:state` will capture the callerId and state as `args.from` and `args.state` respectively.
*   `"cast#button/:digit#locked` will capture a button press in the `locked` state and provide the digit value in `args.digit`.
*   `"cast#*context#open` intercepts any `cast` events in state `open` regardless of the parameters passed when cast was invoked (note: the splat will be available as `args.context`).

### Event Handlers

A key part of a state machine specification is the list of (route, handler) tuples:

```
(string | Array<string>, function | string | [string, string | number])
```

> Note: Event handlers are specified as an array to preserve order (vs. objects, where property[iteration order](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in#Deleted_added_or_modified_properties) is arbitrary).

#### Multiple Routes to a Handler

When a route is specified as an array, it is treated as a boolean OR, i.e. if any route matches an incoming event route, the corresponding handler is invoked.

#### Handler Functions

Handler functions receive the following:

```ts
type HandlerOpts<TData> = {
    args: { [k in string]: string },
    current: State,
    data: TData,
    event: Event,
    route: string
}
```

*   `current`: the state machine’s current state.
*   `data`: the state machine’s current data.
*   `args`: any arguments or splats parsed from the incoming event’s route.
*   `event`: the actual incoming event.
*   `route`: the event’s route.

Handler functions can return:

*   `ResultBuilder` a fluent builder for `Results`.
*   `Result` \- verbose, not recommended.
*   `void` \- interpreted as `keepStateAndData`

#### `string` Handlers

Instead of a handler function, you can provide a

*   `state: string` \- interpreted as a next state directive.
*   `[state: string, timeout: string | number]` \- interpreted as a next state directive and event timeout.

### Result Builder

StateM provides a fluent interface (`ResultBuilder`) for specifying state transitions and actions in handler functions.

The following functions return a `ResultBuilder`:

*   [keepState](#): Instructs the state machine to keep the current state (i.e. transition to the same state). Does not emit a state entry event.
*   [repeatState](#): Like `keepState`, but emits a state entry event.
*   [nextState(state)](#): Instructs the state machine to transition to the given `state` (can be the current state).

#### ResultBuilder Methods

`ResultBuilders` provide the following chainable methods:

*   [data(spec)](#): Instructs the state machine to mutate state data with the given `spec`.
*   [eventTimeout(time)](#): Starts the event timer which may result in a `EventTimeoutEvent` event if a new event is not received.
*   [stateTimeout(time)](#): Starts the state timer which may result in a `StateTimeoutEvent` event if a state transition does not occur.
*   [timeout(time, name)](#): Starts a generic timer with an optional name which may result in a `GenericTimeoutEvent`. Calling `timeout(name)` will cancel the event if it has not yet fired.
*   [nextEvent(type, context, extra)](#): Inserts an event of the given type at the front of the queue so that it is executed before pending events.
*   [internalEvent(context, extra)](#): Like `nextEvent`, this method inserts an `InternalEvent` event.
*   [postpone](#): Instructs the state machine to postpone the current until the state changes at which point any postponed events are delivered before pending events.
*   [reply(from, msg)](#): Instructs the state machine to reply to the sender with id `from`; the result of a prior invocation of `call`.

### Mutating State Machine Data

State machine data is mutated by calling the `data` on `ResultBuilder` with [immutability-helper](#) commands, including:

*   `{$push: array}` `push()` all the items in `array` on the target.
    *   `{$unshift: array}` `unshift()` all the items in `array` on the target.
    *   `{$splice: array of arrays}` for each item in `arrays` call `splice()` on the target with the parameters provided by the item. Note: The items in the array are applied sequentially, so the order matters. The indices of the target may change during the operation.* * `{$set: any}` replace the target entirely.
    *   `{$toggle: array of strings}` toggles a list of boolean fields from the target object.
    *   `{$unset: array of strings}` remove the list of keys in `array` from the target object.
    *   `{$merge: object}` merge the keys of `object` with the target.
    *   `{$apply: function}` passes in the current value to the function and updates it with the new returned value.
    *   `{$add: array of objects}` add a value to a `Map` or `Set`. When adding to a `Set` you pass in an array of objects to add, when adding to a Map, you pass in `[key, value]` arrays like so: `update(myMap, {$add: [['foo', 'bar'], ['baz', 'boo']]})`
    *   `{$remove: array of strings}` remove the list of keys in array from a `Map` or `Set`.

Event Types
===========

*   [CallEvent](docs/classes/callevent.md): Sends a event of type `call` to the state machine and returns a pending Promise.
    *   Call `call(context, extra)` to emit.
    *   Event handlers can reply with `reply()` action which resolves the pending Promise returned by `call()`.
    *   Internally, call generates a `from` id to identify the caller.
    *   The event route for call is: `call/<from>#<context>#<state>`.
*   [CastEvent](docs/classes/castevent.md): Sends a event of type `cast` to the state machine and returns without waiting for a result.
    *   Call `cast(context, extra)` to emit.
    *   The event route for cast is: `cast#<context>#<state>`.
*   [EnterEvent](docs/classes/enterevent.md): Sends a `enter` event to the state machine.
    *   Internally generated by the state machine on a state transition. If the state machine is transitioning to the same state, `enter` is emitted if the previous event handler returns `repeatState` (and not for either of `keepState`, or `nextState(same state)`).
*   [EventTimeoutEvent](docs/classes/eventtimeoutevent.md): Sends a `eventTimeout` event to the state machine.
    *   Internally generated by the state machine when the eventTimeout timer fires.
    *   The eventTimeout timer is started by invoking `eventTimeout(timeout)` in a event handler.
    *   The event route for `eventTimeout` is: `eventTimeout#<context>#<state>`.
    *   Can be cancelled by calling `eventTimeout()` without a timeout argument from an event handler.
*   [GenericTimeoutEvent](docs/classes/generictimeoutevent.md): Sends a `genericTimeout` event to the state machine.
    *   Internally generated by the state machine when the (optionally named) genericTimeout timer fires.
    *   A genericTimeout timer is started by invoking `genericTimeout(timeout [, name])` in a event handler.
    *   The event route for `genericTimeout` is: `genericTimeout#<context>#<state>`.
    *   Can be cancelled by calling `genericTimeout([name])` without a timeout argument from an event handler.
*   [StateTimeoutEvent](docs/classes/statetimeoutevent.md): Sends a `stateTimeout` event to the state machine.
    *   Internally generated by the state machine when the stateTimeout timer fires.
    *   The stateTimeout timer is started by invoking `stateTimeout(timeout)` in a event handler.
    *   The event route for `stateTimeout` is: `stateTimeout#<context>#<state>`.
    *   Can be cancelled by calling `stateTimeout()` without arguments from an event handler.
*   [InternalEvent](docs/classes/internalevent.md): Sends a `internal` event to the state machine. This is a deliberately named event to let the state machine know that the event is internal.
    *   Internally generated by invoking `internal(context, extra)` from a event handler.
    *   The event route for `internal` is: `internal#<context>#<state>`.

Processing Events
-----------------

The state machine looks for the first event handler whose key matches the `incoming event x current state`, or, a catch-all handler.

The matched handler is invoked with the incoming event, route matching arguments, the current state machine state and data.

The result of the handler invocation can include a state transition directive and transition actions, which are immediately executed, potentially changing the state machine’s state, mutating the internal data as well as the event queue.

Complex State
-------------

Examples
--------

See the `examples` directory for more examples.

### Toggle Button With Count

ToggleButtonCount maintains a counter in the state machine’s data that counts the number of times it turned on.

```ts
type ToggleButtonWithCountData = {
    count: number
}

export class ToggleButtonWithCount
    extends StateMachine<ToggleButtonWithCountData> {
    initialState = 'off'

    handlers: Handlers<ToggleButtonWithCountData> = [
        // if we get 'flip' in 'off', go to 'on'
        // and increment data.count
        ['cast#flip#off', ({data}) => nextState('on')
            .data({count: {$set: data.count + 1}})],

        // flip from on goes back to off.
        ['cast#flip#on', 'off']
    ]

    initialData: ToggleButtonWithCountData = {
        count: 0
    }

    flip() {
        this.cast('flip')
    }
}
```
```ts
let button = new ToggleButton()
button.startSM()

// initial state
console.log(await button.getState())    // 'off'

button.flip()
console.log(await button.getState())    // 'on'

button.flip()
console.log(await button.getState())    // 'off'
```

### Push Button Countdown Timer

PushButtonCountdownTimer turns on when pushed and starts a `genericTimeout`. The button turns off when the timer fires.

```ts
type PushButtonCountdownTimerData = {
    timeout: Timeout
}

class PushButtonCountdownTimer extends StateMachine<PushButtonCountdownTimerData> {
    initialState = 'off'

    handlers: Handlers<PushButtonCountdownTimerData> = [
        // Start a generic timer and go to 'on'
        ['cast#push#off', ({data}) => nextState('on').timeout(data.timeout)],

        // when we get 'genericTimeout' in 'on',
        // go back to 'off'
        ['genericTimeout#*_#on', 'off']
    ]

    constructor(timeout: Timeout) {
        super()
        this.initialData = {timeout}
    }

    push() {
        this.cast('push')
    }
}
```

### A Hotel Safe

See [![](https://img.shields.io/badge/demo-online-green.svg)](https://hotel-safe.netlify.com/#/) `HotelSafe` simulates a type of safe frequently seen in hotel rooms.

*   **Locking the Safe**
    
    *   Press Reset (R). The display will prompt for a new code.
    *   Enter a 4 digit code and then press Lock (L).
    *   The code will flash. The safe is now locked.
*   **Unlocking the Safe**
    
    *   Enter the 4 digit code.
    *   The safe will flash OPENED if the code is correct. The safe is now open.
    *   If the code is incorrect, the display will flash ERROR and the safe will stay locked.

```ts
/**
 * The state machine's data type
 */
type SafeData = {
    code: Array<number>,
    input: Array<number>,
    timeout: Timeout,
    codeSize: number,
    message?: string
}

export default class HotelSafe extends StateMachine<SafeData> {
    handlers: Handlers<SafeData> = [

        // Clear data when safe enters OPEN
        ['enter#*_#open', () => keepState().data({
            code: {$set: []},
            input: {$set: []},
            message: {$set: 'Open'},
        })],

        // User pressed RESET -- get new code
        ['cast#reset#open', () => nextState('open/locking').data({
            message: {$set: 'Enter Code'},
        })],

        // Track the last {codeSize} digits.
        // show code on display. Repeat state for setting timeout
        ['cast#button/:digit#open/locking', ({args, data}) => {
            let code = pushFixed(Number(args.digit), data.code, data.codeSize)
            return repeatState().data({
                code: {$set: code},
                message: {$set: code.join('')},
            })
        }],

        // User pressed LOCK. CLose safe if code is long enough
        // else, repeat state (sets timeout on reentry)
        ['cast#lock#open/locking', ({data}) =>
            data.code.length !== data.codeSize ?
            repeatState() :
            nextState('closed/success').data({
                message: {$set: `**${data.code.join('')}**`},
            })],

        // Clear input when safe is closed
        ['enter#*_#closed', () => keepState().data({
            input: {$set: []},
            message: {$set: 'Locked'}
        })],

        // Postpone button press and go to closed/unlocking
        ['cast#button/*_#closed', ({}) =>
            nextState('closed/unlocking').postpone()],

        // User entered digit(s).
        // Keep state if code is not long enough
        // OPEN if input matches code
        // go to MESSAGE if code does not match and set a timeout
        ['cast#button/:digit#closed/unlocking', ({args, data}) => {
            let digit = Number(args.digit)
            let input = data.input.concat(digit)

            // code is the correct length. Decision time.
            if (input.length >= data.code.length) {
                let [state, msg] = arrayEqual(data.code, input) ?
                    ['open/success', "Opened"] :
                    ['closed/error', "ERROR"]

                return nextState(state).data({message: {$set: msg}})
            }

            // Not long enough. Keep collecting digits.
            // Show masked code. Repeat state for
            // setting timeout
            return repeatState().data({
                input: {$push: [digit]},
                message: {$set: "*".repeat(input.length)}
            })
        }],

        // These states timeout on inactivity (eventTimeout)
        [['enter#*_#open/locking',
            'enter#*_#closed/unlocking'], ({data}) =>
            keepState().eventTimeout(data.timeout)],

        // these states just timeout
        ['enter#*_#:state/*_', ({data}) =>
            keepState().timeout(data.timeout)],

        // If we timeout in a sub state, go to the base state
        [['genericTimeout#*_#:state/*_',
            'eventTimeout#*_#:state/*_',], ({args}) =>
            nextState(args.state)],
    ]

    initialData: SafeData = {
        code: [],
        codeSize: 4,
        timeout: 200,
        input: [],
    }

    initialState = 'open'

    constructor(timeout: Timeout) {
        super()
        this.initialData.timeout = timeout
    }

    /**
     * Safe Interface. casts 'reset'
     */
    reset() {
        this.cast('reset')
    }

    /**
     * Safe Interface. cast 'lock'
     */
    lock() {
        this.cast('lock')
    }

    /**
     * Safe Interface. send button digit
     * @param digit
     */
    button(digit: number) {
        this.cast({button: digit})
    }
}
```

Here’s the hotel safe’s state diagram. The collection of `open(/*)` states (and likewise, `closed(/*)` states) represents a state machine and the rule of thumb is to implement it in a separate machine. Complex states however, make the job easier for simple hierarchies, as shown above.

![](https://github.com/venkatperi/hotelsafe/blob/master/hotel_safe.svg)

## Index

### Enumerations

* [Priority](enums/priority.md)

### Classes

* [CallEvent](classes/callevent.md)
* [CastEvent](classes/castevent.md)
* [EmitAction](classes/emitaction.md)
* [EnterEvent](classes/enterevent.md)
* [EventTimeoutAction](classes/eventtimeoutaction.md)
* [EventTimeoutEvent](classes/eventtimeoutevent.md)
* [GenericTimeoutAction](classes/generictimeoutaction.md)
* [GenericTimeoutEvent](classes/generictimeoutevent.md)
* [InternalEvent](classes/internalevent.md)
* [KeepState](classes/keepstate.md)
* [KeepStateAndData](classes/keepstateanddata.md)
* [KeepStateBuilder](classes/keepstatebuilder.md)
* [NextEventAction](classes/nexteventaction.md)
* [NextState](classes/nextstate.md)
* [NextStateBuilder](classes/nextstatebuilder.md)
* [NextStateWithData](classes/nextstatewithdata.md)
* [RepeatState](classes/repeatstate.md)
* [RepeatStateAndData](classes/repeatstateanddata.md)
* [RepeatStateBuilder](classes/repeatstatebuilder.md)
* [ReplyAction](classes/replyaction.md)
* [Response](classes/response.md)
* [ResultBuilder](classes/resultbuilder.md)
* [StateMachine](classes/statemachine.md)
* [StateTimeoutAction](classes/statetimeoutaction.md)
* [StateTimeoutEvent](classes/statetimeoutevent.md)
* [Stop](classes/stop.md)

### Interfaces

* [IStateMachine](interfaces/istatemachine.md)
* [SMOptions](interfaces/smoptions.md)

### Type aliases

* [ActionType](#actiontype)
* [AnimOptions](#animoptions)
* [ComplexState](#complexstate)
* [DataProxy](#dataproxy)
* [EventContext](#eventcontext)
* [EventExtra](#eventextra)
* [EventType](#eventtype)
* [From](#from)
* [Handler](#handler)
* [HandlerFn](#handlerfn)
* [HandlerOpts](#handleropts)
* [HandlerResult](#handlerresult)
* [HandlerResult2](#handlerresult2)
* [HandlerRoute](#handlerroute)
* [HandlerSpec](#handlerspec)
* [Handlers](#handlers)
* [NamedPrimitiveObject](#namedprimitiveobject)
* [NextStateWithEventTimeout](#nextstatewitheventtimeout)
* [Primitive](#primitive)
* [PrimitiveObject](#primitiveobject)
* [ResultType](#resulttype)
* [State](#state)
* [Timeout](#timeout)

### Variables

* [Emittery](#emittery)
* [StablePriorityQueue](#stablepriorityqueue)

### Functions

* [data](#data)
* [eventTimeout](#eventtimeout)
* [internalEvent](#internalevent)
* [isPromiseResult](#ispromiseresult)
* [keepState](#keepstate)
* [nextEvent](#nextevent)
* [nextState](#nextstate)
* [repeatState](#repeatstate)
* [reply](#reply)
* [stateTimeout](#statetimeout)
* [timeout](#timeout)

---

## Type aliases

<a id="actiontype"></a>

###  ActionType

**Ƭ ActionType**: * "reply" &#124; "nextEvent" &#124; "postpone" &#124; "stateTimeout" &#124; "eventTimeout" &#124; "genericTimeout" &#124; "emit"
*

Transition actions

___
<a id="animoptions"></a>

###  AnimOptions

**Ƭ AnimOptions**: *`object`*

#### Type declaration

`Optional`  delay:  `undefined` &#124; `number`

Delay between context switches

`Optional`  includeDefault:  `undefined` &#124; `false` &#124; `true`

Include switching when a default handler is involved

___
<a id="complexstate"></a>

###  ComplexState

**Ƭ ComplexState**: * `Array`<`string`> &#124; [NamedPrimitiveObject](#namedprimitiveobject)
*

A complex state. If an object, must have a 'name' key which specifies the base state name.

___
<a id="dataproxy"></a>

###  DataProxy

**Ƭ DataProxy**: *`object`*

#### Type declaration

 get : function
▸ **get**(): `T`

**Returns:** `T`

 set : function
▸ **set**(value: *`T`*, state: *[State](#state)*): `void`

**Parameters:**

| Param | Type |
| ------ | ------ |
| value | `T` |
| state | [State](#state) |

**Returns:** `void`

___
<a id="eventcontext"></a>

###  EventContext

**Ƭ EventContext**: * [Primitive](#primitive) &#124; [PrimitiveObject](#primitiveobject)
*

Events can accept simple arguments of type {Primitive}, or a {PrimitiveObject}

___
<a id="eventextra"></a>

###  EventExtra

**Ƭ EventExtra**: *`any`*

Non {Primitive|PrimitiveObject} arguments to events.

___
<a id="eventtype"></a>

###  EventType

**Ƭ EventType**: * "call" &#124; "cast" &#124; "enter" &#124; "eventTimeout" &#124; "stateTimeout" &#124; "genericTimeout" &#124; "internal"
*

State machine events

___
<a id="from"></a>

###  From

**Ƭ From**: *`string`*

The caller's address for a {CallEvent}

___
<a id="handler"></a>

###  Handler

**Ƭ Handler**: * [HandlerFn](#handlerfn)<`TData`> &#124; [State](#state) &#124; [NextStateWithEventTimeout](#nextstatewitheventtimeout)
*

Route handler. Can be a function, a state or a \[state, event timeout\] tuple

___
<a id="handlerfn"></a>

###  HandlerFn

**Ƭ HandlerFn**: *`function`*

Handler function

#### Type declaration
▸(opts: *[HandlerOpts](#handleropts)<`TData`>*): [HandlerResult2](#handlerresult2)<`TData`>

**Parameters:**

| Param | Type |
| ------ | ------ |
| opts | [HandlerOpts](#handleropts)<`TData`> |

**Returns:** [HandlerResult2](#handlerresult2)<`TData`>

___
<a id="handleropts"></a>

###  HandlerOpts

**Ƭ HandlerOpts**: *`object`*

Values passed to a {Handler}

#### Type declaration

 args: `object`

 current: [State](#state)

 data: `TData`

 event: `Event`

 route: `string`

___
<a id="handlerresult"></a>

###  HandlerResult

**Ƭ HandlerResult**: * `Result` &#124; `ResultWithData`<`TData`> &#124; [ResultBuilder](classes/resultbuilder.md) &#124; `void`
*

Result of a handler invocation. {ResultBuilder.getResult()} is invoked to convert a {ResultBuilder} to a {Result} {void} implies {KeepStateWithData}

___
<a id="handlerresult2"></a>

###  HandlerResult2

**Ƭ HandlerResult2**: * [HandlerResult](#handlerresult)<`TData`> &#124; `Promise`<[HandlerResult](#handlerresult)<`TData`>>
*

___
<a id="handlerroute"></a>

###  HandlerRoute

**Ƭ HandlerRoute**: * `string` &#124; `Array`<`string`>
*

The key of a handler. Can be {string|Array}. If {Array}, the routes are treated as a boolean OR. Any matching route in the array will invoke the handler.

___
<a id="handlerspec"></a>

###  HandlerSpec

**Ƭ HandlerSpec**: * [[HandlerRoute](#handlerroute), [Handler](#handler)<`TData`>] &#124; `object`
*

A {HandlerRoute} to {Handler} entry. Can be a tuple or object with string keys. If an object, the keys are treated as {string} routes.

___
<a id="handlers"></a>

###  Handlers

**Ƭ Handlers**: *`Array`<[HandlerSpec](#handlerspec)<`TData`>>*

List of route handlers

___
<a id="namedprimitiveobject"></a>

###  NamedPrimitiveObject

**Ƭ NamedPrimitiveObject**: *`object`*

Like {PrimitiveObject}, but expects a key 'name'

#### Type declaration

[k: `string`]: [Primitive](#primitive)

 name: `string`

___
<a id="nextstatewitheventtimeout"></a>

###  NextStateWithEventTimeout

**Ƭ NextStateWithEventTimeout**: *[[State](#state), [Timeout](#timeout)]*

Handlers can be specified as a tuple of the next {State} and a {EventTimeout}

___
<a id="primitive"></a>

###  Primitive

**Ƭ Primitive**: * `number` &#124; `string` &#124; `boolean` &#124; `null` &#124; `undefined`
*

Our definition of primitives (doesn't include symbol)

___
<a id="primitiveobject"></a>

###  PrimitiveObject

**Ƭ PrimitiveObject**: *`object`*

Object with string keys and primitive values

#### Type declaration

___
<a id="resulttype"></a>

###  ResultType

**Ƭ ResultType**: * "none" &#124; "keepState" &#124; "keepStateAndData" &#124; "nextState" &#124; "nextStateWithData" &#124; "repeatState" &#124; "repeatStateAndData" &#124; "stop" &#124; "builder"
*

Hander results

___
<a id="state"></a>

###  State

**Ƭ State**: * `string` &#124; [ComplexState](#complexstate)
*

A State in the state machine.

___
<a id="timeout"></a>

###  Timeout

**Ƭ Timeout**: * `number` &#124; `string`
*

Timeout values. Milliseconds if {number}. For string values, see {NTimer}

___

## Variables

<a id="emittery"></a>

### `<Const>` Emittery

**● Emittery**: *`any`* =  require('emittery')

___
<a id="stablepriorityqueue"></a>

### `<Const>` StablePriorityQueue

**● StablePriorityQueue**: *`any`* =  require("stablepriorityqueue")

___

## Functions

<a id="data"></a>

###  data

▸ **data**<`TData`>(spec: *`Spec`<`TData`>*): [ResultBuilder](classes/resultbuilder.md)

Helper to only mutate data

**Type parameters:**

#### TData 
**Parameters:**

| Param | Type | Description |
| ------ | ------ | ------ |
| spec | `Spec`<`TData`> |  - |

**Returns:** [ResultBuilder](classes/resultbuilder.md)

___
<a id="eventtimeout"></a>

###  eventTimeout

▸ **eventTimeout**(time: *[Timeout](#timeout)*): [KeepStateBuilder](classes/keepstatebuilder.md)

Helper function to set the event timeout timer

**Parameters:**

| Param | Type | Description |
| ------ | ------ | ------ |
| time | [Timeout](#timeout) |  - |

**Returns:** [KeepStateBuilder](classes/keepstatebuilder.md)

___
<a id="internalevent"></a>

###  internalEvent

▸ **internalEvent**(context?: *[EventContext](#eventcontext)*, extra?: *[EventExtra](#eventextra)*): [KeepStateBuilder](classes/keepstatebuilder.md)

Helper function to insert an 'internal' event

**Parameters:**

| Param | Type | Description |
| ------ | ------ | ------ |
| `Optional` context | [EventContext](#eventcontext) |  - |
| `Optional` extra | [EventExtra](#eventextra) |  - |

**Returns:** [KeepStateBuilder](classes/keepstatebuilder.md)

___
<a id="ispromiseresult"></a>

###  isPromiseResult

▸ **isPromiseResult**<`TData`>(r: *`any`*): `boolean`

**Type parameters:**

#### TData 
**Parameters:**

| Param | Type |
| ------ | ------ |
| r | `any` |

**Returns:** `boolean`

___
<a id="keepstate"></a>

###  keepState

▸ **keepState**(): [KeepStateBuilder](classes/keepstatebuilder.md)

Returns a [KeepStateBuilder](classes/keepstatebuilder.md)

**Returns:** [KeepStateBuilder](classes/keepstatebuilder.md)

___
<a id="nextevent"></a>

###  nextEvent

▸ **nextEvent**(type: *[EventType](#eventtype)*, context?: *[EventContext](#eventcontext)*, extra?: *[EventExtra](#eventextra)*): [KeepStateBuilder](classes/keepstatebuilder.md)

Helper function to insert a new event

**Parameters:**

| Param | Type | Description |
| ------ | ------ | ------ |
| type | [EventType](#eventtype) |  - |
| `Optional` context | [EventContext](#eventcontext) |  - |
| `Optional` extra | [EventExtra](#eventextra) |  - |

**Returns:** [KeepStateBuilder](classes/keepstatebuilder.md)

___
<a id="nextstate"></a>

###  nextState

▸ **nextState**(state: *[State](#state)*): [NextStateBuilder](classes/nextstatebuilder.md)

Returns a [NextStateBuilder](classes/nextstatebuilder.md)

**Parameters:**

| Param | Type | Description |
| ------ | ------ | ------ |
| state | [State](#state) |  - |

**Returns:** [NextStateBuilder](classes/nextstatebuilder.md)

___
<a id="repeatstate"></a>

###  repeatState

▸ **repeatState**(): [RepeatStateBuilder](classes/repeatstatebuilder.md)

Returns a [RepeatStateBuilder](classes/repeatstatebuilder.md)

**Returns:** [RepeatStateBuilder](classes/repeatstatebuilder.md)

___
<a id="reply"></a>

###  reply

▸ **reply**(from: *`string`*, msg: *`any`*): [KeepStateBuilder](classes/keepstatebuilder.md)

Helper function to return a reply

**Parameters:**

| Param | Type | Description |
| ------ | ------ | ------ |
| from | `string` |  - |
| msg | `any` |  - |

**Returns:** [KeepStateBuilder](classes/keepstatebuilder.md)

___
<a id="statetimeout"></a>

###  stateTimeout

▸ **stateTimeout**(time: *[Timeout](#timeout)*): [KeepStateBuilder](classes/keepstatebuilder.md)

Helper function to set a state timeout (keeps state and data)

**Parameters:**

| Param | Type | Description |
| ------ | ------ | ------ |
| time | [Timeout](#timeout) |  - |

**Returns:** [KeepStateBuilder](classes/keepstatebuilder.md)

___
<a id="timeout"></a>

###  timeout

▸ **timeout**(time: *[Timeout](#timeout)*): [KeepStateBuilder](classes/keepstatebuilder.md)

helper function to set a generic timer

**Parameters:**

| Param | Type | Description |
| ------ | ------ | ------ |
| time | [Timeout](#timeout) |  - |

**Returns:** [KeepStateBuilder](classes/keepstatebuilder.md)

___

---
_Source: https://npm.io/package/gen-statem · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
