statebot ()

Write more robust and understandable programs.

Statebot hopes to make Finite State Machines (FSMs) a little more accessible.

You're reading the documentation. Other exits are:

Statebot was written by Conan Theobald and is MIT licensed.

Jump right in

Play around with an example that uses React in this CodeSandbox.

You can install Statebot into your npm project:

npm i statebot
import statebot from 'statebot'

Or non-npm project:

<script src="https://unpkg.com/statebot@2.7.4/dist/browser/statebot.min.js"></script>
const { Statebot } = statebot
// Make machines with Statebot()

const { isStatebot, routeIsPossible, assertRoute } = statebot
// These are assertion helpers you can use for testing

Open the developer-console :)

I've included Statebot in this page. Open the developer-console to follow along with the examples below:

var machine = Statebot('promise-like', {
  chart: `
    // This one will behave a bit like a Promise
    idle -> pending ->
      resolved | rejected

    // ...and we're done
    resolved -> done
    rejected -> done
  `,
  startIn: 'idle'
})

machine.canTransitionTo('pending')
// true

machine.enter('pending')
machine.statesAvailableFromHere()
// ["resolved", "rejected"]

We can hook-up events with .performTransitions():

machine.performTransitions({
 'pending -> resolved': {
   on: 'data-loaded'
 },
 'pending -> rejected': {
   on: ['timeout', 'data-error'],
   then: (msg) => {
     console.warn('Uh oh...', msg)
   }
 },
 'resolved | rejected -> done': {
   on: 'thats-all-folks'
 }
})

machine.emit('data-error', 'Did you hear that?')

Here's the API:

Hitchers Status Actions
.performTransitions() / .onEvent() .canTransitionTo() / .statesAvailableFromHere() .emit() / .Emit()
.onTransitions() .currentState() / .previousState() / .history() .enter() / .Enter()
.onEntering() / .onEntered() .inState() / .InState() .pause() / .resume()
.onExiting() / .onExited() .info() / .inspect() / .name() .reset()
.onSwitching() / .onSwitched() .paused()

Static Members

Statebot (name, options)

Create a statebotFsm object.

parameter type description
name string Give your Statebot a name. Used for logging and by assertRoute() .
options statebotOptions

Examples

var machine = Statebot('lemming', {
  chart: `
    walking -> (digging | building | falling) ->
      walking

    falling -> splatting
    walking -> exiting
  `
})

isStatebot (object)

Tests that an object is a statebotFsm.

parameter type description
object any The object to test.

Returns

boolean :

Examples

var machine = Statebot(...)

isStatebot(machine)
// true

routeIsPossible (machine, route)

Assert that a certain route can be followed by a statebotFsm.

This merely tests that a certain path can be taken through a state-machine. It doesn't assert that the states are moved-through while the machine is working, as with assertRoute().

parameter type description
machine statebotFsm The machine to test the route on.
route (string | Array<string>) The route to test as an arrow-delimited string:

"idle -> pending -> success -> done"

Returns

boolean :

Examples

var machine = Statebot(...)

routeIsPossible(machine,
  'walking -> falling -> splatting -> walking'
)
// false

assertRoute (machine, expectedRoute, options?)

Assert that a statebotFsm traced the route specified.

Whereas routeIsPossible() only checks that a particular route can be followed, assertRoute will hook-into a machine and wait for it to trace the specified path within a timeout period.

parameter type description
machine statebotFsm The machine to run the assertion on.
expectedRoute (string | Array<string>) The expected route as an arrow-delimited string:

"idle -> pending -> success -> done"

options assertRouteOptions?

Returns

Promise :

Examples

var machine = Statebot(...)

assertRoute(
  machine, 'prepare -> debounce -> sending -> done -> idle',
  {
    description: 'Email sent with no issues',
    fromState: 'idle',
    timeoutInMs: 1000 * 20,
    permittedDeviations: 0,
    logLevel: 3
  }
)
.then(() => console.log('Assertion passed!'))
.catch(err => console.error(`Whoops: ${err}`))

machine.enter('idle')

decomposeChart (chart)

Decompose a statebotChart into an object of states, routes, and transitions.

Statebot() uses this internally to parse charts. Exposed for debugging.

parameter type description
chart statebotChart

Returns

Object :

