diff --git a/build.mjs b/build.mjs new file mode 100644 index 0000000..9d8cbbb --- /dev/null +++ b/build.mjs @@ -0,0 +1,10 @@ +import * as esbuild from 'esbuild' + +await esbuild.build({ + entryPoints: ['src/index.ts'], + bundle: true, + sourcemap: true, + minify: true, + format: 'esm', + outdir: 'dist', +}) \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 5082620..75ae52c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,2 +1,2 @@ -var d=function(...t){return{states:t}},y=function(t,...e){return{name:t,ons:e}},v=function(t,...e){return{eventName:t,reactions:e}},D=function(t){return{type:"Do",fn:t}},k=function(t){return{type:"Goto",targetStateName:t}},c=function(t){return{doFunctions:t}};function l(t,e){let{state:o,context:s}=e;return typeof o>"u"&&(o=t.states[0].name),{machine:t,state:o,context:s,tickQueues:[]}}function i(t){return t.machine.states.find(e=>e.name===t.state)}function _(t,e){return t.ons.filter(o=>o.eventName===e[0])}function C(){}function G(t,e){let o=i(t),r=_(o,e).map(n=>n.reactions).flat(),a=r.findIndex(n=>n.type==="Goto"),E=a===-1?r.length-1:a,S=r.slice(0,E+1).map(n=>n.type==="Do"?n.fn:n.type==="Goto"?(p,f,T)=>{T.state=n.targetStateName}:C);c(S).doFunctions.forEach(n=>{n(t.context,e,t)})}var m=function(){},A=function(){};export{D as Do,k as Goto,d as Machine,v as On,m as Spawn,y as State,A as Unspawn,l as interpret,G as send}; +var l=function(...t){return{states:t}},g=function(t,...n){return{name:t,eventReactionCouplings:n}},y=function(t,...n){return{eventName:t,reactions:n}},E=function(t){return{type:"SideEffect",fn:t}},S=function(t){return{type:"Goto",targetStateName:t}},v=function(t){return{type:"ContextMutation",fn:t}};function d(t,n){let{state:e,context:i}=n;typeof e>"u"&&(e=t.states[0].name);let o={machine:t,state:e,context:i,eventQueue:[],isTransitioning:!1,subscriptions:{}};return c(o,["entry",null]),o}function T(t){return t.machine.states.find(n=>n.name===t.state)}function p(t,n){return t.eventReactionCouplings.filter(e=>e.eventName===n[0])}function c(t,n){if(t.eventQueue.push(n),t.isTransitioning===!1){for(t.isTransitioning=!0;t.eventQueue.length>0;)_(t);t.isTransitioning=!1,Object.values(t.subscriptions).forEach(e=>{e(t)})}}var C=c;function _(t){let n=t.eventQueue.shift();if(typeof n<"u"){let e=T(t),o=p(e,n).map(a=>a.reactions).flat(),{sideEffects:u,contextMutations:f,goto_:r}=x(o);u.forEach(a=>{a.fn(t.context,n,t)}),f.forEach(a=>{t.context=a.fn(t.context,n,t)}),r!==null&&(c(t,["exit",null]),t.state=r.targetStateName,c(t,["entry",null]))}}function x(t){let n=[],e=[],i=null;return t.forEach(o=>{o.type==="SideEffect"?n.push(o):o.type==="ContextMutation"?e.push(o):o.type==="Goto"&&(i=o)}),{sideEffects:n,contextMutations:e,goto_:i}}var s=0;function M(t,n){return s++,t.subscriptions[s.toString()]=n,s}function b(t,n){delete t.subscriptions[n.toString()]}var h=function(){},R=function(){};export{v as Context,S as Goto,l as Machine,y as On,E as SideEffect,h as Spawn,g as State,R as Unspawn,C as enqueue,d as interpret,c as send,M as subscribe,b as unsubscribe}; //# sourceMappingURL=index.js.map diff --git a/dist/index.js.map b/dist/index.js.map index cbb5705..049b441 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/index.ts"], - "sourcesContent": ["type Event_T = [name:string, payload:any];\nexport interface Machine_T {\n states: Array>\n}\nexport interface State_T {\n name: S;\n ons: Array>;\n}\nexport interface On_T {\n eventName: E[0];\n reactions: Array | Goto_T>;\n};\nexport interface Do_T {\n type: 'Do';\n fn: DoFn_T;\n};\nexport type DoFn_T = (ctx:C,e:E,self:Interpreter_T)=>any;\nexport interface Goto_T {\n type: 'Goto';\n targetStateName: S;\n};\n\nexport const Machine = function(...states:Array>) : Machine_T { return {states}; };\nexport const State = function(name:S, ...ons:Array>) : State_T{ return {name, ons}; };\nexport const On = function(eventName:E[0], ...reactions:Array | Goto_T>) : On_T{ return {eventName, reactions}; };\nexport const Do = function(fn:DoFn_T) : Do_T{ return {type:'Do', fn}; };\nexport const Goto = function(targetStateName:S) : Goto_T { return {type:'Goto', targetStateName} };\n\ninterface Tick_T {\n doFunctions: Array>\n};\nconst Tick = function(doFunctions : Array>) : Tick_T{ return {doFunctions}; };\n\n\nexport interface Interpreter_T {\n machine: Machine_T;\n state: S;\n context: C;\n tickQueues:Array>\n}\ntype TickQueue_T = Array>;\nexport function interpret(machine:Machine_T, options:{state?:S, context:C}) : Interpreter_T{\n let {state, context} = options;\n if(typeof state === 'undefined'){ state = machine.states[0].name; }\n return {machine, state, context, tickQueues:[]};\n}\n\n/** Helper function for `send()`\n */\nfunction getState(interpreter : Interpreter_T) : State_T{\n return interpreter.machine.states.find((state)=>state.name===interpreter.state) as unknown as State_T;\n}\n/** Helper function for `send()`\n */\nfunction getOns(state : State_T, event:E) : Array>{\n return state.ons.filter((on)=>on.eventName===event[0]);\n}\n/** Helper function for `send()`\n */\nfunction noop(){}\n/** Inject an Event into the Interpreter's \"tick queue\".\n * \n * An event can be signify something \"new\" happening, such that its reactions should run on the next Tick;\n * or it can signify a milestone \"within\" the current Tick, such that a Tick can be thought of as having \n * \"sub-Ticks\".\n * \n * This distinction is significant for proper ordering of reaction execution, and also for determining\n * whether to run a reaction at all. If an Event is received, and is specified to be applied on a past \n * Tick, it is discarded.\n */\nexport function send(interpreter : Interpreter_T, event:E){\n const state = getState(interpreter);\n const onsTree = getOns(state, event);\n const reactions = onsTree\n .map((on)=>on.reactions)\n .flat();\n const indexOfFirstGoto = reactions.findIndex((reaction)=>reaction.type==='Goto');\n const indexOfFinalReaction = indexOfFirstGoto === -1 ? reactions.length-1 : indexOfFirstGoto;\n const reactionsUntilFirstGoto = reactions.slice(0, indexOfFinalReaction+1);\n const functionsToRunInTick = reactionsUntilFirstGoto\n .map((reaction)=>{\n if(reaction.type === 'Do'){\n return reaction.fn;\n }\n else if(reaction.type === 'Goto'){\n return (ctx:C,e:E,self:Interpreter_T)=>{\n self.state = reaction.targetStateName;\n };\n }\n else{\n return noop;\n }\n });\n const tick = Tick(functionsToRunInTick);\n tick.doFunctions.forEach((fn)=>{ fn(interpreter.context, event, interpreter); });\n}\n\nexport const Spawn = function(){};\nexport const Unspawn = function(){};"], - "mappings": "AAsBO,IAAMA,EAAU,YAAmCC,EAAiD,CAAE,MAAO,CAAC,OAAAA,CAAM,CAAG,EACjHC,EAAQ,SAAgCC,KAAWC,EAAwC,CAAE,MAAO,CAAC,KAAAD,EAAM,IAAAC,CAAG,CAAG,EACjHC,EAAK,SAAgCC,KAAmBC,EAAuD,CAAE,MAAO,CAAC,UAAAD,EAAW,UAAAC,CAAS,CAAG,EAChJC,EAAK,SAAiCC,EAA+B,CAAE,MAAO,CAAC,KAAK,KAAM,GAAAA,CAAE,CAAG,EAC/FC,EAAO,SAAYC,EAA+B,CAAE,MAAO,CAAC,KAAK,OAAQ,gBAAAA,CAAe,CAAE,EAKjGC,EAAO,SAAgCC,EAAmD,CAAE,MAAO,CAAC,YAAAA,CAAW,CAAG,EAUjH,SAASC,EAAiCC,EAA0BC,EAAqD,CAC9H,GAAI,CAAC,MAAAC,EAAO,QAAAC,CAAO,EAAIF,EACvB,OAAG,OAAOC,EAAU,MAAcA,EAAQF,EAAQ,OAAO,CAAC,EAAE,MACrD,CAAC,QAAAA,EAAS,MAAAE,EAAO,QAAAC,EAAS,WAAW,CAAC,CAAC,CAChD,CAIA,SAASC,EAAgCC,EAAoD,CAC3F,OAAOA,EAAY,QAAQ,OAAO,KAAMH,GAAQA,EAAM,OAAOG,EAAY,KAAK,CAChF,CAGA,SAASC,EAA8BJ,EAAwBK,EAA6B,CAC1F,OAAOL,EAAM,IAAI,OAAQM,GAAKA,EAAG,YAAYD,EAAM,CAAC,CAAC,CACvD,CAGA,SAASE,GAAM,CAAC,CAWT,SAASC,EAA4BL,EAAoCE,EAAQ,CACtF,IAAML,EAAQE,EAASC,CAAW,EAE5Bb,EADUc,EAAOJ,EAAOK,CAAK,EAEhC,IAAKC,GAAKA,EAAG,SAAS,EACtB,KAAK,EACFG,EAAmBnB,EAAU,UAAWoB,GAAWA,EAAS,OAAO,MAAM,EACzEC,EAAuBF,IAAqB,GAAKnB,EAAU,OAAO,EAAImB,EAEtEG,EAD0BtB,EAAU,MAAM,EAAGqB,EAAqB,CAAC,EAEtE,IAAKD,GACDA,EAAS,OAAS,KACZA,EAAS,GAEVA,EAAS,OAAS,OACjB,CAACG,EAAMC,EAAIC,IAA4B,CAC5CA,EAAK,MAAQL,EAAS,eACxB,EAGOH,CAEV,EACUZ,EAAKiB,CAAoB,EACjC,YAAY,QAASpB,GAAK,CAAEA,EAAGW,EAAY,QAASE,EAAOF,CAAW,CAAG,CAAC,CACjF,CAEO,IAAMa,EAAQ,UAAU,CAAC,EACnBC,EAAU,UAAU,CAAC", - "names": ["Machine", "states", "State", "name", "ons", "On", "eventName", "reactions", "Do", "fn", "Goto", "targetStateName", "Tick", "doFunctions", "interpret", "machine", "options", "state", "context", "getState", "interpreter", "getOns", "event", "on", "noop", "send", "indexOfFirstGoto", "reaction", "indexOfFinalReaction", "functionsToRunInTick", "ctx", "e", "self", "Spawn", "Unspawn"] + "sourcesContent": ["export type Event_T = [name:string, payload:any];\nexport interface Machine_T {\n states: Array\n}\nexport interface State_T {\n name: string;\n eventReactionCouplings: Array;\n}\nexport interface EventReactionCouplings_T {\n eventName: string;\n reactions: Array;\n};\nexport type Reaction_T = SideEffect_T | ContextMutation_T | Goto_T;\nexport interface SideEffect_T {\n type: 'SideEffect';\n fn: SideEffectFunction_T;\n};\nexport type SideEffectFunction_T = (ctx:any,e:Event_T,self:Interpreter_T)=>void;\nexport interface ContextMutation_T {\n type: 'ContextMutation';\n fn: ContextMutationFunction_T;\n};\nexport type ContextMutationFunction_T = (ctx:any,e:Event_T,self:Interpreter_T)=>any;\nexport interface Goto_T {\n type: 'Goto';\n targetStateName: string;\n};\n\nexport const Machine = function(...states:Array) : Machine_T { return {states}; };\nexport const State = function(name:string, ...eventReactionCouplings:Array) : State_T{ return {name, eventReactionCouplings}; };\nexport const On = function(eventName:string, ...reactions:Array) : EventReactionCouplings_T{ return {eventName, reactions}; };\nexport const SideEffect = function(fn:SideEffectFunction_T) : SideEffect_T{ return {type:'SideEffect', fn}; };\nexport const Goto = function(targetStateName:string) : Goto_T { return {type:'Goto', targetStateName} };\nexport const Context = function(fn:ContextMutationFunction_T) : ContextMutation_T { return {type:'ContextMutation', fn} };\n\n\n\n\n\nexport interface Interpreter_T {\n machine: Machine_T;\n state: string;\n context: any;\n eventQueue:Array;\n isTransitioning: boolean;\n subscriptions: Record\n}\nexport function interpret(machine:Machine_T, options:{state?:string, context:any}) : Interpreter_T{\n let {state, context} = options;\n if(typeof state === 'undefined'){ state = machine.states[0].name; }\n const interpreter = {machine, state, context, eventQueue:[], isTransitioning:false, subscriptions: {}}\n send(interpreter, ['entry', null] );\n return interpreter;\n}\n\n/** Helper function for `send()`\n */\nfunction getState(interpreter : Interpreter_T) : State_T{\n return interpreter.machine.states.find((state)=>state.name===interpreter.state) as unknown as State_T;\n}\n/** Helper function for `send()`\n */\nfunction getMatchingEventReactionCouplings(state : State_T, event:Event_T) : Array{\n return state.eventReactionCouplings.filter((eventReactionCoupling)=>eventReactionCoupling.eventName===event[0]);\n}\n/** Inject an Event into the Interpreter's \"tick queue\".\n * \n * An event can be signify something \"new\" happening, such that its reactions should run on the next Tick;\n * or it can signify a milestone \"within\" the current Tick, such that a Tick can be thought of as having \n * \"sub-Ticks\".\n * \n * This distinction is significant for proper ordering of reaction execution, and also for determining\n * whether to run a reaction at all. If an Event is received, and is specified to be applied on a past \n * Tick, it is discarded.\n */\nexport function send(interpreter : Interpreter_T, event:Event_T){\n interpreter.eventQueue.push(event);\n if(interpreter.isTransitioning === false){\n interpreter.isTransitioning = true;\n while(interpreter.eventQueue.length > 0){\n processNextEvent(interpreter);\n }\n interpreter.isTransitioning = false;\n // only run subscriptions here, once the machine's state has settled:\n Object.values(interpreter.subscriptions).forEach((subscriptionCallbackFunction)=>{ subscriptionCallbackFunction(interpreter); });\n }\n}\nexport const enqueue = send;\nfunction processNextEvent(interpreter:Interpreter_T){\n const nextEvent = interpreter.eventQueue.shift();\n if(typeof nextEvent !== 'undefined'){\n const state = getState(interpreter);\n const eventReactionCouplings = getMatchingEventReactionCouplings(state, nextEvent);\n const reactions = eventReactionCouplings\n .map((eventReactionCoupling)=>eventReactionCoupling.reactions)\n .flat();\n const {sideEffects, contextMutations, goto_} = categorizeReactions(reactions);\n // can process sideEffects in parallel:\n sideEffects.forEach((sideEffect)=>{\n sideEffect.fn(interpreter.context, nextEvent, interpreter);\n });\n // must process contextMutations in-series:\n contextMutations.forEach((contextMutation)=>{\n interpreter.context = contextMutation.fn(interpreter.context, nextEvent, interpreter);\n });\n // processing of `goto` must be last:\n if(goto_ !== null){\n send(interpreter, ['exit', null]);\n interpreter.state = goto_.targetStateName;\n send(interpreter, ['entry', null]);\n }\n }\n}\nfunction categorizeReactions(reactions:Array) : {sideEffects:Array, contextMutations:Array, goto_:Goto_T|null}{\n let \n sideEffects:Array = [], \n contextMutations:Array = [], \n goto_:Goto_T|null = null;\n reactions.forEach((reaction)=>{\n if(reaction.type === 'SideEffect'){\n sideEffects.push(reaction);\n }\n else if(reaction.type === 'ContextMutation'){\n contextMutations.push(reaction);\n }\n else if(reaction.type === 'Goto'){\n goto_ = reaction;\n }\n });\n return {sideEffects, contextMutations, goto_};\n}\n\nexport type SubscriptionCallbackFunction_T = (self:Interpreter_T)=>void;\nlet subscriptionId : number = 0;\nexport function subscribe(interpreter:Interpreter_T, callback:SubscriptionCallbackFunction_T){\n subscriptionId++;\n interpreter.subscriptions[subscriptionId.toString()] = callback;\n return subscriptionId;\n}\nexport function unsubscribe(interpreter:Interpreter_T, subscriptionId:string){\n delete interpreter.subscriptions[subscriptionId.toString()];\n}\n\nexport const Spawn = function(){};\nexport const Unspawn = function(){};\n\n/*\nexport function useMachine(machine, options){\n return useMemo(()=>interpret(AppMachine, {context:{}}),[]);\n}\n*/"], + "mappings": "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", + "names": ["Machine", "states", "State", "name", "eventReactionCouplings", "On", "eventName", "reactions", "SideEffect", "fn", "Goto", "targetStateName", "Context", "interpret", "machine", "options", "state", "context", "interpreter", "send", "getState", "getMatchingEventReactionCouplings", "event", "eventReactionCoupling", "processNextEvent", "subscriptionCallbackFunction", "enqueue", "nextEvent", "sideEffects", "contextMutations", "goto_", "categorizeReactions", "sideEffect", "contextMutation", "reaction", "subscriptionId", "subscribe", "callback", "unsubscribe", "Spawn", "Unspawn"] } diff --git a/src/index.ts b/src/index.ts index 95dfe1c..9457263 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,11 +43,12 @@ export interface Interpreter_T { context: any; eventQueue:Array; isTransitioning: boolean; + subscriptions: Record } export function interpret(machine:Machine_T, options:{state?:string, context:any}) : Interpreter_T{ let {state, context} = options; if(typeof state === 'undefined'){ state = machine.states[0].name; } - const interpreter = {machine, state, context, eventQueue:[], isTransitioning:false} + const interpreter = {machine, state, context, eventQueue:[], isTransitioning:false, subscriptions: {}} send(interpreter, ['entry', null] ); return interpreter; } @@ -80,6 +81,8 @@ export function send(interpreter : Interpreter_T, event:Event_T){ processNextEvent(interpreter); } interpreter.isTransitioning = false; + // only run subscriptions here, once the machine's state has settled: + Object.values(interpreter.subscriptions).forEach((subscriptionCallbackFunction)=>{ subscriptionCallbackFunction(interpreter); }); } } export const enqueue = send; @@ -102,6 +105,7 @@ function processNextEvent(interpreter:Interpreter_T){ }); // processing of `goto` must be last: if(goto_ !== null){ + send(interpreter, ['exit', null]); interpreter.state = goto_.targetStateName; send(interpreter, ['entry', null]); } @@ -126,5 +130,22 @@ function categorizeReactions(reactions:Array) : {sideEffects:Arrayvoid; +let subscriptionId : number = 0; +export function subscribe(interpreter:Interpreter_T, callback:SubscriptionCallbackFunction_T){ + subscriptionId++; + interpreter.subscriptions[subscriptionId.toString()] = callback; + return subscriptionId; +} +export function unsubscribe(interpreter:Interpreter_T, subscriptionId:string){ + delete interpreter.subscriptions[subscriptionId.toString()]; +} + export const Spawn = function(){}; -export const Unspawn = function(){}; \ No newline at end of file +export const Unspawn = function(){}; + +/* +export function useMachine(machine, options){ + return useMemo(()=>interpret(AppMachine, {context:{}}),[]); +} +*/ \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..6100268 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "emitDeclarationOnly": true, + "declaration": true, + "lib": ["ES2020"] + } +} \ No newline at end of file