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.
npm install jssmEasy. Small. Fast. TS, es6, es5. Node, Browser. 100% coverage. Property
tests. Fuzz tests. Language tests for a dozen languages and emoji. Easy to
share online. Easy to embed.
Readable, useful state machines as one-liner strings.
5,072 tests, run 5,963 times.
* 5,063 specs with 100.0% coverage.
* 9 fuzz tests with 12.4% coverage.
With 3,007 lines, that's about 1.7 tests per line, or 2.0 generated tests per line.
Meet your new state machine library.
Discord community - Documentation - Issue tracker - CI build history
Wouldn't it be nice if your TypeScript and Javascript state machines were simple and readable one-liners?
`javascript
import { sm } from 'jssm';
const TrafficLight = smRed -> Green -> Yellow -> Red;;`
Wouldn't it be great if they were easy to work with?
`javascript
const log = s => console.log(s);
log( TrafficLight.state() ); // 'Red'
Machine.transition('Green'); // true
log( TrafficLight.state() ); // 'Green'
`
What if the notation supported action names easily?
`javascriptRed 'next' -> Green 'next' -> Yellow 'next' -> Red;
const TLWA = sm; // TLWA = Traffic Light With Actions
log( TLWA.state() ); // 'Red'
TLWA.action('next'); // true
log( TLWA.state() ); // 'Green'
TLWA.action('next'); // true
log( TLWA.state() ); // 'Yellow'
TLWA.action('next'); // true
log( TLWA.state() ); // 'Red'
`
What if integration with the outside was straightforward?
`javascriptRed 'next' -> Green 'next' -> Yellow 'next' -> Red;
const MTL = sm // MTL = More Traffic Lights
.hook('Red', 'Green', () => log('GO GO GO') ) // node will jump the gun when you hit return, though
.hook_entry('Red', () => log('STOP') ); // so put it on one line in node
log( MTL.state() ); // 'Red'
MTL.action('next'); // true, console logs 'GO GO GO'
log( MTL.state() ); // 'Green'
MTL.action('next'); // true
log( MTL.state() ); // 'Yellow'
MTL.action('next'); // true, console logs 'STOP'
log( MTL.state() ); // 'Red'
`
What if the machine followed JS standards, and distinguished refusals as false from mistakes as thrown?
`javascriptRed -> Green -> Yellow -> Red;
const ATL = sm; // ATL = Another Traffic Light
log( ATL.state() ); // 'Red' - uses 1st state unless told otherwise
ATL.transition('Yellow'); // false (Yellow isn't allowed from Red)
ATL.transition('Blue'); // throws (Blue isn't a state at all)
`
What if there were easy convenience notations for lists, and for designating main-path => vs available path -> vs~>
only-when-forced ?
`javascript
const TrafficLightWithOff = sm
Red => Green => Yellow => Red;
[Red Yellow Green] ~> Off -> Red;;`
What if that were easy to render visually?
`javascript
const TrafficLightWithOff = sm
Red => Green => Yellow => Red;
[Red Yellow Green] ~> Off -> Red;;`

What if that were easy to render visually, with styling, in PNG, JPEG, or SVG?
`javascript
const TrafficLightWithOff = sm
Red => Green => Yellow => Red;
[Red Yellow Green] ~> Off -> Red;
flow: left;
state Red : { background-color: pink; corners: rounded; };
state Yellow : { background-color: lightyellow; corners: rounded; };
state Green : { background-color: lightgreen; corners: rounded; };
state Off : {
background-color : steelblue;
text-color : white;
shape : octagon;
linestyle : dashed;
};;`

What if the machine was lighting fast, able to do tens of millions of transitions per second?

* What if the machine and language had extensive 100% test coverage
with thousands of cases?
* What if the machine gave extensive Typescript introspection support?
* What if the machine had been around and active since May 2017?
* What if the machine was MIT licensed, end to end?
But, above all else:
What if it was easy?
Meet JSSM: the Javascript State Machine.
State machines can make your code cleaner, safer, and more trustworthy.
And, with the right language, state machines can be easy and fun.
JSSM is a Javascript state machine implementing Finite State Language, with a terse DSL and a simple API.
100% test coverage; typed with Flowtype. MIT licensed.
The 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.
Visualize with jssm-viz, or at the command line with jssm-viz-cli.
Language test cases for Belorussian, English, German, Hebrew, Italian, Russian, Spanish, Ukrainian, and Emoji. Please help to make sure that your language is well handled!

![GitHub forks]()
![GitHub watchers]()
![GitHub stars]()
![GitHub followers]()








`fsl`
Red 'Proceed' -> Green 'Proceed' -> Yellow 'Proceed' -> Red;
This will produce the following FSM (graphed with jssm-viz):

You'll build an executable state machine.

As usual, a valid question.
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 associateddata 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 RedBlue
1. A sufficiently smart implementation knows there's no such thing as Green
1. A sufficiently smart implementation knows that when in , to be told to Proceed means to go to Yellow, butYellow
when in , 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.
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.
> A state machine in JSSM is defined in one of two ways: through the DSL, or through a datastructure.
So yeah, let's start by getting some terminology out of the way, and then we can go right back to that impenetrable
sentence, so that it'll make sense.
Finite state machines have been around forever, are used by everyone, and are hugely important. As a result, the
terminology is a mess, is in conflict, and is very poorly chosen, in accordince with everything-is-horrible law.
This section describes the terminology as used by this library. The author has done his best to choose a terminology
that matches common use and will be familiar to most. Conflicts are explained in the following section, to keep this
simple.
For this quick overview, we'll define six basic concepts:
1. Finite state machinesMachine
1. sState
1. sCurrent state
1. Transition
1. sAction
1. s
There's other stuff, of course, but these five are enough to wrap your head around finite state machines.
#### Basic concepts
This is a trivial traffic light FSM, with three states, three transitions, and one action:
`fsl`
Red 'Proceed' -> Green 'Proceed' -> Yellow 'Proceed' -> Red;

