An event-driven finite state machine backed by Promises
npm install promise-state-machine-es6[![NPM version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![License][license-image]](LICENSE) [![Gratipay][gratipay-image]][gratipay-url]
This is a rewritten version of promise-state-machine but with no dependencies; not bluebird - just native ES6, DOT) data generation support for use with Graphvis or vis.js, to generate a visual representation of your state machine.
npm install promise-state-machine-es6 --save
`Class PromiseStateMachine
Constructor(options)
state - May be any primitive type.
options.initial - Initial state.
options.events - An Object where key denotes a transition.
options.events[transition].from - From state, may be an array of state.
options.events[transition].to - To state Each key defined in
options.events is defined as a method on the current instance. Use these methods to request a state transition. These methods returns a Promise that Resolves when transition succeded and Rejects when failed. To intercept a transition listen on the transition name, eg if options.events has "warn" transition we can intercept it by fsm.on('warn', (from, to, ...rest) => Promise.resolve()). This event would get called when fsm.warn(...rest).then() is called.is(...states) : Bool
Check if instance is in any state. Argument may be one or many states or an array of states.can(...events) : Bool
Check if instance can transition to a specific state. Argument may be one or many events or an array of events.state [getter] : state
Get current statetoDOTsync(options) : String
Synchronously create DOT file data as a string.
options.replacer - Optional synchronous replacer function that takes a data object and returns a data object with all values stringified. data.from - From state
data.to - To state
data.transition - Transition key # Events
$3
A transition event for each key of options.events passed to the constructor may be emitted when calling any method as defined by options.events.$3
This event is emitted before [transitionKey] event is emitted, returning a Promise that rejects will abort the transition and [eventsKey] event will not be emitted.Examples
$3
`javascript
const fsm = new PromiseStateMachine({
initial: 'green',
events: {
warn: { from: 'green', to: 'yellow' },
panic: { from: ['green', 'yellow'], to: 'red' },
calm: { from: 'red', to: 'yellow' },
clear: { from: ['yellow', 'red'], to: 'green' }
}
});fsm.on('warn', (from, to) => {
return Promise.resolve('result 1');
});
fsm.on('warn', (from, to, transaction, somethingElse) => {
return Promise.resolve('result 2');
});
fsm.on('transaction', (transition, from, to, ...rest) => {
transition; // => 'warn'
});
fsm.warn(transaction, somethingElse).then(function(results) {
// results: ['result 1', 'result 2']
}, function(error) {
// could receive a StateTransitionError if trying to transition via an
// inaccessible event.
});
fsm.is('green'); // => false
fsm.is('yellow'); // => true
fsm.state; // => 'yellow'
fsm.can('calm'); // => false
fsm.can('panic'); // => true
`$3
`javascript
const dotDataString = new PromiseStateMachine({
events: {
approve: { from: 'pending', to: 'approved' },
reject: { from: ['pending', 'approved'], to: 'rejected' },
pend: { from: ['approved', 'rejected'], to: 'pending' },
}
}).toDOTsync();
`
!Alt text$3
`javascript
const dotDataString = new PromiseStateMachine({
events: {
doWork: { from: ['Working', 'Starting'], to: 'Working' },
handleError: { from: ['Working', 'Starting'], to: 'Error' },
end: { from: ['Working', 'Starting'], to: 'End' }
}
}).toDOTsync();
`
!Alt text$3
`javascript
class MyClass extends PromiseStateMachine {
constructor(options) {
super(options);
}
}const fsm = new MyClass({
initial: 'green',
events: {
warn: { from: 'green', to: 'yellow' },
panic: { from: 'yellow', to: 'red' },
calm: { from: 'red', to: 'yellow' },
clear: { from: 'yellow', to: 'green' }
}
});
fsm.is('green'); // => true
fsm.warn().then(() => {
fsm.is('green'); // => false
});
``- [ ] streamed version of toDOTsync
[npm-image]: http://img.shields.io/npm/v/promise-state-machine-es6.svg
[npm-url]: https://npmjs.org/package/promise-state-machine-es6
[downloads-image]: https://img.shields.io/npm/dm/promise-state-machine-es6.svg
[downloads-url]: https://npmjs.org/package/promise-state-machine-es6
[travis-image]: https://travis-ci.org/Faleij/promise-state-machine.svg?branch=master
[travis-url]: https://travis-ci.org/Faleij/promise-state-machine
[coveralls-image]: https://coveralls.io/repos/Faleij/promise-state-machine/badge.svg?branch=master&service=github
[coveralls-url]: https://coveralls.io/github/Faleij/promise-state-machine?branch=master
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg
[gratipay-image]: https://img.shields.io/gratipay/faleij.svg
[gratipay-url]: https://gratipay.com/faleij/