Examples

var { states, routes, transitions } = decomposeChart`
  pending ->
    success | failure
`
// states = ['pending', 'success', 'failure']
// routes = [ 'pending->success', 'pending->failure']
// transitions = [
//   ['pending', 'success'],
//   ['pending', 'failure']
// ]

statebotOptions ()

Options for creating a Statebot.

Type: Object

property type description
chart statebotChart : The state-chart.
startIn string? : The state in which to start. If unspecified, the first state in the chart will be used.
logLevel number? : How noisy the logging is, from 1 to 3:
1) console.warn
2) console.warn/log/table
3) console.warn/log/table/info

3 is the default. Argument type-errors will always throw.

historyLimit number? : Limit how much history the state-machine keeps. Accessed via statebotFsm#history() .
events events? : If you wish to have your Statebots listen to events coming from a shared EventEmitter, you can pass it in here. The emit() / onEvent() / performTransitions() methods will use it.

It should have the same signature as EventEmitter.

  • Since Statebot 2.5.0 mitt is also compatible.
  • Since Statebot 2.6.0 mitt is used internally.

statebotChart ()

A description of all the states in a machine, plus all of the permitted transitions between them.

This is defined using a string or an array of strings, but Template Literals are much more convenient.

An arrow -> configures a permitted transition between two states:

from-state -> to-state

It's the only operator needed to build any chart:

var promiseLikeChart = `
  pending -> resolved
  pending -> rejected
  resolved -> done
  rejected -> done
`

The "OR" operator | can help us remove some redundancy from the above example:

var promiseLikeChart = `
  pending -> resolved | rejected
  resolved | rejected -> done
`

In both charts, pending can transition to resolved or rejected, and resolved or rejected can both transition to done.

We can streamline this even further:

var promiseLikeChart = `
  pending -> (resolved | rejected) -> done
`

Again, this is exactly equivalent to the previous two examples.

Notice in this one that we have parentheses ( ) surrounding resolved and rejected. They are actually completely ignored by the parser, and you can use them as you please to help make your charts more readable.

A chart works exactly the same without them:

var promiseLikeChart = `
  pending -> resolved | rejected -> done
`

Charts can also be split across multiple-lines:

var promiseLikeChart = `
  pending ->
  resolved |
  rejected ->
  done
`

Notice that all white-space is ignored on either side of the -> and |.

// Comments of this kind are allowed, too:

var promiseLikeChart = `
  pending -> // Where do we go from here?
    (resolved | rejected) -> // Ah, yes

  // And now we're all finished
  done
`

Finally, here's a more full example:

var dragDropChart = `
  idle ->
    drag-detect ->
      (dragging | clicked)

  // Just a click, bail-out!
  clicked -> idle

  // Drag detected!
  dragging ->
    drag-wait -> dragged -> drag-wait

  // Drag finished...
  (drag-wait | dragged) ->
    (drag-done | drag-cancel) ->
      idle
`

Type: (string | Array<string>)

statebotFsm ()

A state-machine object created by Statebot().

Type: Object

Instance Members

canTransitionTo (states)

Tests to see if we can transition to the specified state from the .currentState().

If more than one state is specified, true is returned only if ALL states are available.

parameter type description
states (string | Array<string>)

Returns

boolean :

Examples

var machine = Statebot('game-menus', {
  chart: `
    loading ->
      menu ->
           play |
        options |
          sound |
           quit

    // Go back to menu
    play | options | sound -> menu

    // Can quit from main game, too
    play -> quit
  `
})

machine.canTransitionTo('play')
// false

machine.enter('menu')
machine.canTransitionTo(['play', 'options'])
// true

currentState ()

Returns the current state.

Returns

string :

Examples

var machine = Statebot('coroutine', {
  chart: `
    suspended -> running -> (suspended | dead)
  `
})

machine.currentState()
// "suspended"

emit (eventName, args?)

Immediately emits an event, firing any listeners added using .performTransitions() or .onEvent().

parameter type description
eventName string
args ...any? Optional arguments to pass to listeners.

Returns

boolean : Whether or not the event had listeners.

See: Node Events for more information.

Statebot imports EventEmitter from the events package for dealing with events in the browser.

Since Statebot 2.6.0 mitt is used for both the browser and non-browser builds.