Let's review its pieces.
* finite state machinesfinite state machine
* A (or FSM) is a collection of states, and rules about how you can transition betweenstate
the s.FSM
* We tend to refer to a design for a machine as "an ."FSM
* In this example, the traffic light's structure is "a traffic light ."
* statesFSM
* s always have at least one state, and nearly always many statesstate
* In this example,
* the s are Red, Yellow, and GreenFSM
* Something made from this will only ever be one of those colors - not, say, Blue
* machinesFSM
* Single instances of an are referred to as a machinemachines
* We might have a thousand instances of the traffic light designed above
* We would say "My intersection has four of the standard three color light FSM."
* current statemachine
* A has a current state, though an FSM does notFSM
* "This specific traffic light is currently Red"
* Traffic lights in general do not have a current color, only specific lights
* s do not have a current state, only specific machinesmachine
* A given will always have exactly one state - never multiple, never none
* transitionsFSM
* s nearly always have transitionsstate
* Transitions govern whether a may be reached from another stateFSM
* This restriction is much of the value of stransition
* In this example,
* the s aremachine
* Green → Yellow
* Yellow → Red
* Red → Green
* a whose current state is Green may switch to Yellow, because there is an appropriate transitionmachine
* a whose current state is Green may not switch to Red, or to Green anew, because there is nomachine
such transition
* A in Yellow which is told to transition to Green (which isn't legal) will know to refuseFSM
* This makes s an effective tool for error prevention
* actionsFSM
* Many s have actions, which represent events from the outside world.action
* In this example, there is only one action - Proceed
* The Proceed is available from all three colorsFSM
* At any time we may indicate to this light to go to its next color, without
taking the time to know what it is.
* This allows s like the light to self-manage.machine
* A in Yellow which is told to take the action Proceed willcurrent state
know on its own to switch its to Red.FSM
* This makes s an effective tool for complexity reduction
Those six ideas in hand - FSMs, states, machines, current state, transitions, and actions - and you're ready
to move forwards.
One other quick definition - a DSL, or domain specific language, is when someone makes a language and embeds it intoReact
a different language, for the purpose of attacking a specific job. When uses a precompiler to embed stuff that
looks like HTML in Javascript, that's a DSL.
This library implements a simple language for defining finite state machines inside of strings. For example, thisDSL defines that 'a -> b;' actually means "create two states, create a transition between them, assign the first asDSL
the initial state", et cetera. That micro-language is the that we'll be referring to a lot, coming up. ThisDSL's parser's original name was jssm-dot, because it's a descendant-in-spirit of an older flowcharting language
DOT, from graphviz, which is also used to make the
visualizations in jssm-viz by way of viz-js.
Enough history lesson. On with the tooling.
So let's put together a trivial four-state traffic light: the three colors, plus Off. This will give us an
opportunity to go over the basic facilities in the language.
At any time, you can take the code and put it into the
graph explorer for an opportunity to mess with the
code as you see fit.
#### 0: Lights always have an off state
Our light will start in the Off state, with the ability to switch to the Red state.
Since that's a normal, not-notable thing, we'll just make it a regular -> legal transition.
`fsl`
Off -> Red;
We will give that transition an action, and call it TurnOn.
`fsl`
Off 'TurnOn' -> Red;
So far, our machine is simple:

#### 1: Traffic lights have a three-color cycle
The main path of a traffic light is cycling from Green to Yellow, then to Red, then back again. Because
this is the main path, we'll mark these steps => main transitions.
`fsl`
Off 'TurnOn' -> Red => Green => Yellow => Red;
We will give those all the same action name, Proceed, indicating "next color" without needing to know what we're
currently on.
`fsl`
Off 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;
Machine's still pretty simple:

#### 2: Traffic lights can be shut down
We'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
be a ~> forced transition.
We could write
`fsl`
Off 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;
Red ~> Off;
Yellow ~> Off;
Green ~> Off;
But that takes a lot of space even with this short list, so, instead we'll use the array notation
`fsl`
Off 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;
[Red Yellow Green] ~> Off;
And we'd like those all to have the action TurnOff, so
`fsl`
Off 'TurnOn' -> Red 'Proceed' => Green 'Proceed' => Yellow 'Proceed' => Red;
[Red Yellow Green] 'TurnOff' ~> Off;
Machine's still not too bad:

That's actually the bulk of the language. There are other little add-ons here and there, but, primarily you now know
how to write a state machine.
Let's load it and use it! 😀
#### loading into node
#### loading into html
#### jssm-viz
#### redistribution on npm
Let's make a state machine for ATMs. In the process, we will use a lot of core concepts of finite state machinesfsl
and of , this library's DSL.
We're going to improve on this NCSU ATM diagram that I
found:

Remember, at any time, you can take the code and put it into the
graph explorer for an opportunity to mess with the
code as you see fit.
#### 0: Empty machine
We'll start with an empty machine.
`fsl`
EmptyWaiting 'Wait' -> EmptyWaiting;

#### 1: Should be able to eject cards
We'll add the ability to physically eject the user's card and reset to the empty and waiting state. Right now it'll
dangle around un-used at the top, but later it'll become useful.
This is expressed as the path EjectCardAndReset -> EmptyWaiting;
`fsl`
EmptyWaiting 'Wait' -> EmptyWaiting;
EjectCardAndReset -> EmptyWaiting;

#### 2: Should be able to insert cards
We'll add the ability to physically insert a card, next. You know, the, uh, thing ATMs are pretty much for.
To get this, add the path leg EmptyWaiting 'InsertCard' -> HasCardNoAuth;
`fsl`
EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;
EjectCardAndReset -> EmptyWaiting;
Notice that the new state, HasCardNoAuth, has been rendered red. This is because it is terminal - there isterminal node
no exit from this node currently. (EmptyAndWaiting did not render that way because it had a transition to itself.)
That will change as we go back to adding more nodes. s are usually either mistakes or the last singlestate of a given FSM.

#### 3: Should be able to cancel and recover the card
Next, we should have a cancel, because the ATM's
exit to the main menu, and return our card credential.
To that end, we add the path HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
`fsl
EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;
HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
EjectCardAndReset -> EmptyWaiting;
`

#### 4: Can give the wrong PIN
Next, let's give the ability to get the password ... wrong. 😂 Because we all know that one ATM that only has the
wrong-PIN path, so, apparently that's a product to someone.
When they get the PIN wrong, they're prompted to try again (or to cancel.)
We'll add the path HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
`fsl
EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;
HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
EjectCardAndReset -> EmptyWaiting;
`

#### 5: Can give the correct PIN
Next, let's give the ability to get the password right.
We'll add two paths. The first gets the password right: HasCardNoAuth 'RightPIN' -> MainMenu;
The second, from our new state MainMenu, gives people the ability to leave: MainMenu 'ExitReturnCard' -> EjectCardAndReset;
`fsl
EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;
HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
HasCardNoAuth 'RightPIN' -> MainMenu;
MainMenu 'ExitReturnCard' -> EjectCardAndReset;
EjectCardAndReset -> EmptyWaiting;
`

#### 6: Can check balance from main menu
Hooray, now we're getting somewhere.
Let's add the ability to check your balance. First pick that from the main menu, then pick which account to see the
balance of, then you're shown a screen with the information you requested; then go back to the main menu.
That's MainMenu 'CheckBalance' -> PickAccount -> DisplayBalance -> MainMenu;.
`fsl
EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;
HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
HasCardNoAuth 'RightPIN' -> MainMenu;
MainMenu 'ExitReturnCard' -> EjectCardAndReset;
MainMenu 'CheckBalance' -> PickAccount -> DisplayBalance -> MainMenu;
EjectCardAndReset -> EmptyWaiting;
`

#### 7: Can deposit money from main menu
Let's add something difficult. Their state machine just proceeds assuming everything is okay.
To desposit money:
1. Accept physical money
2. If accept failed (eg door jammed,) reject physical object, go to main menu
3. If accept succeeded, ask human expected value
4. Pick an account this should go into
5. Contact bank. Request to credit for theoretical physical money.
6. Three results: yes, no, offer-after-audit.
7. If no, reject physical object, go to main menu.
8. If yes, consume physical object, tell user consumed, go to main menu
9. If offer-after-audit, ask human what to do
10. if human-yes, consume physical object, tell user consumed, go to main menu
11. if human-no, reject physical object, go to main menu
Writing this out in code is not only generally longer than the text form, but also error prone and hard to maintain.
... or there's the FSM DSL, which is usually as-brief-as the text, and frequently both briefer and more explicit.
* Rules 1-2: MainMenu 'AcceptDeposit' -> TentativeAcceptMoney 'AcceptFail' -> RejectPhysicalMoney -> MainMenu;TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;
* Rules 3-6: BankResponse 'BankNo' -> RejectPhysicalMoney;
* Rule 7: BankResponse 'BankYes' -> ConsumeMoney -> NotifyConsumed -> MainMenu;
* Rule 8: BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;
* Rules 9-10: BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;
* Rule 11:
Or, as a block,
`fsl
MainMenu 'AcceptDeposit' -> TentativeAcceptMoney;
TentativeAcceptMoney 'AcceptFail' -> RejectPhysicalMoney -> MainMenu;
TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;
BankResponse 'BankNo' -> RejectPhysicalMoney;
BankResponse 'BankYes' -> ConsumeMoney -> NotifyConsumed -> MainMenu;
BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;
BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;
`
Which leaves us with the total code
`fsl
EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;
HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
HasCardNoAuth 'RightPIN' -> MainMenu;
MainMenu 'AcceptDeposit' -> TentativeAcceptMoney;
MainMenu 'ExitReturnCard' -> EjectCardAndReset;
MainMenu 'CheckBalance' -> PickCheckBalanceAccount -> DisplayBalance -> MainMenu;
TentativeAcceptMoney 'AcceptFail' -> RejectPhysicalMoney -> MainMenu;
TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;
BankResponse 'BankNo' -> RejectPhysicalMoney;
BankResponse 'BankYes' -> ConsumeMoney -> NotifyConsumed -> MainMenu;
BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;
BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;
EjectCardAndReset -> EmptyWaiting;
`

#### 8: Can withdraw money from main menu
Let's also be able to take money from the machine. After this, we'll move on, since our example is pretty squarely made
by now.
1. Pick a withdrawl account, or cancel to the main menu
2. Shown a balance, pick a withdrawl amount, or cancel to acct picker
3. Is the withdrawl account too high? If so go to 2
4. Does the machine actually have the money? If not go to 2
5. Otherwise confirm intent w/ human
6. Attempt to post the transaction.
7. If fail, display reason and go to 1
8. If succeed, dispense money and go to main menu
* Rules 1-3: MainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;AcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;
* Rule 4: MachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;
* Rule 5: ConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;
* Rule 6: BankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;
* Rule 7: BankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;
* Rule 8:
Rule 1 canceller: PickWithdrawlAccount 'CancelWithdrawl' -> MainMenu;PickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;
Rule 2 canceller:
Or as a whole, we're adding
`fsl
MainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;
AcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;
MachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;
ConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;
BankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;
BankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;
PickWithdrawlAccount 'CancelWithdrawl' -> MainMenu;
PickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;
`
Which leaves us with
`fsl
EmptyWaiting 'Wait' -> EmptyWaiting 'InsertCard' -> HasCardNoAuth;
HasCardNoAuth 'CancelAuthReturnCard' -> EjectCardAndReset;
HasCardNoAuth 'WrongPIN' -> HasCardNoAuth;
HasCardNoAuth 'RightPIN' -> MainMenu;
MainMenu 'AcceptDeposit' -> TentativeAcceptMoney;
MainMenu 'ExitReturnCard' -> EjectCardAndReset;
MainMenu 'CheckBalance' -> PickCheckBalanceAccount -> DisplayBalance -> MainMenu;
TentativeAcceptMoney 'AcceptFail' -> RejectPhysicalMoney -> MainMenu;
TentativeAcceptMoney 'AcceptSucceed' -> PickDepositAccount -> RequestValue 'TellBank' -> BankResponse;
BankResponse 'BankNo' -> RejectPhysicalMoney;
BankResponse 'BankYes' -> ConsumeMoney -> NotifyConsumed -> MainMenu;
BankResponse 'BankAudit' -> BankAuditOffer 'HumanAcceptAudit' -> ConsumeMoney;
BankAuditOffer 'HumanRejectAudit' -> RejectPhysicalMoney;
MainMenu -> PickWithdrawlAccount -> PickAmount -> AcctHasMoney? 'TooHighForAcct' -> PickWithdrawlAccount;
AcctHasMoney? -> MachineHasMoney? 'MachineLowOnCash' -> PickAmount;
MachineHasMoney? -> ConfirmWithdrawWithHuman 'MakeChanges' -> PickWithdrawlAmount;
ConfirmWithdrawWithHuman 'PostWithdrawl' -> BankWithdrawlResponse;
BankWithdrawlResponse 'WithdrawlFailure' -> WithdrawlFailureExplanation -> PickWithdrawlAccount;
BankWithdrawlResponse 'WithdrawlSuccess' -> DispenseMoney -> MainMenu;
PickWithdrawlAccount 'CancelWithdrawl' -> MainMenu;
PickWithdrawlAmount 'SwitchAccounts' -> PickWithdrawlAccount;
EjectCardAndReset -> EmptyWaiting;
`

As you can see, building up even very complex state machines is actually relatively straightforward, in a short
amount of time.
1. Make a github repository.
1. Put your code in a file inside, with the extension .fslmachine_name
1. Make sure your code contains a
Once done, your work should show up here.
1. Finity 😮
1. Stately.js
1. machina.js
1. Pastafarian
1. Henderson
1. fsm-as-promised
1. state-machine
1. mood
1. FSM Workbench
1. SimpleStateMachine
1. shime/micro-machine
1. soveran/micromachine (ruby)
1. fabiospampinato/FSM
1. HQarroum/FSM
1. Finite-State-Automata
1. finite-state-machine
1. nfm
And some similar stuff:
1. redux-machine
1. ember-fsm
1. State machine cat
1. Workty 😮
1. sam-simpler
1. event_chain
1. DRAKON
1. Yakindu Statechart Tools
1. GraphViz
1. Viz.js, which we use
JSSM and FSL have had a lot of help.
* Mykhaylo Les provided three translation test cases (Ukrainian, Belarussian, and Russian,) and the corresponding Traffic Light translations (also Ukrainian, Belarussian, and Russian.)
* Tanvir Islam provided the Bengali test case, translated the Traffic Light to Bengali, and published the first non-English FSL machine, in Bengali.
* Francisco Junior provided the Portuguese test case and translated the Traffic Light to Portuguese
* Jeff Katz provided the German test case.
* Alex Cresswell provdied the Spanish test case
* Dvir Cohen provided the Hebrew test case.
* David de la Peña provided the French test case
If I've overlooked you, please let me know.
If you'd like to help, it's straightforward.
1. Easy mode: open a PR with this file translated into your language
1. Extra mile: create a new repo containing this file translated
Vat Raghavan has participated extensively in language discussion and implemented several features.
Forest Belton has provided guidance, bugfixes, parser and language commentary.
Jordan Harbrand suggested two interesting features and provided strong feedback on the initial tutorial draft.
The biggest thanks must go to Michael Morgan, who has debated significant sections of
the notation, invented several concepts and operators, helped with the parser, with system nomenclature, for having published
the first not-by-me FSL` machine, for encouragement, and generally just for having been as interested as he has been.