Skip to content

Instantly share code, notes, and snippets.

@sramam
Created March 17, 2018 20:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sramam/fba55f5325a8c398870292e1f3cada05 to your computer and use it in GitHub Desktop.
Save sramam/fba55f5325a8c398870292e1f3cada05 to your computer and use it in GitHub Desktop.
A simple bank-account FSM, implemented in javascript-state-machine
const StateMachine = require('javascript-state-machine');
const Account = StateMachine.factory({
init: 'open',
transitions: [
// open state
{name: 'deposit', from: 'open', to: 'open'},
{name: 'withdraw', from: 'open', to: 'open'},
{name: 'available', from: 'open', to: 'open'},
{name: 'placeHold', from: 'open', to: 'held'},
{name: 'close', from: 'open', to: 'closed'},
// held state
{name: 'deposit', from: 'held', to: 'held'},
{name: 'available', from: 'held', to: 'held'},
{name: 'removeHold', from: 'held', to: 'open'},
{name: 'close', from: 'held', to: 'closed'},
// closed state
{name: 'reopen', from: 'closed', to: 'open'},
],
data: function(accountBalance) {
return { accountBalance: accountBalance || 0 };
},
methods:{
onDeposit: function(lc, amount) {
if (amount < 0) {
console.log(`ERROR: cannot deposit a negative amount`);
return false;
}
this.accountBalance += amount;
},
onWithdraw: function(lc, amount) {
if (this.accountBalance < amount) {
console.log(`ERROR: ${amount} is more than you have in the account! Cannot withdraw this amount.`);
return false;
}
this.accountBalance -= amount;
},
onInvalidTransition: function(event, from, to) {
console.log(`ERROR: It's not possible to ${event} from an account that is ${from} `);
},
balance: function() {
if (!this.can('available')) {
console.log(`ERROR: cannot call available in ${this.state}`);
return false;
}
return this.accountBalance;
},
statement: function () {
console.log(`Account is ${this.state} with a balance of ${this.balance()}`)
}
}
});
const account = new Account(10);
// legal operations on an open account
account.statement();
account.deposit(5);
account.statement();
account.withdraw(10);
account.statement();
account.withdraw(10);
account.statement();
// moving states
account.placeHold();
account.statement();
account.removeHold();
account.close();
account.statement();
account.reopen();
account.statement();
// move state to test illegal operations
account.placeHold();
account.withdraw(1);
account.removeHold();
account.withdraw(1);
account.statement();
// Visualization also built in
const visualize = require('javascript-state-machine/lib/visualize');
const fs = require('fs');
const viz = require('viz.js');
const dot = visualize(account);
const svg = viz(dot, { format: "svg"});
fs.writeFileSync('./account.svg', svg, 'utf8');
fs.writeFileSync('./account.dot', dot, 'utf8');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment