{"analyzedAt":"2022-12-19T09:42:35.303Z","collected":{"metadata":{"name":"jssm","scope":"unscoped","version":"5.88.3","description":"A Javascript finite state machine (FSM) with a terse DSL and a simple API.  Most FSMs are one-liners.  Fast, easy, powerful, well tested, typed with TypeScript, and visualizations. MIT License.","keywords":["finite","state","state machine","state-machine","machine","finite-state-machine","finite state machine","fsm","fsm-library","js","javascript","javascript-library","mit-license","tested","typed","typed-js","mealy","moore","mealy machine","moore machine","mealy-machine","moore-machine","graphviz","viz.js","fsl","finite-state-language","flowchart","visualization","TypeScript","StoneCypher"],"date":"2022-12-19T03:21:20.639Z","author":{"name":"John Haugeland","email":"stonecypher@gmail.com","username":"stonecypher"},"publisher":{"username":"stonecypher","email":"stonecypher@gmail.com"},"maintainers":[{"username":"stonecypher","email":"stonecypher@gmail.com"}],"repository":{"type":"git","url":"git+https://github.com/StoneCypher/jssm.git"},"links":{"npm":"https://www.npmjs.com/package/jssm","homepage":"https://stonecypher.github.io/jssm/","repository":"https://github.com/StoneCypher/jssm","bugs":"https://github.com/StoneCypher/jssm/issues"},"license":"MIT","dependencies":{"reduce-to-639-1":"^1.1.0","better_git_changelog":"^1.6.1","circular_buffer_js":"^1.10.0"},"devDependencies":{"@knodes/typedoc-plugin-pages":"^0.22.5","@rollup/plugin-commonjs":"^22.0.0","@rollup/plugin-node-resolve":"^13.3.0","@rollup/plugin-replace":"^4.0.0","@types/jest":"^27.0.2","@typescript-eslint/eslint-plugin":"^5.30.4","@typescript-eslint/parser":"^5.30.4","benny":"^3.7.1","chalk":"^4.1.2","cloc":"^2.10.0","coveralls":"^3.0.11","eslint":"^7.32.0","eslint-plugin-fp":"^2.3.0","eslint-plugin-new-with-error":"^2.0.0","eslint-plugin-promise":"^5.1.0","eslint-plugin-react":"^7.26.1","eslint-plugin-unicorn":"^37.0.1","fast-check":"^2.12.0","glob":"^7.1.6","jest":"^27.3.1","jest-json-reporter2":"^1.1.0","pegjs":"^0.10.0","rollup":"^2.72.1","semver":"^5.7.1","terser":"^5.14.2","text_audit":"^0.9.3","ts-jest":"^27.0.7","twitter-api-client":"^1.6.0","typedoc":"^0.22.18","typedoc-plugin-missing-exports":"^0.23.0","typescript":"^4.7.4","xml2js":"^0.4.23"},"releases":[{"from":"2022-11-19T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":4},{"from":"2022-09-20T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":8},{"from":"2022-06-22T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":68},{"from":"2021-12-19T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":159},{"from":"2020-12-19T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":162}],"hasTestScript":true,"readme":"<!--\n\nI8,        8        ,8I                                     88\n`8b       d8b       d8'                                     \"\"\n \"8,     ,8\"8,     ,8\"\n  Y8     8P Y8     8P  ,adPPYYba,  8b,dPPYba,  8b,dPPYba,   88  8b,dPPYba,    ,adPPYb,d8\n  `8b   d8' `8b   d8'  \"\"     `Y8  88P'   \"Y8  88P'   `\"8a  88  88P'   `\"8a  a8\"    `Y88\n   `8a a8'   `8a a8'   ,adPPPPP88  88          88       88  88  88       88  8b       88\n    `8a8'     `8a8'    88,    ,88  88          88       88  88  88       88  \"8a,   ,d88\n     `8'       `8'     `\"8bbdP\"Y8  88          88       88  88  88       88   `\"YbbdP\"Y8\n                                                                              aa,    ,88\n                                                                               \"Y8bbdP\"\n\nThis file is generated.  If you edit it, the edits ***will be lost***.\n----------------------\n\nPlease edit the file it's derived from, instead: `./src/md/readme_base.md`\n\n\n\n* Generated for version 5.88.3 at 12/18/2022, 5:39:00 PM\n\n-->\n# jssm 5.88.3\n\nEasy.  Small.  Fast.  TS, es6, es5.  Node, Browser.  100% coverage.  Property\ntests.  Fuzz tests.  Language tests for a dozen languages and emoji.  Easy to\nshare online.  Easy to embed.\n\nReadable, useful state machines as one-liner strings.\n\n***4,923 tests*** run 5,814 times.  4,914 specs with 100.0% coverage, 9 fuzz tests with 13.2% coverage.  With 2,828 lines, that's about 1.7 tests per line, or {{line_run_ratio}} generated tests per line.\n\n***Meet your new state machine library.***\n\n# <a href=\"https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html\" target=\"_blank\" rel=\"noopener noreferrer\">TRY THE LIVE EDITOR</a>\n\n<a href=\"https://discord.gg/9P95USqnMK\">Discord community</a> - <a href=\"https://stonecypher.github.io/jssm/docs/\">Documentation</a> - <a href=\"https://github.com/StoneCypher/fsl/issues\">Issue tracker</a> - <a href=\"https://github.com/StoneCypher/jssm/actions\">CI build history</a>\n\n<a href=\"https://discord.gg/9P95USqnMK\">![Discord community](https://discordapp.com/api/guilds/899910109642235924/widget.png?style=banner1)</a>\n\n<br/><br/>\n\nWouldn't it be nice if your TypeScript and Javascript state machines were simple and readable one-liners?\n\n```javascript\nimport { sm } from 'jssm';\n\nconst TrafficLight = sm`Red -> Green -> Yellow -> Red;`;\n```\n\n<br/>\n\nWouldn't it be great if they were easy to work with?\n\n```javascript\nconst log = s => console.log(s);\n\nlog( TrafficLight.state() );  // 'Red'\n\nMachine.transition('Green');  // true\nlog( TrafficLight.state() );  // 'Green'\n```\n\n<br/>\n\nWhat if the notation supported action names easily?\n\n```javascript\nconst TLWA = sm`Red 'next' -> Green 'next' -> Yellow 'next' -> Red;`;  // TLWA = Traffic Light With Actions\n\nlog( TLWA.state() );  // 'Red'\n\nTLWA.action('next');  // true\nlog( TLWA.state() );  // 'Green'\n\nTLWA.action('next');  // true\nlog( TLWA.state() );  // 'Yellow'\n\nTLWA.action('next');  // true\nlog( TLWA.state() );  // 'Red'\n```\n\n<br/>\n\nWhat if integration with the outside was straightforward?\n\n```javascript\nconst MTL = sm`Red 'next' -> Green 'next' -> Yellow 'next' -> Red;`  // MTL = More Traffic Lights\n              .hook('Red', 'Green', () => log('GO GO GO') )          // node will jump the gun when you hit return, though\n              .hook_entry('Red', () => log('STOP') );                // so put it on one line in node\n\nlog( MTL.state() );  // 'Red'\n\nTLWA.action('next');  // true, console logs 'GO GO GO'\nlog( TLWA.state() );  // 'Green'\n\nTLWA.action('next');  // true\nlog( TLWA.state() );  // 'Yellow'\n\nTLWA.action('next');  // true, console logs 'STOP'\nlog( TLWA.state() );  // 'Red'\n```\n\n<br/>\n\nWhat if the machine followed JS standards, and distinguished refusals as `false` from mistakes as `throw`n?\n\n```javascript\nconst ATL = sm`Red -> Green -> Yellow -> Red;`;  // ATL = Another Traffic Light\n\nlog( ATL.state() );         // 'Red' - uses 1st state unless told otherwise\nATL.transition('Yellow');   // false (Yellow isn't allowed from Red)\nATL.transition('Blue');     // throws (Blue isn't a state at all)\n```\n\n<br/>\n\nWhat if there were easy convenience notations for lists, and for designating main-path `=>` vs available path `->` vs\nonly-when-forced `~>` ?\n\n```javascript\nconst TrafficLightWithOff = sm`\n  Red => Green => Yellow => Red;\n  [Red Yellow Green] ~> Off -> Red;\n`;\n```\n\n<br/>\n\nWhat if that were easy to render visually?\n\n```javascript\nconst TrafficLightWithOff = sm`\n  Red => Green => Yellow => Red;\n  [Red Yellow Green] ~> Off -> Red;\n`;\n```\n\n<br/>\n\n<img src=\"https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/doc%20light%20unstyled.png\"/>\n\n<br/>\n\nWhat if that were easy to render visually, with styling, in PNG, JPEG, or SVG?\n\n```javascript\nconst TrafficLightWithOff = sm`\n  Red => Green => Yellow => Red;\n  [Red Yellow Green] ~> Off -> Red;\n\n  flow: left;\n\n  state Red    : { background-color: pink;        corners: rounded; };\n  state Yellow : { background-color: lightyellow; corners: rounded; };\n  state Green  : { background-color: lightgreen;  corners: rounded; };\n\n  state Off : {\n    background-color : steelblue;\n    text-color       : white;\n    shape            : octagon;\n    linestyle        : dashed;\n  };\n`;\n```\n\n<br/>\n\n<img src=\"https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/doc%20light%20styled.png\"/>\n\n<br/>\n\nWhat if the machine was lighting fast, able to do tens of millions of transitions per second?\n\n<img src=\"https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/speed%20claim.png\"/>\n\n<br/>\n\n* What if the machine and language had [extensive 100% test coverage](https://coveralls.io/github/StoneCypher/jssm)\n  with [thousands of cases](https://github.com/StoneCypher/jssm/tree/main/src/ts/tests)?\n* What if the machine gave extensive Typescript introspection support?\n* What if the machine had been around and active since May 2017?\n* What if the machine was MIT licensed, end to end?\n\nBut, above all else:\n\n`What if it was easy?`\n\n\n\n\n\n<br/><br/>\n\n# Introducing JSSM\n\nMeet JSSM: the <b><u>J</u></b>ava<b><u>s</u></b>cript <b><u>S</u></b>tate <b><u>M</u></b>achine.\n\nState machines can make your code cleaner, safer, and more trustworthy.\n\nAnd, with the right language, state machines can be easy and fun.\n\n<a href=\"https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html\" target=\"_blank\" rel=\"noopener noreferrer\">TRY THE LIVE EDITOR</a>\n\n\n\n<br/>\n\n## What is JSSM?\n\nJSSM is a Javascript state machine implementing [Finite State Language](https://fsl.tools/), with a terse DSL and a simple API.\n100% test coverage; typed with Flowtype.  MIT licensed.\n\nThe NPM package includes pure `es6`, a `cjs es5` bundle, and `.d.ts` typings.  The repository includes the original typescript, the bundle, the es6, documentation, tests, tutorials, and so on.\n\n[Try it live!](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html)\n\nVisualize with [jssm-viz](https://github.com/StoneCypher/jssm-viz), or at the command line with [jssm-viz-cli](https://github.com/StoneCypher/jssm-viz-cli).\n\nLanguage test cases for Belorussian, English, German, Hebrew, Italian, Russian, Spanish, Ukrainian, and Emoji.  Please help to make sure that your language is well handled!\n\n<div id=\"badge_style_hook\">\n\n[![Actions Status](https://github.com/StoneCypher/jssm/workflows/Node%20CI/badge.svg)](https://github.com/StoneCypher/jssm/actions)\n\n[![GitHub forks](https://img.shields.io/github/forks/StoneCypher/jssm.svg?style=social&label=Fork%20JSSM)]()\n[![GitHub watchers](https://img.shields.io/github/watchers/StoneCypher/jssm.svg?style=social&label=Watch%20JSSM)]()\n[![GitHub stars](https://img.shields.io/github/stars/StoneCypher/jssm.svg?style=social&label=JSSM%20Stars)]()\n[![GitHub followers](https://img.shields.io/github/followers/StoneCypher.svg?style=social&label=Follow%20StoneCypher)]()\n\n[![License](https://img.shields.io/npm/l/jssm.svg)](https://github.com/StoneCypher/jssm/blob/master/LICENSE.md)\n[![Open issues](https://img.shields.io/github/issues/StoneCypher/jssm.svg)](https://github.com/StoneCypher/jssm/issues)\n[![Closed issues](https://img.shields.io/github/issues-closed/StoneCypher/jssm.svg)](https://github.com/StoneCypher/jssm/issues?q=is%3Aissue+is%3Aclosed)\n[![Travis status](https://img.shields.io/travis/StoneCypher/jssm.svg)](https://travis-ci.org/StoneCypher/jssm)\n[![Coveralls status](https://img.shields.io/coveralls/StoneCypher/jssm.svg)](https://coveralls.io/github/StoneCypher/jssm)\n\n[![NPM version](https://img.shields.io/npm/v/jssm.svg)](https://www.npmjs.com/package/jssm)\n[![CDNjs version](https://img.shields.io/cdnjs/v/jquery.svg)](https://img.shields.io/cdnjs/v/jquery.svg)\n[![NPM downloads](https://img.shields.io/npm/dt/jssm.svg)](https://www.npmjs.com/package/jssm)\n\n<img src=\"https://starchart.cc/StoneCypher/jssm.svg\" width=\"50%\">\n\n</div>\n\n\n\n<br/><br/>\n\n## TL;DR\nSpecify finite state machines with a brief syntax.  Run them; they're fast.  Make mistakes; they're strict.  Derive\ncharts.  Save and load states, and histories.  Make machine factories to churn out dozens or thousands of instances.\nImpress friends and loved ones.  Cure corns and callouses.\n\n```fsl\nRed 'Proceed' -> Green 'Proceed' -> Yellow 'Proceed' -> Red;\n```\n\nThis will produce the following FSM (graphed with [jssm-viz](https://github.com/StoneCypher/jssm-viz)):\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/ryg%20proceed.png)\n\nYou'll build an executable state machine.\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/ryg%20traffic%20light%20console%20screenshot.png)\n\n\n\n<br/><br/>\n\n## Why\n\nAs usual, a valid question.\n\n\n\n<br/>\n\n### Why state machines\n\nState machines are a method of making your software better able to prevent illegal states.  Similar to type systems, SQL\nconstraints, and linters, state machines are a way to teach the software to catch mistakes in ways you define, to help\nlead to better software.\n\nThe major mechanism of a state machine is to define `states`, the `transitions` between them, and sometimes associated\n`data` and other niceties.  The minor mechanism of state machines is to attach `actions` to the transitions, such that\nthe state machine can partially run itself.\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/ryg%20proceed.png)\n\nSo, to look at the same traffic light as above, you'll notice some things.\n\n1. A sufficiently smart implementation will know that it's okay for `Green` to switch to `Yellow`, but not to `Red`\n1. A sufficiently smart implementation knows there's no such thing as `Blue`\n1. A sufficiently smart implementation knows that when in `Green`, to be told to `Proceed` means to go to `Yellow`, but\n   when in `Yellow`, it means to go to `Red` instead\n\nAlong with other common sense things, a good state machine implementation can help eliminate large classes of error in\nsoftware.  State machines are often applied when the stakes on having things correct are high.\n\n\n\n<br/>\n\n### Why this implementation\n\nBrevity.\n\nHigh quality testing.  JSSM has 100% coverage, and has partial stochastic test coverage.\n\nFeature parity, especially around the DSL and data control.\n\nData integrity.  JSSM allows a much stricter form of state machine than is common, with a relatively low performance\nand storage overhead.  It also offers an extremely terse domain specific language (though it does not require said DSL)\nto produce state machines in otherwise comparatively tiny and easily read code.\n\n\n\n<br/><br/>\n\n## Quick Start\n\n> A state machine in `JSSM` is defined in one of two ways: through the DSL, or through a datastructure.\n\nSo yeah, let's start by getting some terminology out of the way, and then we can go right back to that impenetrable\nsentence, so that it'll make sense.\n\n\n\n<br/>\n\n### Quick Terminology\n\nFinite state machines have been around forever, are used by everyone, and are hugely important.  As a result, the\nterminology is a mess, is in conflict, and is very poorly chosen, in accordince with everything-is-horrible law.\n\nThis section describes the terminology *as used by this library*.  The author has done his best to choose a terminology\nthat matches common use and will be familiar to most.  Conflicts are explained in the following section, to keep this\nsimple.\n\nFor this quick overview, we'll define six basic concepts:\n\n1. `Finite state machine`s\n1. `Machine`s\n1. `State`s\n1. `Current state`\n1. `Transition`s\n1. `Action`s\n\nThere's other stuff, of course, but these five are enough to wrap your head around `finite state machine`s.\n\n\n\n<br/>\n\n#### Basic concepts\n\nThis is a trivial traffic light `FSM`, with three states, three transitions, and one action:\n\n```fsl\nRed 'Proceed' -> Green 'Proceed' -> Yellow 'Proceed' -> Red;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/ryg%20proceed.png)\n\nLet's review its pieces.\n\n* `finite state machine`s\n  * A `finite state machine` (or `FSM`) is a collection of `state`s, and rules about how you can `transition` between\n    the `state`s.\n  * We tend to refer to a design for a machine as \"an `FSM`.\"\n  * In this example, the traffic light's structure is \"a traffic light `FSM`.\"\n\n* `state`s\n  * `FSM`s always have at least one `state`, and nearly always many `state`s\n  * In this example,\n    * the `state`s are **Red**, **Yellow**, and **Green**\n    * Something made from this `FSM` will only ever be one of those colors - not, say, **Blue**\n\n* `machine`s\n  * Single instances of an `FSM` are referred to as a `machine`\n  * We might have a thousand instances of the traffic light designed above\n  * We would say \"My intersection has four `machines` of the standard three color light `FSM`.\"\n\n* `current state`\n  * A `machine` has a `current state`, though an `FSM` does not\n    * \"This specific traffic light is currently **Red**\"\n  * Traffic lights in general do not have a current color, only specific lights\n  * `FSM`s do not have a current state, only specific `machine`s\n  * A given `machine` will always have exactly one `state` - never multiple, never none\n\n* `transitions`\n  * `FSM`s nearly always have `transition`s\n  * Transitions govern whether a `state` may be reached from another `state`\n    * This restriction is much of the value of `FSM`s\n  * In this example,\n    * the `transition`s are\n      * **Green** &rarr; **Yellow**\n      * **Yellow** &rarr; **Red**\n      * **Red** &rarr; **Green**\n    * a `machine` whose `current state` is **Green** may switch to **Yellow**, because there is an appropriate transition\n    * a `machine` whose `current state` is **Green** may not switch to **Red**, or to **Green** anew, because there is no\n      such transition\n      * A `machine` in **Yellow** which is told to `transition` to **Green** (which isn't legal) will know to refuse\n      * This makes `FSM`s an effective tool for error prevention\n\n* `actions`\n  * Many `FSM`s have `action`s, which represent events from the outside world.\n  * In this example, there is only one action - **Proceed**\n    * The `action` **Proceed** is available from all three colors\n  * At any time we may indicate to this light to go to its next color, without\n    taking the time to know what it is.\n    * This allows `FSM`s like the light to self-manage.\n    * A `machine` in **Yellow** which is told to take the `action` **Proceed** will\n      know on its own to switch its `current state` to **Red**.\n    * This makes `FSM`s an effective tool for complexity reduction\n\nThose six ideas in hand - `FSM`s, `state`s, `machine`s, `current state`, `transition`s, and `action`s - and you're ready\nto move forwards.\n\nOne other quick definition - a `DSL`, or `domain specific language`, is when someone makes a language and embeds it into\na different language, for the purpose of attacking a specific job.  When `React` uses a precompiler to embed stuff that\nlooks like HTML in Javascript, that's a DSL.\n\nThis library implements a simple language for `defining finite state machine`s inside of strings.  For example, this\n`DSL` defines that `'a -> b;'` actually means \"create two states, create a transition between them, assign the first as\nthe initial state\", et cetera.  That micro-language is the `DSL` that we'll be referring to a lot, coming up.  This\n`DSL`'s parser's original name was `jssm-dot`, because it's a descendant-in-spirit of an older flowcharting language\n[DOT](http://www.graphviz.org/content/dot-language), from [graphviz](graphviz.org), which is also used to make the\nvisualizations in [jssm-viz](https://github.com/StoneCypher/jssm-viz) by way of [viz-js](viz-js.com).\n\nEnough history lesson.  On with the tooling.\n\n\n\n<br/>\n\n### And now, that Quick Start we were talking about\n\nSo let's put together a trivial four-state traffic light: the three colors, plus **Off**.  This will give us an\nopportunity to go over the basic facilities in the language.\n\nAt any time, you can take the code and put it into the\n[graph explorer](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html) for an opportunity to mess with the\ncode as you see fit.\n\n\n\n<br/>\n\n#### 0: Lights always have an off state\n\nOur light will start in the **Off** `state`, with the ability to switch to the **Red** `state`.\n\nSince that's a normal, not-notable thing, we'll just make it a regular `-> legal transition`.\n\n```fsl\nOff -> Red;\n```\n\nWe will give that `transition` an `action`, and call it **TurnOn**.\n\n```fsl\nOff 'TurnOn' -> Red;\n```\n\nSo far, our machine is simple:\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/traffic%20light%20quick%20start%20tutorial/Off%20To%20Red.png)\n\n\n\n<br/>\n\n#### 1: Traffic lights have a three-color cycle\n\nThe main path of a traffic light is cycling from **Green** to **Yellow**, then to **Red**, then back again.  Because\nthis is the main path, we'll mark these steps `=> main transition`s.\n\n```fsl\nOff 'TurnOn' -> Red => Green => Yellow => Red;\n```\n\nWe will give those all the same action name, **Proceed**, indicating \"next color\" without needing to know what we're\ncurrently on.\n\n```fsl\nOff 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;\n```\n\nMachine's still pretty simple:\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/traffic%20light%20quick%20start%20tutorial/Off%20To%20RGY.png)\n\n\n\n<br/>\n\n#### 2: Traffic lights can be shut down\n\nWe'd also like to be able to turn this light back off.  Because that's expected to be a rarity, we'll require that it\nbe a `~> forced transition`.\n\nWe could write\n\n```fsl\nOff 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;\nRed ~> Off;\nYellow ~> Off;\nGreen ~> Off;\n```\n\nBut that takes a lot of space even with this short list, so, instead we'll use the array notation\n\n```fsl\nOff 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;\n[Red Yellow Green] ~> Off;\n```\n\nAnd we'd like those all to have the action **TurnOff**, so\n\n```fsl\nOff 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;\n[Red Yellow Green] 'TurnOff' ~> Off;\n```\n\nMachine's still not too bad:\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/traffic%20light%20quick%20start%20tutorial/Off%20To%20From%20RGY.png)\n\n\n\n<br/>\n\n### Let's actually use the traffic light\n\nThat's actually the bulk of the language.  There are other little add-ons here and there, but, primarily you now know\nhow to write a state machine.\n\nLet's load it and use it!  😀\n\n#### loading into node\n#### loading into html\n#### jssm-viz\n#### redistribution on npm\n\n\n\n<br/>\n\n### An introduction to machine design\n\nLet's make a `state machine` for ATMs.  In the process, we will use a lot of core concepts of `finite state machine`s\nand of `fsl`, this library's `DSL`.\n\nWe're going to improve on this [NCSU ATM diagram](https://people.engr.ncsu.edu/efg/210/s99/Notes/fsm/atm.gif) that I\nfound:\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/ncsu%20atm%20diagram.gif)\n\nRemember, at any time, you can take the code and put it into the\n[graph explorer](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html) for an opportunity to mess with the\ncode as you see fit.\n\n\n\n<br/>\n\n#### 0: Empty machine\n\nWe'll start with an [empty machine](https://github.com/StoneCypher/jssm/blob/master/src/machines/atm%20quick%20start%20tutorial/1_EmptyWaiting.jssm).\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/0_EmptyWaiting.png)\n\n\n\n<br/>\n\n#### 1: Should be able to eject cards\n\nWe'll add the ability to physically eject the user's card and reset to the empty and waiting state.  Right now it'll\ndangle around un-used at the top, but later it'll become useful.\n\nThis is expressed as the path `EjectCardAndReset -> EmptyWaiting;`\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting;\nEjectCardAndReset -> EmptyWaiting;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/1_EjectCard.png)\n\n\n\n<br/>\n\n#### 2: Should be able to insert cards\n\nWe'll add the ability to physically insert a card, next.  You know, the, uh, thing ATMs are pretty much for.\n\nTo get this, add the path leg `EmptyWaiting 'InsertCard' -> HasCardNoAuth;`\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;\nEjectCardAndReset -> EmptyWaiting;\n```\n\nNotice that the new `state`, **HasCardNoAuth**, has been rendered red.  This is because it is `terminal` - there is\nno exit from this node currently.  (**EmptyAndWaiting** did not render that way because it had a transition to itself.)\nThat will change as we go back to adding more nodes.  `terminal node`s are usually either mistakes or the last single\n`state` of a given `FSM`.\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/2_InsertCard.png)\n\n\n\n<br/>\n\n#### 3: Should be able to cancel and recover the card\n\nNext, we should have a cancel, because the ATM's <key>7</key> key is broken, and we need our card back.  Cancel will\nexit to the main menu, and return our card credential.\n\nTo that end, we add the path `HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;`\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;\n\nHasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;\n\nEjectCardAndReset -> EmptyWaiting;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/3_ReturnCard.png)\n\n\n\n<br/>\n\n#### 4: Can give the wrong PIN\n\nNext, let's give the ability to get the password ... wrong.  😂  Because we all know that one ATM that only has the\nwrong-PIN path, so, apparently that's a product to someone.\n\nWhen they get the PIN wrong, they're prompted to try again (or to cancel.)\n\nWe'll add the path `HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;`\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;\n\nHasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;\nHasCardNoAuth 'WrongPIN' -> HasCardNoAuth;\n\nEjectCardAndReset -> EmptyWaiting;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/4_WrongPin.png)\n\n\n\n\n\n<br/>\n\n#### 5: Can give the correct PIN\n\nNext, let's give the ability to get the password right.\n\nWe'll add two paths.  The first gets the password right: `HasCardNoAuth 'RightPIN' -> MainMenu;`\n\nThe second, from our new `state` **MainMenu**, gives people the ability to leave: `MainMenu 'ExitReturnCard' -> EjectCardAndReset;`\n\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;\n\nHasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;\nHasCardNoAuth 'WrongPIN' -> HasCardNoAuth;\nHasCardNoAuth 'RightPIN' -> MainMenu;\n\nMainMenu 'ExitReturnCard' -> EjectCardAndReset;\n\nEjectCardAndReset -> EmptyWaiting;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/5_RightPin.png)\n\n\n\n<br/>\n\n#### 6: Can check balance from main menu\n\nHooray, now we're getting somewhere.\n\nLet's add the ability to check your balance.  First pick that from the main menu, then pick which account to see the\nbalance of, then you're shown a screen with the information you requested; then go back to the main menu.\n\nThat's `MainMenu 'CheckBalance' -> PickAccount -> DisplayBalance -> MainMenu;`.\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;\n\nHasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;\nHasCardNoAuth 'WrongPIN' -> HasCardNoAuth;\nHasCardNoAuth 'RightPIN' -> MainMenu;\n\nMainMenu 'ExitReturnCard' -> EjectCardAndReset;\nMainMenu 'CheckBalance' -> PickAccount -> DisplayBalance -> MainMenu;\n\nEjectCardAndReset -> EmptyWaiting;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/6_CanCheckBalance.png)\n\n\n\n<br/>\n\n#### 7: Can deposit money from main menu\n\nLet's add something difficult.  Their state machine just proceeds assuming everything is okay.\n\nTo desposit money:\n\n1. Accept physical money\n2. If accept failed (eg door jammed,) reject physical object, go to main menu\n3. If accept succeeded, ask human expected value\n4. Pick an account this should go into\n5. Contact bank.  Request to credit for theoretical physical money.\n6. Three results: yes, no, offer-after-audit.\n7. If no, reject physical object, go to main menu.\n8. If yes, consume physical object, tell user consumed, go to main menu\n9. If offer-after-audit, ask human what to do\n10. if human-yes, consume physical object, tell user consumed, go to main menu\n11. if human-no, reject physical object, go to main menu\n\nWriting this out in code is not only generally longer than the text form, but also error prone and hard to maintain.\n\n... or there's the `FSM` `DSL`, which is usually as-brief-as the text, and frequently both briefer and more explicit.\n\n* Rules 1-2: `MainMenu 'AcceptDeposit' -> TentativeAcceptMoney 'AcceptFail' -> RejectPhysicalMoney -> MainMenu;`\n* Rules 3-6: `TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;`\n* Rule 7: `BankResponse 'BankNo' -> RejectPhysicalMoney;`\n* Rule 8: `BankResponse 'BankYes' -> ConsumeMoney -> NotifyConsumed -> MainMenu;`\n* Rules 9-10: `BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;`\n* Rule 11: `BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;`\n\nOr, as a block,\n\n```fsl\nMainMenu 'AcceptDeposit' -> TentativeAcceptMoney;\n\nTentativeAcceptMoney 'AcceptFail' -> RejectPhysicalMoney -> MainMenu;\nTentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;\n\nBankResponse 'BankNo'    -> RejectPhysicalMoney;\nBankResponse 'BankYes'   -> ConsumeMoney -> NotifyConsumed -> MainMenu;\nBankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;\n\nBankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;\n```\n\nWhich leaves us with the total code\n\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;\n\nHasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;\nHasCardNoAuth 'WrongPIN' -> HasCardNoAuth;\nHasCardNoAuth 'RightPIN' -> MainMenu;\n\nMainMenu 'AcceptDeposit'  -> TentativeAcceptMoney;\nMainMenu 'ExitReturnCard' -> EjectCardAndReset;\nMainMenu 'CheckBalance'   -> PickCheckBalanceAccount -> DisplayBalance -> MainMenu;\n\nTentativeAcceptMoney 'AcceptFail'    -> RejectPhysicalMoney -> MainMenu;\nTentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;\n\nBankResponse 'BankNo'    -> RejectPhysicalMoney;\nBankResponse 'BankYes'   -> ConsumeMoney -> NotifyConsumed -> MainMenu;\nBankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;\n\nBankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;\n\nEjectCardAndReset -> EmptyWaiting;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/7_CanDepositMoney.png)\n\n\n\n<br/>\n\n#### 8: Can withdraw money from main menu\n\nLet's also be able to take money from the machine.  After this, we'll move on, since our example is pretty squarely made\nby now.\n\n1. Pick a withdrawl account, or cancel to the main menu\n2. Shown a balance, pick a withdrawl amount, or cancel to acct picker\n3. Is the withdrawl account too high?  If so go to 2\n4. Does the machine actually have the money?  If not go to 2\n5. Otherwise confirm intent w/ human\n6. Attempt to post the transaction.\n7. If fail, display reason and go to 1\n8. If succeed, dispense money and go to main menu\n\n* Rules 1-3: `MainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;`\n* Rule 4: `AcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;`\n* Rule 5: `MachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;`\n* Rule 6: `ConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;`\n* Rule 7: `BankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;`\n* Rule 8: `BankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;`\n\nRule 1 canceller: `PickWithdrawlAccount 'CancelWithdrawl' -> MainMenu;`\nRule 2 canceller: `PickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;`\n\nOr as a whole, we're adding\n\n```fsl\nMainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;\nAcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;\nMachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;\nConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;\nBankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;\nBankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;\n\nPickWithdrawlAccount 'CancelWithdrawl' -> MainMenu;\nPickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;\n```\n\nWhich leaves us with\n\n```fsl\nEmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;\n\nHasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;\nHasCardNoAuth 'WrongPIN' -> HasCardNoAuth;\nHasCardNoAuth 'RightPIN' -> MainMenu;\n\nMainMenu 'AcceptDeposit'  -> TentativeAcceptMoney;\nMainMenu 'ExitReturnCard' -> EjectCardAndReset;\nMainMenu 'CheckBalance'   -> PickCheckBalanceAccount -> DisplayBalance -> MainMenu;\n\nTentativeAcceptMoney 'AcceptFail'    -> RejectPhysicalMoney -> MainMenu;\nTentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;\n\nBankResponse 'BankNo'    -> RejectPhysicalMoney;\nBankResponse 'BankYes'   -> ConsumeMoney -> NotifyConsumed -> MainMenu;\nBankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;\n\nBankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;\n\nMainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;\nAcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;\nMachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;\nConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;\nBankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;\nBankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;\n\nPickWithdrawlAccount 'CancelWithdrawl' -> MainMenu;\nPickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;\n\nEjectCardAndReset -> EmptyWaiting;\n```\n\n![](https://raw.githubusercontent.com/StoneCypher/jssm/master/src/assets/atm%20quick%20start%20tutorial/8_CanWithdrawMoney.png)\n\nAs you can see, building up even very complex state machines is actually relatively straightforward, in a short\namount of time.\n\n\n\n<br/><br/>\n\n## Features\n### DSL\n### States\n### Transitions\n### Cycles\n### Stripes\n### Named Ordered Lists\n### Atoms\n### Strings\n### Arrow types\n### Unicode representations\n### Node declarations\n### All the styling bullshit\n### Named edges\n### URL callouts\n### The 9 or whatever directives\n### How to publish a machine\n#### Legal, main, and forced\n### Validators\n### State history\n### Automatic visualization\n\n\n\n<br/><br/>\n\n## How to think in state machines\n\n\n\n<br/><br/>\n\n## Example Machines\n### Door lock\n### Traffic lights\n#### Basic three-state\n#### RYG, Off, Flash-red, Flash-yellow\n#### RYG, Off, Flash-red, Flash-yellow, Green-left, Yellow-left\n#### Heirarchal intersection\n### [ATM](https://people.engr.ncsu.edu/efg/210/s99/Notes/fsm/atm.gif)\n### [HTTP](https://www.w3.org/Library/User/Architecture/HTTP.gif)\n#### Better HTTP\n### [TCP](http://www.texample.net/media/tikz/examples/PNG/tcp-state-machine.png)\n### Coin-op vending machine (data)\n### Video games\n#### Pac-man Ghost (sensors)\n#### Weather (probabilistics)\n#### Roguelike monster (interface satisfaction)\n### Candy crush clone game flow (practical large use)\n### Vegas locked 21 dealer behavior\n### React SPA website (practical large use)\n### [BGP](https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/BGP_FSM.svg/549px-BGP_FSM.svg.png)\n### [LibGCrypt FIPS mode FSM](https://www.gnupg.org/documentation/manuals/gcrypt/fips-fsm.png)\n\n\n\n<br/><br/>\n\n## How to debug\n\n\n\n<br/><br/>\n\n## How to publish\nIt's really quite simple.\n\n1. Make a github repository.\n1. Put your code in a file inside, with the extension `.fsl`\n1. Make sure your code contains a `machine_name`\n\nOnce done, your work should show up [here](https://github.com/search?utf8=%E2%9C%93&q=extension%3Afsl+machine_name&type=Code).\n\n\n\n<br/><br/>\n\n## Notation Comparison\n### Their notations, one by one\n### Apples to Apples - Traffic Light\n\n\n\n<br/><br/>\n\n## Other state machines\nThere are a lot of state machine impls for JS, many quite a bit more mature than this one.  Here are some options:\n\n1. [Finity](https://github.com/nickuraltsev/finity) 😮\n1. [Stately.js](https://github.com/fschaefer/Stately.js)\n1. [machina.js](https://github.com/ifandelse/machina.js)\n1. [Pastafarian](https://github.com/orbitbot/pastafarian)\n1. [Henderson](https://github.com/orbitbot/henderson)\n1. [fsm-as-promised](https://github.com/vstirbu/fsm-as-promised)\n1. [state-machine](https://github.com/DEADB17/state-machine)\n1. [mood](https://github.com/bredele/mood)\n1. [FSM Workbench](https://github.com/MatthewHepburn/FSM-Workbench)\n1. [SimpleStateMachine](https://github.com/ccnokes/SimpleStateMachine)\n1. shime/[micro-machine](https://github.com/shime/micro-machine)\n    1. soveran/[micromachine](https://github.com/soveran/micromachine) (ruby)\n1. fabiospampinato/[FSM](https://github.com/fabiospampinato/FSM)\n1. HQarroum/[FSM](https://github.com/HQarroum/Fsm)\n1. [Finite-State-Automata](https://github.com/RolandR/Finite-State-Automata)\n1. [finite-state-machine](https://github.com/MarkH817/finite-state-machine)\n1. [nfm](https://github.com/ajauhri/nfm)\n\n\nAnd some similar stuff:\n1. [redux-machine](https://github.com/mheiber/redux-machine)\n1. [ember-fsm](https://github.com/heycarsten/ember-fsm)\n1. [State machine cat](https://github.com/sverweij/state-machine-cat)\n1. [Workty](https://github.com/AlexLevshin/workty) 😮\n1. [sam-simpler](https://github.com/sladiri/sam-simpler)\n1. [event_chain](https://github.com/quilin/event_chain)\n1. [DRAKON](https://en.wikipedia.org/wiki/DRAKON)\n1. [Yakindu Statechart Tools](https://github.com/Yakindu/statecharts)\n1. [GraphViz](http://www.graphviz.org/)\n    1. [Viz.js](https://github.com/mdaines/viz.js/), which we use\n\n\n\n<br/><br/><br/>\n\n# Thanks\n\nJSSM and FSL have had a lot of help.\n\n\n\n<br/><br/>\n\n## Internationalization\n\n* [Mykhaylo Les](https://github.com/miles91) provided three translation test cases ([Ukrainian](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/ukrainian.json), [Belarussian](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/belarussian.json), and [Russian](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/russian.json),) and the corresponding Traffic Light translations (also [Ukrainian](https://github.com/StoneCypher/fsl_traffic_light_ukrainian/blob/master/traffic%20light.fsl), [Belarussian](https://github.com/StoneCypher/fsl_traffic_light_belarussian/blob/master/traffic_light.fsl), and [Russian](https://github.com/StoneCypher/fsl_traffic_light_russian/blob/master/traffic%20light.fsl).)\n* [Tanvir Islam](https://github.com/tanvirrb) provided the [Bengali test case](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/bengali.json), translated the [Traffic Light](https://github.com/tanvirrb/fsl-traffic-light-bengali/blob/master/traffic_light.fsl) to Bengali, and published the first non-English `FSL` machine, in Bengali.\n* [Francisco Junior](https://github.com/fcojr) provided the [Portuguese test case](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/portuguese.json) and translated the [Traffic Light](https://github.com/StoneCypher/fsl_traffic_light_portuguese/blob/master/traffic_light.fsl) to Portuguese\n* [Jeff Katz](https://github.com/kraln) provided the [German test case](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/german.json).\n* [Alex Cresswell](https://github.com/technophile77) provdied the [Spanish test case](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/spanish.json)\n* [Dvir Cohen](https://github.com/cohendvir) provided the [Hebrew test case](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/hebrew.json).\n* [David de la Peña](https://github.com/daviddelapena) provided the [French test case](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/french.json)\n\nIf I've overlooked you, please let me know.\n\nIf you'd like to help, it's straightforward.\n\n1. Easy mode: open a PR with [this file](https://github.com/StoneCypher/jssm/blob/master/src/js/tests/language_data/english.json) translated into your language\n1. Extra mile: create a new repo containing [this file](https://github.com/StoneCypher/fsl_traffic_light/blob/master/traffic_light.fsl) translated\n\n\n\n<br/><br/>\n\n## Code and Language\n\n[Vat Raghavan](https://github.com/MachinShin) has participated extensively in language discussion and implemented several features.\n\n[Forest Belton](https://github.com/forestbelton) has provided guidance, bugfixes, parser and language commentary.\n\n[Jordan Harbrand](https://github.com/ljharb) suggested two interesting features and provided strong feedback on the initial tutorial draft.\n\nThe biggest thanks must go to [Michael Morgan](https://github.com/msmorgan/), who has debated significant sections of\nthe notation, invented several concepts and operators, helped with the parser, with system nomenclature, for having published\nthe first not-by-me `FSL` machine, for encouragement, and generally just for having been as interested as he has been."},"npm":{"downloads":[{"from":"2022-12-18T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":8},{"from":"2022-12-12T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":1809},{"from":"2022-11-19T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":10601},{"from":"2022-09-20T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":28714},{"from":"2022-06-22T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":43065},{"from":"2021-12-19T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":53949}],"starsCount":1},"github":{"homepage":"http://fsl.tools/","starsCount":218,"forksCount":19,"subscribersCount":7,"issues":{"count":552,"openCount":0,"distribution":{"3600":280,"10800":8,"32400":6,"97200":9,"291600":22,"874800":32,"2624400":37,"7873200":122,"23619600":16,"70858800":19,"212576400":1},"isDisabled":false},"contributors":[{"username":"StoneCypher","commitsCount":836},{"username":"machinshin","commitsCount":18},{"username":"dependabot[bot]","commitsCount":10},{"username":"cohendvir","commitsCount":2},{"username":"technophile77","commitsCount":2},{"username":"msmorgan","commitsCount":1},{"username":"daviddelapena","commitsCount":1},{"username":"tanvirrb","commitsCount":1},{"username":"kraln","commitsCount":1}],"commits":[{"from":"2022-12-12T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":0},{"from":"2022-11-19T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":0},{"from":"2022-09-20T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":0},{"from":"2022-06-22T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":0},{"from":"2021-12-19T00:00:00.000Z","to":"2022-12-19T00:00:00.000Z","count":0}],"statuses":[{"context":"coverage/coveralls","state":"success"}]},"source":{"files":{"readmeSize":38801,"testsSize":240772,"hasNpmIgnore":true,"hasChangelog":true},"badges":[{"urls":{"original":"https://img.shields.io/npm/l/jssm.svg","shields":"https://img.shields.io/npm/l/jssm.svg","content":"https://img.shields.io/npm/l/jssm.json"},"info":{"service":"npm","type":"license","modifiers":{"type":"l"}}},{"urls":{"original":"https://img.shields.io/travis/StoneCypher/jssm.svg","service":"https://api.travis-ci.org/StoneCypher/jssm.svg","shields":"https://img.shields.io/travis/StoneCypher/jssm.svg","content":"https://img.shields.io/travis/StoneCypher/jssm.json"},"info":{"service":"travis","type":"build"}},{"urls":{"original":"https://img.shields.io/coveralls/StoneCypher/jssm.svg","service":"https://coveralls.io/repos/StoneCypher/jssm/badge.svg","shields":"https://img.shields.io/coveralls/StoneCypher/jssm.svg","content":"https://img.shields.io/coveralls/StoneCypher/jssm.json"},"info":{"service":"coveralls","type":"coverage"}},{"urls":{"original":"https://img.shields.io/npm/v/jssm.svg","shields":"https://img.shields.io/npm/v/jssm.svg","content":"https://img.shields.io/npm/v/jssm.json"},"info":{"service":"npm","type":"version","modifiers":{"type":"v"}}},{"urls":{"original":"https://img.shields.io/npm/dt/jssm.svg","shields":"https://img.shields.io/npm/dt/jssm.svg","content":"https://img.shields.io/npm/dt/jssm.json"},"info":{"service":"npm","type":"downloads","modifiers":{"type":"dt"}}}],"linters":["editorconfig","eslint"],"coverage":1}},"evaluation":{"quality":{"carefulness":0.9999999999999999,"tests":1,"health":1,"branding":1},"popularity":{"communityInterest":254,"downloadsCount":9571.333333333334,"downloadsAcceleration":74.25142694063928,"dependentsCount":0},"maintenance":{"releasesFrequency":1,"commitsFrequency":0.9,"openIssues":1,"issuesDistribution":0.9}},"score":{"final":0.7005777875683155,"detail":{"quality":0.9999999999999999,"popularity":0.14454601861413724,"maintenance":0.9999619458667646}}}