JSPM

jssm

4.7.4
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1390
  • Score
    100M100P100Q107876F
  • License MIT

A Javascript state machine with a simple API. Well tested, and typed with Flowtype. MIT License.

Package Exports

  • jssm

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (jssm) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

jssm

A Javascript state machine with a simple API. Well tested, and typed with Flowtype. MIT license.

License Open issues Closed issues

Dependency status NSP status Travis status Coveralls status CodeClimate status

NPM version CDNjs version NPM downloads

TL;DR

Specify finite state machines with a brief syntax. Run them. Derive charts from them. Save and load states. Make factories. Impress friends and loved ones. Cure corns and callouses.

const traffic_light = sm`
  Red 'Proceed' -> Green 'Proceed' -> Yellow 'Proceed' -> Red;
`;

This will produce the following FSM (graphed with jssm-viz):

You could also write that as a piece of data, for when you're generating. That's ... a bit more verbose.

const traffic_light = new jssm.machine({

  initial_state : 'Red',

  transitions   : [
    { action: 'Proceed', from:'Green',  to:'Yellow' },
    { action: 'Proceed', from:'Yellow', to:'Red'    },
    { action: 'Proceed', from:'Red',    to:'Green'  }
  ]

});

In either case, you'll build an executable state machine.

// use with actions
traffic_light.state();              // 'Red'
traffic_light.action('Proceed');    // true
traffic_light.state();              // 'Green'
traffic_light.action('Proceed');    // true
traffic_light.state();              // 'Yellow'
traffic_light.action('Proceed');    // true
traffic_light.state();              // 'Red'

// use with transitions
traffic_light.transition('Yellow'); // false (lights can't go from red to yellow, only to green)
traffic_light.state();              // 'Red'
traffic_light.transition('Red');    // false (lights can't go from red to red, either)
traffic_light.state();              // 'Red'
traffic_light.transition('Green');  // true
traffic_light.state();              // 'Green'

Which you can see being hand-executed in the Chrome console here:



Why

As usual, a valid question.

Why state machines

State machines are a method of making your software better able to prevent illegal states. Similar to type systems, SQL constraints, and linters, state machines are a way to teach the software to catch mistakes in ways you define, to help lead to better software.

The major mechanism of a state machine is to define states, the transitions between them, and sometimes associated data and other niceties. The minor mechanism of state machines is to attach actions to the transitions, such that the state machine can partially run itself.

So, to look at the same traffic light as above, you'll notice some things.

  1. A sufficiently smart implementation will know that it's okay for Green to switch to Yellow, but not to Red
  2. A sufficiently smart implementation knows there's no such thing as Blue
  3. A sufficiently smart implementation knows that when in Green, to be told to Proceed means to go to Yellow, but when in Yellow, it means to go to Red instead

Along with other common sense things, a good state machine implementation can help eliminate large classes of error in software. State machines are often applied when the stakes on having things correct are high.

Why this implementation

Brevity.

High quality testing. JSSM has 100% coverage, and has partial stochastic test coverage.

Feature parity, especially around the DSL and data control.

Data integrity. JSSM allows a much stricter form of state machine than is common, with a relatively low performance and storage overhead. It also offers an extremely terse domain specific language (though it does not require said DSL) to produce state machines in otherwise comparatively tiny and easily read code.

Quick Start

A state machine in JSSM is defined in one of two ways: through the DSL, or through a datastructure.

In the quick start, we'll use the DSL. It looks like this:

const example = sm` FirstState -> SecondState -> ThirdState; `;

There are two pieces of code there, really. There's the outside javascript, which invokes the library and sets up the state machine's instance variable:

const example = sm` ... `;

And there's the domain-specific language, which creates the actual state machine.

FirstState -> SecondState -> ThirdState;

Terminology

Features

DSL

States

Transitions

Validators

State history

Automatic visualization

How to think in state machines

Example Machines

Door lock

Traffic lights

Basic three-state

RYG, Off, Flash-red, Flash-yellow

RYG, Off, Flash-red, Flash-yellow, Green-left, Yellow-left

Heirarchal intersection

ATM

HTTP

Better HTTP

TCP

Coin-op vending machine (data)

Video games

Pac-man Ghost (sensors)

Weather (probabilistics)

Roguelike monster (interface satisfaction)

Candy crush clone game flow (practical large use)

React SPA website (practical large use)

BGP

LibGCrypt FIPS mode FSM

How to debug

Notation Comparison

Their notations, one by one

Apples to Apples - Traffic Light

Other state machines

There are a lot of state machine impls for JS, many quite a bit more mature than this one. Here are some options:

  1. Finity 😮
  2. Stately.js
  3. machina.js
  4. Pastafarian
  5. Henderson
  6. fsm-as-promised
  7. state-machine
  8. mood
  9. FSM Workbench
  10. SimpleStateMachine
  11. shime/micro-machine
    1. soveran/micromachine (ruby)
  12. fabiospampinato/FSM
  13. HQarroum/FSM
  14. Finite-State-Automata
  15. finite-state-machine
  16. nfm

And some similar stuff:

  1. redux-machine
  2. ember-fsm
  3. State machine cat
  4. Workty 😮
  5. sam-simpler
  6. event_chain
  7. DRAKON
  8. Yakindu Statechart Tools
  9. GraphViz
    1. Viz.js, which we use