Examples

var machine = Statebot('basic-form', {
  chart: `
    idle -> sending -> redirect
  `
})

machine.performTransitions({
  'idle -> sending': {
    on: 'post-data',
    then: (...args) => {
      console.log('Event args: ', args)
      // setTimeout(machine.Enter('redirect'), 5000)
    }
  }
})

machine.emit('post-data', 'Hello, world!')
// Event args: ["Hello, world!"]

machine.currentState()
// "sending"

Emit (eventName, curriedArgs?)

Creates a function that emits the specified event.

(This is essentially a convenience wrapper around .emit().)

parameter type description
eventName string The desired event to .emit() .
curriedArgs ...any? Arguments that will curry into the returned emit() function whenever it is called.

Returns

function : A function that emits that event.

Examples

var machine = Statebot('traffic-lights', {
  chart: `
    go ->
      prepare-to-stop ->
      stop

    // ...gotta keep that traffic flowing
    stop ->
      prepare-to-go ->
      go
  `,
  startIn: 'stop'
})

machine.performTransitions({
  'stop -> prepare-to-go':   { on: 'timer' },
  'prepare-to-go -> go':     { on: 'timer' },
  'go -> prepare-to-stop':   { on: 'timer' },
  'prepare-to-stop -> stop': { on: 'timer' }
})

var nextTrafficLight = machine.Emit('timer')
machine.currentState()
// "stop"

nextTrafficLight()
nextTrafficLight()
nextTrafficLight()

machine.currentState()
// "prepare-to-stop"

enter (state, args?)

Immediately changes to the specified state, so long as it is accessible from the .currentState().

parameter type description
state string The desired state to switch-to.
args ...any? Optional arguments to pass to transition callbacks.

Returns

boolean : Whether or not the state changed.

Examples

var machine = Statebot('dialog', {
  chart: `
    idle -> showing-modal -> (saving | idle)
      saving -> idle
  `
})

machine.currentState()
// "idle"

machine.enter('saving')
// false

// [dialog]: Invalid transition "idle->saving", not switching
// > Previous transition: "[undefined]->idle"
// > From "idle", valid states are: ["showing-modal"]

machine.enter('showing-modal')
// true

Enter (state, curriedArgs?)

Creates a function that changes to the specified state, so long as it is accessible from the .currentState().

(This is essentially a convenience wrapper around .enter().)

parameter type description
state string The desired state to switch-to.
curriedArgs ...any? Arguments that will curry into the returned enter() function whenever it is called.

Returns

function : A function that can change the state when called.

Examples

var machine = Statebot('popup-menu', {
  chart: `
    idle -> menu-opened ->
      (item-clicked | idle)

    item-clicked -> idle
  `,
  startIn: 'menu-opened'
})

button.onclick = machine.Enter('item-clicked')
machine.currentState()
// "menu-opened"

button.onclick()
machine.currentState()
// "item-clicked"

history ()

Returns all states the machine has been in so far, up to a limit set by historyLimit in statebotOptions.

Returns

Array<string> : A copy of the state-history.

Examples

var machine = Statebot('downloader', {
  chart: `
    loading -> (failure | success)
      failure -> loading
      success -> done
  `,
  historyLimit: 4
})

machine.enter('failure')
machine.enter('loading')
machine.enter('success')
machine.enter('done')
machine.history()
// ["failure", "loading", "success", "done"]

info ()

Print information about the current machine to the console.

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.info()
// [half-duplex]: Information about this state-machine.
// [half-duplex]: Listening for the following state-changes:
// ┌─────────┬─────────────┬────────┐
// │ (index) │   states    │   #    │
// ├─────────┼─────────────┼────────┤
// │    0    │   'done'    │ 'None' │
// │    1    │   'idle'    │ 'None' │
// │    2    │ 'receiving' │ 'None' │
// │    3    │  'sending'  │ 'None' │
// └─────────┴─────────────┴────────┘
// [half-duplex] Listening for the following transitions:
// ┌─────────┬───────────────────┬────────┐
// │ (index) │    transitions    │   #    │
// ├─────────┼───────────────────┼────────┤
// │    0    │ 'idle->receiving' │ 'None' │
// │    1    │  'idle->sending'  │ 'None' │
// │    2    │ 'receiving->done' │ 'None' │
// │    3    │  'sending->done'  │ 'None' │
// └─────────┴───────────────────┴────────┘
// [half-duplex]: Listening for the following events:
// (No information)

