(() => { // src/index.ts var Machine = function(...states) { return { states }; }; var State = function(name, ...ons) { return { name, ons }; }; var On = function(eventName, ...reactions) { return { eventName, reactions }; }; var Do = function(fn) { return { type: "Do", fn }; }; var Goto = function(targetStateName) { return { type: "Goto", targetStateName }; }; var Tick = function(doFunctions) { return { doFunctions }; }; function interpret(machine2, options) { let { state, context } = options; if (typeof state === "undefined") { state = machine2.states[0].name; } const interpreter = { machine: machine2, state, context, tickQueues: [] }; console.log(interpreter); send(interpreter, ["entry", null]); return interpreter; } function getState(interpreter) { return interpreter.machine.states.find((state) => state.name === interpreter.state); } function getOns(state, event) { return state.ons.filter((on) => on.eventName === event[0]); } function noop() { } function send(interpreter, event) { const state = getState(interpreter); const onsTree = getOns(state, event); const reactions = onsTree.map((on) => on.reactions).flat(); const indexOfFirstGoto = reactions.findIndex((reaction) => reaction.type === "Goto"); const indexOfFinalReaction = indexOfFirstGoto === -1 ? reactions.length - 1 : indexOfFirstGoto; const reactionsUntilFirstGoto = reactions.slice(0, indexOfFinalReaction + 1); const functionsToRunInTick = reactionsUntilFirstGoto.map((reaction) => { if (reaction.type === "Do") { return reaction.fn; } else if (reaction.type === "Goto") { return (ctx, e, self) => { self.state = reaction.targetStateName; send(self, ["entry", e]); }; } else { return noop; } }); const tick = Tick(functionsToRunInTick); tick.doFunctions.forEach((fn) => { fn(interpreter.context, event, interpreter); }); } // src/tests/00-basic.ts var beginTimer = (ctx, e, self) => { setTimeout(() => { send(self, ["timer-finished", null]); }, 800); }; var log = (ctx, e, self) => { console.log(self.state); }; var machine = Machine( State( "green", On( "entry", Do(beginTimer), Do(log) ), On( "timer-finished", Goto("yellow") ) ), State( "yellow", On( "entry", Do(beginTimer), Do(log) ), On( "timer-finished", Goto("red") ) ), State( "red", On( "entry", Do(beginTimer), Do(log) ), On( "timer-finished", Goto("green") ) ) ); var actor = interpret(machine, { context: {} }); })();