{"_id":"stately.js","_rev":"17-6dba8ab9be6dd12cbf4dcc4baae615a8","name":"stately.js","description":"Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.js and the browser.","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"stately.js","description":"Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.js and the browser.","homepage":"https://github.com/fschaefer/Stately.js","author":{"name":"Florian Schäfer"},"repository":{"type":"git","url":"git://github.com/fschaefer/Stately.js.git"},"keywords":["automata","finite","fsm","machine","state"],"bugs":{"email":"florian.schaefer+Stately.js@gmail.com","url":"https://github.com/fschaefer/Stately.js/issues"},"dependencies":{},"devDependencies":{},"contributors":[{"name":"Rowan Udell","url":"https://github.com/rowanu"},{"name":"Cory Watson","email":"cory.andrew.1988@gmail.com","url":"https://github.com/coryandrew1988"}],"engine":"node >= 0.8.0","main":"Stately.js","version":"1.0.0","_id":"stately.js@1.0.0","dist":{"shasum":"60f7593992b9b79be1182125716556153e1cc039","tarball":"https://registry.npmjs.org/stately.js/-/stately.js-1.0.0.tgz","integrity":"sha512-K+++Ylmqj5ydbdPAZTqEdZ5K0cGcJghFzRaQAqPxcA29/9oh6g37KVyyv5v9k/8BB4X0SUkk6NfkWut98wtrWA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDTxC7GWciG/drOt8rdK3WccsvyHVQTS4HJ7yFqrAuGoAiBtY1zqmH5hwmpdeTPjy2EvbuzgIsCrRBQEseKiSUGiAw=="}]},"_npmVersion":"1.1.63","_npmUser":{"name":"rowanu","email":"rowanu@gmail.com"},"maintainers":[{"name":"rowanu","email":"rowanu@gmail.com"}]},"1.1.0":{"name":"stately.js","description":"Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.js and the browser.","homepage":"https://github.com/fschaefer/Stately.js","author":{"name":"Florian Schäfer"},"repository":{"type":"git","url":"git://github.com/fschaefer/Stately.js.git"},"keywords":["automata","finite","fsm","machine","state"],"bugs":{"email":"florian.schaefer+Stately.js@gmail.com","url":"https://github.com/fschaefer/Stately.js/issues"},"dependencies":{},"devDependencies":{},"contributors":[{"name":"Rowan Udell","url":"https://github.com/rowanu"},{"name":"Cory Watson","email":"cory.andrew.1988@gmail.com","url":"https://github.com/coryandrew1988"}],"engine":"node >= 0.8.0","main":"Stately.js","version":"1.1.0","_id":"stately.js@1.1.0","dist":{"shasum":"16459af037e50aff3408a4dcf6e6f366e4eb77fc","tarball":"https://registry.npmjs.org/stately.js/-/stately.js-1.1.0.tgz","integrity":"sha512-MEwpbZ+n3aGQ+VSYBBq/sCJt+tGNw15E8pmmNiLUI8OsZL3sgBcVym7LDXjOCXc5ipoNAf4reJctWh56LeTOPw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCkTjtxMgx8dqLW4T4VLXepVSlUnEOpmV44LnYUXKjOPgIhAN1eDVcl/4FrFtR2RTM57fSmI7jeheV00V0kbN91V4Tf"}]},"_from":".","_npmVersion":"1.2.14","_npmUser":{"name":"rowanu","email":"rowanu@gmail.com"},"maintainers":[{"name":"rowanu","email":"rowanu@gmail.com"}]},"1.2.0":{"name":"stately.js","description":"Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.js and the browser.","homepage":"https://github.com/fschaefer/Stately.js","author":{"name":"Florian Schäfer"},"repository":{"type":"git","url":"git://github.com/fschaefer/Stately.js.git"},"keywords":["automata","finite","fsm","machine","state"],"bugs":{"url":"https://github.com/fschaefer/Stately.js/issues","email":"florian.schaefer+Stately.js@gmail.com"},"dependencies":{},"devDependencies":{},"contributors":[{"name":"Rowan Udell","url":"https://github.com/rowanu"},{"name":"Cory Watson","email":"cory.andrew.1988@gmail.com","url":"https://github.com/coryandrew1988"}],"engine":"node >= 0.8.0","main":"Stately.js","version":"1.2.0","directories":{"test":"tests"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"license":"MIT","_id":"stately.js@1.2.0","dist":{"shasum":"cf51a1fa99dfbda16dd295cc8ccd4503ffa34b42","tarball":"https://registry.npmjs.org/stately.js/-/stately.js-1.2.0.tgz","integrity":"sha512-wk5cZy79JkUBrQMQOSscwD3phsu2cxZH5YA8c4UauQBIfpTAhGsHMXiCNhJamX0wYAq1hXJLadOm5CkyYqlwMA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDcIgzMhwxV2GwDm/qPl4smGEcxuyB5MzbSZFN81IMLpgIgB7bEYyAIg1bwyM/1pUteqK01RoC9VbUBfPc4sr8pNsM="}]},"_from":".","_npmVersion":"1.3.8","_npmUser":{"name":"rowanu","email":"rowanu@gmail.com"},"maintainers":[{"name":"rowanu","email":"rowanu@gmail.com"}]},"1.3.0":{"name":"stately.js","description":"Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.js and the browser.","homepage":"https://github.com/fschaefer/Stately.js","author":{"name":"Florian Schäfer"},"repository":{"type":"git","url":"git://github.com/fschaefer/Stately.js.git"},"keywords":["automata","finite","fsm","machine","state"],"bugs":{"url":"https://github.com/fschaefer/Stately.js/issues","email":"florian.schaefer+Stately.js@gmail.com"},"dependencies":{},"devDependencies":{},"contributors":[{"name":"Rowan Udell","email":"rowanu@gmail.com","url":"https://github.com/rowanu"},{"name":"Cory Watson","email":"cory.andrew.1988@gmail.com","url":"https://github.com/coryandrew1988"}],"engine":"node >= 0.8.0","main":"Stately.js","version":"1.3.0","directories":{"test":"tests"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"license":"MIT","gitHead":"d9d7a94e35146befcaf035a9f04efa78aa88f69c","_id":"stately.js@1.3.0","_shasum":"52d0d1c152a069a67cb14503ac5ddcdb8be1d777","_from":".","_npmVersion":"2.11.2","_nodeVersion":"0.12.5","_npmUser":{"name":"rowanu","email":"rowanu@gmail.com"},"dist":{"shasum":"52d0d1c152a069a67cb14503ac5ddcdb8be1d777","tarball":"https://registry.npmjs.org/stately.js/-/stately.js-1.3.0.tgz","integrity":"sha512-yfr3aweC9ZViGLjauSuuypEUqRiWhyvqVfDe8C8ujJm7QwbBzgEVCnf2KrkSl2gbprNB4UG0+v72ZfPWZaMN7g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDMAz6EWo1/Xs/Cr2Ww04SCBbRtZ0GUGqdbFy1rIu4VjAiBGKGZ8yaAb64tlZ24owYWh2fxZwon9RExOleaEaZPbiQ=="}]},"maintainers":[{"name":"rowanu","email":"rowanu@gmail.com"}]},"2.0.0":{"name":"stately.js","description":"Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.js and the browser.","homepage":"https://github.com/fschaefer/Stately.js","author":{"name":"Florian Schäfer"},"repository":{"type":"git","url":"git://github.com/fschaefer/Stately.js.git"},"keywords":["automata","finite","fsm","machine","state"],"bugs":{"url":"https://github.com/fschaefer/Stately.js/issues","email":"florian.schaefer+Stately.js@gmail.com"},"dependencies":{},"devDependencies":{},"contributors":[{"name":"Rowan Udell","email":"rowanu@gmail.com","url":"https://github.com/rowanu"},{"name":"Cory Watson","email":"cory.andrew.1988@gmail.com","url":"https://github.com/coryandrew1988"}],"engine":"node >= 0.8.0","main":"Stately.js","version":"2.0.0","directories":{"test":"tests"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"license":"MIT","gitHead":"d596d99948d07b35eeceb8cc6d031b98151d94c1","_id":"stately.js@2.0.0","_npmVersion":"5.4.1","_nodeVersion":"6.10.3","_npmUser":{"name":"rowanu","email":"rowanu@gmail.com"},"dist":{"integrity":"sha512-YGqeGpKVQTD8v3ilfBUUi7S8zQ/obqExaH0kdUX/q7BlDYqDHvyV7r+QYccfNkHtI56uhSqM6J+9LRqR/znnSw==","shasum":"5785f8de9e31baf473f00428b4178530563087b5","tarball":"https://registry.npmjs.org/stately.js/-/stately.js-2.0.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIERUPJR/iHRI/lEppbvUOBysMamZD3FO9ULOWrYEV/5FAiEA1IIR9+WoFwroxCD4JlBLxl6+vrKOZ6U047HvijkvFOA="}]},"maintainers":[{"name":"rowanu","email":"rowanu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/stately.js-2.0.0.tgz_1508196891181_0.7518006581813097"}}},"readme":"![Stately.js Logo](https://github.com/fschaefer/Stately.js/raw/master/misc/Stately.js.png)\n\n## What is it?\n\nStately.js is a JavaScript based finite-state machine (FSM) engine for Node.js\nand the browser.\n\n## Installation\n\nIn Node.js you can install Stately.js with `npm`:\n\n    $ npm install stately.js\n\nand include it to your project by:\n\n```js\nvar Stately = require('stately.js');\n```\n\nAlternately, you can install Stately.js with `bower`:\n\n    $ bower install --save Stately.js\n\nIn browsers you can include it directly by adding it to the document head section:\n\n```html\n<script type=\"text/javascript\" src=\"https://raw.github.com/fschaefer/Stately.js/master/Stately.js\"></script>\n<script type=\"text/javascript\">\n    // use Stately\n</script>\n```\n\nor with Asynchronous Module Definition by e.g.:\n\n```html\n<script type=\"text/javascript\" src=\"https://raw.github.com/jrburke/requirejs/master/require.js\"></script>\n<script type=\"text/javascript\">\nrequire(['https://raw.github.com/fschaefer/Stately.js/master/Stately.js'], function (Stately) {\n    // use Stately\n});\n</script>\n```\n\n## Usage\n\n### Creating a new machine\n\nA new state machine can be created with either the new operator:\n\n```js\nvar machine = new Stately(statesObject, initialStateName);\n```\n\nor the factory method:\n\n```js\nvar machine = Stately.machine(statesObject, initialStateName);\n```\n\nBoth will return a new `stateMachine` object, with all events from all states\nattached to it. The machine will transition into the initial state `initialStateName`\n or the first attached `stateObject` if `initialStateName` is omitted. In addition\nto the events the `stateMachine` object has a `getMachineState()` method, returning\nthe current name of the machines state, `getMachineEvents()`, returning possible\nevents in the current state.\n\nThe `statesObject` is an object  with `stateObject` objects attached as\nproperties.\nThe property names of the `statesObject` are the `states` of the machine.\nThe attached `stateObject` objects model the machines states with the property\nnames as `events` and the connected functions as `actions`:\n\n```js\nvar machine = Stately.machine({\n    'STATE0': {\n        event: function () {\n            ...\n        }\n    },\n    'STATE1': {\n        event: function () {\n            ...\n        }\n    },\n    'STATE2':{\n        event: function () {\n            ...\n        },\n        anotherEvent: function () {\n            ...\n        }\n    }\n});\n```\n\nIf different states use the same event identifier, the `events` are chained up\nand the machine handles calling the correct `action` for the current state (if\nthe `event` is handled in the current state). If the event is not handled in\nthe current state, it is ignored.\n\nIf no immediate `action` needs to be declared, the desired transition `state`\ncan be attached to the `event` as string directly:\n\n```js\nvar machine = Stately.machine({\n    'STATE0': {\n        'event':        /* => */ 'STATE1'\n    },\n    'STATE1': {\n        'event':        /* => */ 'STATE2'\n    },\n    'STATE2': {\n        'event':        /* => */ 'STATE0',\n        'anotherEvent': /* => */ 'STATE1'\n    }\n});\n```\n\n### Transitions\n\nThere are several ways an `action` can transition the machine into another\nstate. The simplest form is returning the desired next state from an action.\nTherefore, `this` refers to the (internal) `stateStore` inside an `action` to\naccess the other states of the machine:\n\n```js\n...\n\n'STATE1': {\n    doSomething: function () {\n\n        ...\n\n        //transition from STATE1 to STATE2\n        return this.STATE2;\n        // as an alternative just return the new state as string\n        // return 'STATE2';\n    }\n}\n\n...\n```\n\nIf an action should not transition the machine into another state, just omit\nthe return value (or return the current state).\n\nSometimes it is desired to return a value from an action. In this case the\nreturn value must be an array with two elements. The first element is the next\nstate the machine should transition into, and the second element the return\nvalue:\n\n```js\n...\n\n'STATE1': {\n    doSomething: function () {\n\n        ...\n\n        //transition from STATE1 to STATE2 and return a string\n        return [this.STATE2, 'this is a return value'];\n    }\n}\n\n...\n```\n\nFor asynchronous actions there are `getMachineState()` and\n`setMachineState(nextState)` accessible through the `this` reference of an\naction:\n\n```js\n...\n\n'STATE1': {\n    doSomething: function () {\n        var self = this;\n\n        setTimeout(function () {\n\n            ...\n\n            self.setMachineState(self.STATE2);\n        }, 5000);\n\n        ...\n\n    }\n}\n\n...\n```\n\nBecause `this` refers to the `stateStore`, it is also possible to call an\naction from another state (note: this won't trigger the `notification`s):\n\n```js\n...\n\n'STATE1': {\n    doSomething: function () {\n\n        ...\n\n        this.STATE2.doSomethingDifferent.call(this);\n\n        ...\n\n        return this.STATE3.doSomethingCompletelyDifferent.call(this);\n    }\n}\n\n...\n```\n\n### Special event hook functions\n\nOnce in a while, it is useful to get a `notification` when the machine\ntransitions into another state. Therefore there are some special event names\nreserved for event functions, namely `onEnter`, `onLeave` (triggered\nwhen entering / leaving a state), `onBefore<eventname>` and `onAfter<eventname>`\n(triggered before or after calling an event).\n\nThe event function has the following signature:\n\n```js\nfunction (event, oldState, newState) {\n    ...\n}\n```\n\n`event` - The event that triggered the transition.\n`oldState` - The old state the machine is transitioned from.\n`newState` - The new state the machine is transitioned into.\n\nInside these functions, `this` refers to the internal `stateStore`.\n\n## Examples\n\n### Door\n\n```js\nvar door = Stately.machine({\n    'OPEN': {\n        'close':  /* => */ 'CLOSED'\n    },\n    'CLOSED': {\n        'open':   /* => */ 'OPEN',\n        'lock':   /* => */ 'LOCKED'\n    },\n    'LOCKED': {\n        'unlock': /* => */ 'CLOSED',\n        'break':  /* => */ 'BROKEN'\n    },\n    'BROKEN': {\n        'fix': function () {\n            this.fixed = (this.fixed === undefined ? 1 : ++this.fixed);\n            return this.fixed < 3 ? this.OPEN : this.BROKEN;\n        }\n    }\n});\n\n//the initial state of the door is open (it's the first state object)\nconsole.log(door.getMachineState() === 'OPEN');        // true;\n\n//close and lock the door\ndoor.close().lock();\nconsole.log(door.getMachineState() === 'LOCKED');      // true;\n\n//try to open it\ndoor.open();\nconsole.log(door.getMachineState() === 'OPEN');        // false;\n\n//unlock, open, lock (is ignored because it fails), close, and lock\ndoor.unlock().open().lock().close().lock();\nconsole.log(door.getMachineState() === 'LOCKED');      // true;\n\n//the door is still locked, break it\ndoor.break();\nconsole.log(door.getMachineState() === 'BROKEN');      // true;\n\n//fix opens the door, close it, lock it, break it again\ndoor.fix().close().lock().break();\nconsole.log(door.getMachineState() === 'BROKEN');      // true;\n\n//and again fix opens the door, close it, lock it, break it\ndoor.fix().close().lock().break();\nconsole.log(door.getMachineState() === 'BROKEN');      // true;\n\n//fixing is limited, the door stays broken\ndoor.fix();\nconsole.log(door.getMachineState() === 'OPEN');        // false;\nconsole.log(door.getMachineState() === 'BROKEN');      // true;\n```\n\n### Radio\n\n```js\nfunction reporter(event, oldState, newState) {\n\n    var transition = oldState + ' => ' + newState;\n\n    switch (transition) {\n        /*\n        ...\n        case 'STOPPED => PLAYING':\n        case 'PLAYING => PAUSED':\n        ...\n        */\n        default:\n            console.log(transition);\n            break;\n    }\n}\n\nvar radio = Stately.machine({\n    'STOPPED': {\n        onEnter: reporter,\n        play: function () {\n            return this.PLAYING;\n        }\n    },\n    'PLAYING': {\n        onEnter: reporter,\n        stop: function () {\n            return this.STOPPED;\n        },\n        pause: function () {\n            return this.PAUSED;\n        }\n    },\n    'PAUSED': {\n        onEnter: reporter,\n        play: function () {\n            return this.PLAYING;\n        },\n        stop: function () {\n            return this.STOPPED;\n        }\n    }\n});\n\nradio.play().pause().play().pause().stop();\n//STOPPED => PLAYING\n//PLAYING => PAUSED\n//PAUSED => PLAYING\n//PLAYING => PAUSED\n//PAUSED => STOPPED\n```\n\n## jsFiddles\n* http://jsfiddle.net/FloHimself/sz2hG/108/\n","maintainers":[{"name":"rowanu","email":"rowanu@gmail.com"}],"time":{"modified":"2022-06-27T00:00:51.328Z","created":"2012-10-29T18:43:44.376Z","1.0.0":"2012-10-29T18:43:45.178Z","1.1.0":"2013-03-21T22:08:19.563Z","1.2.0":"2013-12-16T16:53:50.940Z","1.3.0":"2015-10-22T08:37:46.339Z","2.0.0":"2017-10-16T23:34:51.297Z"},"author":{"name":"Florian Schäfer"},"repository":{"type":"git","url":"git://github.com/fschaefer/Stately.js.git"},"users":{"withinthefog":true,"sunwukung":true,"shangsinian":true,"muccix":true},"homepage":"https://github.com/fschaefer/Stately.js","keywords":["automata","finite","fsm","machine","state"],"contributors":[{"name":"Rowan Udell","email":"rowanu@gmail.com","url":"https://github.com/rowanu"},{"name":"Cory Watson","email":"cory.andrew.1988@gmail.com","url":"https://github.com/coryandrew1988"}],"bugs":{"url":"https://github.com/fschaefer/Stately.js/issues","email":"florian.schaefer+Stately.js@gmail.com"},"license":"MIT","readmeFilename":"README.md"}