inspect ()

Get information about the current machine.

Same details as .info() in object-form.

Returns

object :

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.inspect()
// Will return an object with the following signature:
//  { states, transitions, events }

// These will each have key-values, the key being the name
// and the value being the number of listeners attached.

inState (state, outputWhenTrue?, fnArgs?)

Checks if the .currentState() matches the specified state, immediately returning either true or false.

If outputWhenTrue is specified, then it will be returned instead of true, and null will be returned instead of false.

If a function is specified, then its return-value will be used as the true-value.

Since v2.7.0:

  • An object can be used instead of a string, with the keys being the states, and the values corresponding to their outputWhenTrue value. See the updated example below.
parameter type description
state (string | object) The state to test against. This can be a string if you have a single condition, or an object for multiple. (See example.)
outputWhenTrue (any | function)? When a string is specified as the first argment, this becomes an optional true -value that is returned if the state matches. If a function is specified, it will be called and its return value will be used.
fnArgs ...any? Arguments that will pass into outputWhenTrue() if it has been defined as a function.

Returns

(boolean | null | any) :

Examples

var machine = Statebot('little-revver', {
  chart: `
    idle ->
      (gear-1 | gear-2 | reverse) ->
    idle
  `
})

machine.inState('idle')
// true

machine.inState('idle', 'Purrrr...')
// "Purrrr..."

machine.enter('gear-1')

// Since v2.7.0:
machine.inState({
  'idle': 'Purrrr...',
  'gear-1': () => 'Chugga-chugga-chugga...',
  'gear-2': () => 'Brumma-brumma-brum-brum...',
  'reverse': false,
})
// "Chugga-chugga-chugga..."

machine.inState('idle', () => {
  console.log('Idling!')
  return 'Purrrr...'
})
// null
// ^ the function is not called at all in the `false` case,
//   so no console.log either.

InState (state, outputWhenTrue?, curriedFnArgs?)

Returns a function which, when run, tests that .currentState() matches the specified state, returning either true or false.

If outputWhenTrue is specified, then it will be returned instead of true, and null will be returned instead of false.

(This is essentially a convenience wrapper around .inState().)

parameter type description
state string The state to test against.
outputWhenTrue (any | function)? Optional true -value. If a function is specified, it will be called and its return value will be used.
curriedFnArgs ...any? Arguments that will curry into outputWhenTrue() if it has been defined as a function.

Returns

function : A function that calls .inState() .

Examples

var machine = Statebot('little-revver', {
  chart: `
    idle ->
      (gear-1 | gear-2 | reverse) ->
    idle
  `
})

var idling = machine.InState('idle')
var purring = machine.InState('idle', () => {
  console.log('Idling!')
  return 'Purrrr...'
})

idling()
// true

purring()
// Idling!
// "Purrrr..."

machine.enter('gear-1')
purring()
// null
// ^ the function is not called at all in the `false` case,
//   so no console.log either.

name ()

Returns the name of the state-machine.

Used for logging and also by assertRoute() for the same.

Returns

string : The name of the state-machine.

Examples

var machine = Statebot('Ay, there’s the rub.', {
  chart: `
    the-question -> (to-be | not-to-be)
      not-to-be -> perchance-to-dream
  `
})

machine.name()
// "Ay, there’s the rub."

onEntered (state, cb)

Adds a listener that runs a callback immediately AFTER the specified-state becomes the current one.

A function is returned that will remove the listener.

parameter type description
state string The state.
cb enterCallback A callback function with the signature:

(fromState, ...args?)

Returns

function : A function that removes the listener.

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.onEntered('done', fromState => {
  console.log('Entered from:', fromState)
})

machine.enter('receiving')
machine.enter('done')
// Entered from: receiving

onEntering (state, cb)

Adds a listener that runs a callback immediately BEFORE the specified-state becomes the current one.

A function is returned that will remove the listener.

parameter type description
state string The state.
cb enterCallback A callback function with the signature:

(fromState, ...args?)

Returns

function : A function that removes the listener.

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.onEntered('done', () => {
  console.log('We made it!')
})

machine.onEntering('done', fromState => {
  console.log('Entering from:', fromState)
})

machine.enter('sending')
machine.enter('done')
// Entering from: sending
// We made it!

onEvent (name, cb)

Adds a listener that runs a callback immediately after the specified event is called.

A function is returned that will remove the listener.

parameter type description
name string The event name.
cb function The callback.

Returns

function : A function that removes the listener.

Examples

var machine = Statebot('traffic-lights', {
  chart: `
    go ->
      prepare-to-stop ->
      stop

    // ...gotta keep that traffic flowing
    stop ->
      prepare-to-go ->
      go
  `
})

machine.performTransitions({
  'stop -> prepare-to-go -> go':   { on: 'timer' },
  'go -> prepare-to-stop -> stop': { on: 'timer' },
})

machine.onEvent('timer', () => {
  redrawTrafficLights()
})

setInterval(machine.Emit('timer'), 2000)

onExited (state, cb)

Adds a listener that runs a callback immediately AFTER the specified-state is no longer the current one.

A function is returned that will remove the listener.

parameter type description
state string The state.
cb exitCallback A callback function with the signature:

(toState, ...args?)

Returns

function : A function that removes the listener.

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.onExited('idle', toState => {
  console.log('We are heading to:', toState)
})

machine.enter('sending')
// We are heading to: sending

onExiting (state, cb)

Adds a listener that runs a callback immediately BEFORE the specified-state is no longer the current one.

A function is returned that will remove the listener.

parameter type description
state string The state.
cb exitCallback A callback function with the signature:

(toState, ...args?)

Returns

function : A function that removes the listener.

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.onExited('idle', () => {
  console.log('Peace out!')
})

machine.onExiting('idle', toState => {
  console.log('Heading to:', toState)
})

machine.enter('receiving')
machine.enter('done')
// Heading to: receiving
// Peace out!

onSwitched (cb)

Adds a listener that runs a callback immediately after ANY state-change.

A function is returned that will remove the listener.

parameter type description
cb switchCallback A callback function with the signature:

(toState, fromState, ...args?)

Returns

function : A function that removes the listener.

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.onSwitched((toState, fromState) => {
  console.log(`We went from "${fromState}" to "${toState}"`)
})

machine.enter('receiving')
// We went from "idle" to "receiving"

onSwitching (cb)

Adds a listener that runs a callback immediately before ANY state-change.

A function is returned that will remove the listener.

parameter type description
cb switchCallback A callback function with the signature:

(toState, fromState, ...args?)

Returns

function : A function that removes the listener.

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.onSwitching((toState, fromState) => {
  console.log(`Going from "${fromState}" to "${toState}"`)
})

machine.enter('receiving')
// Going from "idle" to "receiving"

onTransitions (transitions)

Run callbacks when transitions happen.

parameter type description
transitions (object | function) Configuration in the form of an object, or a function that returns an object. If a function is used, there will be a single argument passed-in: an object with the following methods attached as a convenience:

Returns

function : A function that removes all listeners added by this method.

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.onTransitions({
  'idle -> sending': () => {
    sendData()
      .then(machine.Enter('done', 'sent'))
      .catch(machine.Enter('done', 'failed'))
  },
  'idle -> receiving': () => {
    receiveData()
      .then(machine.Enter('done', 'received'))
      .catch(machine.Enter('done', 'failed'))
  },
  'sending | receiving -> done': whatHappened => {
    console.log('All finished: ', whatHappened)
  }
})

machine.enter('sending')

function sendData() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000)
    setTimeout(reject, 750 + Math.round(Math.random() * 750))
  })
}

function receiveData() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000)
    setTimeout(reject, 750 + Math.round(Math.random() * 750))
  })
}
// The above example using a function for config
machine.onTransitions(({ Enter }) => ({
  'idle -> sending': () => {
    sendData()
      .then(Enter('done', 'sent'))
      .catch(Enter('done', 'failed'))
  },
  'idle -> receiving': () => {
    receiveData()
      .then(Enter('done', 'received'))
      .catch(Enter('done', 'failed'))
  },
  'sending | receiving -> done': whatHappened => {
    console.log('All finished: ', whatHappened)
  }
}))

// etc...

pause ()

Pause the machine. .emit() and .enter() will be no-ops until the machine is .resume()'d.

paused ()

Returns true if the machine is .pause()'d

Returns

boolean :

performTransitions (transitions)

Perform transitions when events happen.

Use then to optionally add callbacks to those transitions.

parameter type description
transitions (object | function) Configuration in the form of an object, or a function that returns an object. If a function is used, there will be a single argument passed-in: an object with the following methods attached as a convenience:

Returns

function : A function that removes all listeners added by this method.

Examples

var machine = Statebot('complex-form', {
  chart: `
    idle ->
      update

    // Maybe things take a long time...
    update ->
      waiting -> waiting-a-while

    // Which path will we take?
    waiting | waiting-a-while ->
      success | failed | timeout

    // All done!
    success | failed | timeout ->
      done
  `
})

machine.performTransitions(({ Enter, emit }) => ({
  'idle -> update': {
    on: 'user-saved',
    then: (data) => {
      console.log('Sending data: ', data)

      sendData(data)
        .then(Enter('success'))
        .catch(Enter('failed'))

      emit('data-sent')
    }
  },
  'update -> waiting': {
    on: 'data-sent',
    then: () => {
      setTimeout(Enter('waiting-a-while'), 750)
      setTimeout(Enter('timeout'), 5000)
    }
  }
}))

// Just to illustrate that you can mix n' match with onTransitions:
machine.onTransitions({
  'waiting | waiting-a-while -> success': () => {
    console.log('Lovely!')
  },
  'waiting | waiting-a-while -> timeout': () => {
    console.log('Well, at least you have your shoes')
  }
})

machine.emit('user-saved', ['some', 'data'])
// Sending data: ["some", "data"]

function sendData() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000)
    setTimeout(reject, 750 + Math.round(Math.random() * 750))
  })
}

previousState ()

Returns the previous state.

Returns

(string | undefined) : The previous state, or undefined if there isn't one (ie; you have just called .reset() , or the machine has just started.)

Examples

var machine = Statebot('simple-sender', {
  chart: `
    idle -> sending -> done
  `
})

machine.enter('sending')
machine.previousState()
// "idle"

reset ()

Returns the state-machine to its starting-state and clears the state-history.

All listeners will still be attached, but no events or transitions will be fired. The pause-state will be maintained.

Examples

var machine = Statebot('carousel', {
  chart: `
    page-1 ->
    page-2 ->
    page-3 ->
    page-4 -> page-1
  `
})

machine.enter('page-2')
machine.reset()
machine.currentState()
// "page-1"

resume ()

Resume a .pause()'d machine.

statesAvailableFromHere (state?)

Return an array of states accessible from the state specified. If no state is passed-in, the .currentState() is used.

parameter type description
state string? The state to check. .currentState() if unspecified.

Returns

Array<String> :

Examples

var machine = Statebot('half-duplex', {
  chart: `
    idle -> sending | receiving -> done
  `
})

machine.statesAvailableFromHere()
// ["sending", "receiving"]

machine.statesAvailableFromHere('receiving')
// ["done"]

enterCallback (fromState, args?)

.onEntering() / .onEntered() callback signature.

Type: Function

parameter type description
fromState string
args ...any? Arguments passed-down from .enter() or .emit()

exitCallback (toState, args?)

.onExiting() / .onExited() callback signature.

Type: Function

parameter type description
toState string
args ...any? Arguments passed-down from .enter() or .emit()

switchCallback (toState, fromState, args?)

.onSwitching() / .onSwitched() callback signature.

Type: Function

parameter type description
toState string
fromState string
args ...any? Arguments passed-down from .enter() or .emit()

assertRouteOptions ()

assertRoute() options.

Type: Object

property type description
description string? : Describe the success-condition for this assertion.
fromState string? : Wait for the machine to be in this state before assertion begins.
run function? : Run this function just before starting the assertion.
permittedDeviations number? : If we hit an unexpected state during assertion, this is a "deviation". It might be that the FSM will come back to the expected state again after a certain number of these. For example, if your FSM has a "retry" route configured, this number can account for it.
timeoutInMs number? : Permitted length of time for the entire assertion, in milliseconds.
logLevel number? : Normally we want logs for assertions, right? Well, you can tune them just like you can with statebotOptions .