Comparing version 3.0.4 to 3.1.0
@@ -1,1 +0,1 @@ | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.xstate=e():t.xstate=e()}(this,function(){return function(t){function e(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=4)}([function(t,e,n){"use strict";function i(t){try{return"string"==typeof t||"number"==typeof t?""+t:t.type}catch(t){throw new Error("Events must be strings or objects with a string event.type property.")}}function r(t){try{return Array.isArray(t)?t:t.toString().split(".")}catch(e){throw new Error("'"+t+"' is not a valid state path.")}}function a(t){if(t instanceof s.State)return t.value;if("object"==typeof t&&!(t instanceof s.State))return t;var e=r(t);if(1===e.length)return e[0];for(var n={},i=n,a=0;a<e.length-1;a++)a===e.length-2?i[e[a]]=e[a+1]:(i[e[a]]={},i=i[e[a]]);return n}function o(t,e){var n={};return Object.keys(t).forEach(function(i){n[i]=e(t[i],i,t)}),n}Object.defineProperty(e,"__esModule",{value:!0});var s=n(2);e.getEventType=i,e.toStatePath=r,e.toTrie=a,e.mapValues=o},function(t,e,n){"use strict";function i(t){return new f(t)}var r=this&&this.__assign||Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++){e=arguments[n];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])}return t};Object.defineProperty(e,"__esModule",{value:!0});var a=n(0),o=n(3);e.matchesState=o.default;var s=n(6);e.mapState=s.default;var c=n(2);e.State=c.State;var u=".",f=function(){function t(e){var n=this;this.config=e,this.__cache={events:void 0,relativeValue:new Map,initialState:void 0},this.key=e.key||"(machine)",this.parent=e.parent,this.machine=this.parent?this.parent.machine:this,this.id=this.parent?this.parent.id+u+this.key:this.key,this.relativeId=this.parent&&this.parent.parent?this.parent.relativeId+u+this.key:this.key,this.initial=e.initial,this.parallel=!!e.parallel,this.states=e.states?a.mapValues(e.states,function(e,i){return new t(r({},e,{key:i,parent:n}))}):{},this.on=e.on,this.strict=!!e.strict,this.onEntry=e.onEntry?[].concat(e.onEntry):void 0,this.onExit=e.onExit?[].concat(e.onExit):void 0}return t.prototype.getStateNodes=function(t){var e=this,n=t instanceof c.State?t.value:a.toTrie(t);if("string"==typeof n){var i=this.states[n].initial;return i?this.getStateNodes((o={},o[n]=i,o)):[this.states[n]]}var r=Object.keys(n);return r.map(function(t){return e.states[t]}).concat(r.map(function(t){return e.states[t].getStateNodes(n[t])}).reduce(function(t,e){return t.concat(e)}));var o},t.prototype.handles=function(t){var e=a.getEventType(t);return!!this.on&&e in this.on},t.prototype.transition=function(t,e,n){if(this.strict){var i=a.getEventType(e);if(-1===this.events.indexOf(i))throw new Error("Machine '"+this.id+"' does not accept event '"+i+"'")}var r=this.transitionStateValue(t,e,n),o=r[0],s=r[1];return o?new c.State(o,c.State.from(t),s.onExit.concat(s.actions).concat(s.onEntry)):c.State.inert(t)},t.prototype.transitionStateValue=function(t,e,n){var i=this,o=t instanceof c.State?t.history:void 0,s=a.toTrie(t);if("string"==typeof s){if(!this.states[s])throw new Error("State '"+s+"' does not exist on machine '"+this.id+"'");var u=this.states[s];if(!u.states||!u.initial)return u.next(e,o?o.value:void 0,n);var f=u.initialState.value;g={},g[s]=f,s=g}var h=a.mapValues(s,function(t,r){var a=o?o.value[r]:void 0,s=new c.State(t,a?c.State.from(a):void 0);return i.states[r].transitionStateValue(s,e,n)});if(Array.prototype.every.call(Object.keys(h),function(t){return void 0===h[t][0]})){if(this.parallel)return[void 0,{onEntry:[],onExit:[],actions:[]}];var l=Object.keys(h)[0],p=this.states[l].next(e,o?o.value:void 0),v=p[0],y=p[1],d=h[l][1];return[v,{onEntry:d.onEntry.concat(y.onEntry),actions:d.actions.concat(y.actions),onExit:d.onExit.concat(y.onExit)}]}this.parallel&&(h=r({},a.mapValues(this.initialState.value,function(t){return[t,{onEntry:[],onExit:[],actions:[]}]}),h));var E={onEntry:[],actions:[],onExit:[]};return[a.mapValues(h,function(t,e){var n=t[0],i=t[1];return i.onEntry&&(r=E.onEntry).push.apply(r,i.onEntry),i.actions&&(a=E.actions).push.apply(a,i.actions),i.onExit&&(o=E.onExit).push.apply(o,i.onExit),n||s[e];var r,a,o}),E];var g},t.prototype.next=function(t,e,n){var i=a.getEventType(t),r={onEntry:[],onExit:[],actions:[]};if(this.onExit&&(r.onExit=this.onExit),!this.on||!this.on[i])return[void 0,r];var o,s=this.on[i];if("string"==typeof s)o=s;else for(var c=0,u=Object.keys(s);c<u.length;c++){var f=u[c],h=s[f],l=h.cond,p=h.actions,v="string"==typeof t||"number"==typeof t?{type:t}:t;if(!l||l(n,v)){o=f,p&&(r.actions=r.actions.concat(p));break}}if(!o)return[void 0,r];var y=a.toStatePath(o),d=this.parent,E=e,g=this.key;if(y.forEach(function(e){if(!d||!d.states)throw new Error("Unable to read '"+e+"'");if("$history"===e)if(E)e="object"==typeof E?Object.keys(E)[0]:E;else{if(!d.initial)throw new Error("Cannot read '$history' from state '"+d.id+"': missing 'initial'");e=d.initial}if(void 0===(d=d.states[e]))throw new Error("Event '"+t+"' on state '"+g+"' leads to undefined state '"+y+"'.");d.onEntry&&(r.onEntry=r.onEntry.concat(d.onEntry)),g=e,E&&(E=E[e])}),!d)throw new Error("no state");for(;d.initial;){if(!d||!d.states)throw new Error("Invalid initial state");d=d.states[d.initial],d.onEntry&&(r.onEntry=r.onEntry.concat(d.onEntry))}return[d.getRelativeValue(this.parent),r]},Object.defineProperty(t.prototype,"initialStateValue",{get:function(){return this.__cache.initialState=this.__cache.initialState||(this.parallel?a.mapValues(this.states,function(t){return t.initialStateValue}):this.initial),this.__cache.initialState},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"initialState",{get:function(){var t=this.initialStateValue;if(!t)throw new Error("Cannot retrieve initial state from simple state '"+this.id+".'");var e=this.getStateNodes(t).reduce(function(t,e){return e.onEntry?t.concat(e.onEntry):t},[]);return new c.State(t,void 0,e)},enumerable:!0,configurable:!0}),t.prototype.getStates=function(t){var e=this;if("string"==typeof t)return[this.states[t]];var n=[];return Object.keys(t).forEach(function(i){n.push.apply(n,e.states[i].getStates(t[i]))}),n},t.prototype.getState=function(t){var e=a.toStatePath(t);try{return e.reduce(function(t,e){if(!t.states)throw new Error("Cannot retrieve subPath '"+e+"' from node with no states");return t.states[e]},this)}catch(e){throw new Error("State '"+t+" does not exist on machine '"+this.id+"'")}},Object.defineProperty(t.prototype,"events",{get:function(){if(this.__cache.events)return this.__cache.events;var t=this.states,e=new Set(this.on?Object.keys(this.on):void 0);return t&&Object.keys(t).forEach(function(n){var i=t[n];if(i.states)for(var r=0,a=i.events;r<a.length;r++){var o=a[r];e.add(""+o)}}),this.__cache.events=Array.from(e)},enumerable:!0,configurable:!0}),t.prototype.getRelativeValue=function(t){var e=t?this.__cache.relativeValue.get(t):void 0;if(e)return e;for(var n=this.initialStateValue,i=n?(s={},s[this.key]=n,s):this.key,a=this.parent;a&&a!==t;){var o=a.initialStateValue;c={},c[a.key]="object"==typeof o&&"object"==typeof i?r({},o,i):i,i=c,a=a.parent}return this.__cache.relativeValue.set(t,i),i;var s,c},t}();e.StateNode=f,e.Machine=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n(5),r=n(0),a=function(){function t(t,e,n){void 0===n&&(n=[]),this.value=t,this.history=e,this.actions=n}return t.from=function(e){return e instanceof t?e:new t(r.toTrie(e))},t.inert=function(e){return e instanceof t?e.actions.length?new t(e.value,e.history,[]):e:t.from(e)},t.prototype.toString=function(){if("string"==typeof this.value)return this.value;for(var t=[],e=this.value;;){if("string"==typeof e){t.push(e);break}var n=Object.keys(e),r=n[0];if(n.slice(1).length)return;t.push(r),e=e[r]}return t.join(i.STATE_DELIMITER)},t}();e.State=a},function(t,e,n){"use strict";function i(t,e){var n=r.toTrie(t),a=r.toTrie(e);return"string"==typeof a?"string"==typeof n?a===n:a in n:"string"==typeof n?n in a:Object.keys(n).every(function(t){return t in a&&i(n[t],a[t])})}Object.defineProperty(e,"__esModule",{value:!0});var r=n(0);e.default=i},function(t,e,n){n(1),t.exports=n(1)},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.STATE_DELIMITER="."},function(t,e,n){"use strict";function i(t,e){var n;return Object.keys(t).forEach(function(t){r.default(t,e)&&(!n||e.length>n.length)&&(n=t)}),t[n]}Object.defineProperty(e,"__esModule",{value:!0});var r=n(3);e.default=i}])}); | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.xstate=e():t.xstate=e()}(this,function(){return function(t){function e(i){if(n[i])return n[i].exports;var a=n[i]={i:i,l:!1,exports:{}};return t[i].call(a.exports,a,a.exports,e),a.l=!0,a.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=4)}([function(t,e,n){"use strict";function i(t){try{return"string"==typeof t||"number"==typeof t?""+t:t.type}catch(t){throw new Error("Events must be strings or objects with a string event.type property.")}}function a(t){try{return Array.isArray(t)?t:t.toString().split(".")}catch(e){throw new Error("'"+t+"' is not a valid state path.")}}function r(t){if(t instanceof s.State)return t.value;if("object"==typeof t&&!(t instanceof s.State))return t;var e=a(t);if(1===e.length)return e[0];for(var n={},i=n,r=0;r<e.length-1;r++)r===e.length-2?i[e[r]]=e[r+1]:(i[e[r]]={},i=i[e[r]]);return n}function o(t,e){var n={};return Object.keys(t).forEach(function(i){n[i]=e(t[i],i,t)}),n}Object.defineProperty(e,"__esModule",{value:!0});var s=n(2);e.getEventType=i,e.toStatePath=a,e.toTrie=r,e.mapValues=o},function(t,e,n){"use strict";function i(t){return new l(t)}var a=this&&this.__assign||Object.assign||function(t){for(var e,n=1,i=arguments.length;n<i;n++){e=arguments[n];for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a])}return t};Object.defineProperty(e,"__esModule",{value:!0});var r=n(0),o=n(3);e.matchesState=o.default;var s=n(6);e.mapState=s.default;var c=n(2);e.State=c.State;var u=n(7),f=".",l=function(){function t(e){var n=this;this.config=e,this.__cache={events:void 0,relativeValue:new Map,initialState:void 0},this.key=e.key||"(machine)",this.parent=e.parent,this.machine=this.parent?this.parent.machine:this,this.id=this.parent?this.parent.id+f+this.key:this.key,this.relativeId=this.parent&&this.parent.parent?this.parent.relativeId+f+this.key:this.key,this.initial=e.initial,this.parallel=!!e.parallel,this.states=e.states?r.mapValues(e.states,function(e,i){return new t(a({},e,{key:i,parent:n}))}):{},this.on=e.on,this.strict=!!e.strict,this.onEntry=e.onEntry?[].concat(e.onEntry):void 0,this.onExit=e.onExit?[].concat(e.onExit):void 0,this.data=e.data,this.activities=e.activities}return t.prototype.getStateNodes=function(t){var e=this,n=t instanceof c.State?t.value:r.toTrie(t);if("string"==typeof n){var i=this.states[n].initial;return i?this.getStateNodes((o={},o[n]=i,o)):[this.states[n]]}var a=Object.keys(n);return a.map(function(t){return e.states[t]}).concat(a.map(function(t){return e.states[t].getStateNodes(n[t])}).reduce(function(t,e){return t.concat(e)}));var o},t.prototype.handles=function(t){var e=r.getEventType(t);return!!this.on&&e in this.on},t.prototype.transition=function(t,e,n){if(this.strict){var i=r.getEventType(e);if(-1===this.events.indexOf(i))throw new Error("Machine '"+this.id+"' does not accept event '"+i+"'")}var a=this.transitionStateValue(t,e,n),o=this.stateTransitionToState(a,t);if(!o)return c.State.inert(t);var s,u=o;do{s=u,u=this.stateTransitionToState(this.transitionStateValue(s,"",n),s)}while(u);return s},t.prototype.stateTransitionToState=function(t,e){var n=t.stateValue,i=t.actions,r=t.activities;if(n){var o=e instanceof c.State?e.activities:void 0,s=a({},o,r);return new c.State(n,c.State.from(e),i?i.onExit.concat(i.actions).concat(i.onEntry):[],s,this.getStateNodes(n).reduce(function(t,e){return t[e.id]=e.data,t},{}))}},t.prototype.transitionStateValue=function(t,e,n){var i=this,o=t instanceof c.State?t.history:void 0,s=r.toTrie(t);if("string"==typeof s){if(!this.states[s])throw new Error("State '"+s+"' does not exist on machine '"+this.id+"'");var u=this.states[s];if(!u.states||!u.initial)return u.next(e,o?o.value:void 0,n);var f=u.initialState.value;m={},m[s]=f,s=m}var l=[],h=r.mapValues(s,function(t,a){var r=o?o.value[a]:void 0,s=new c.State(t,r?c.State.from(r):void 0),u=i.states[a],f=u.transitionStateValue(s,e,n);return f.stateValue||l.push(u.next(e,o?o.value:void 0,n)),f});if(Array.prototype.every.call(Object.keys(h),function(t){return void 0===h[t].stateValue})){if(this.parallel)return l.length?l[0]:{stateValue:void 0,actions:{onEntry:[],onExit:[],actions:[]},activities:void 0};var v=Object.keys(h)[0],p=this.states[v].next(e,o?o.value:void 0,n),y=p.stateValue,d=p.actions,E=p.activities,g=h[v].actions,S=h[v].activities,b=a({},S,E);return{stateValue:y,actions:d?g?{onEntry:g.onEntry.concat(d.onEntry),actions:g.actions.concat(d.actions),onExit:g.onExit.concat(d.onExit)}:d:g,activities:b}}this.parallel&&(h=a({},r.mapValues(this.initialState.value,function(t){return{stateValue:t,actions:{onEntry:[],onExit:[],actions:[]},activities:void 0}}),h));var x={onEntry:[],actions:[],onExit:[]},_={};return{stateValue:r.mapValues(h,function(t,e){var n=t.stateValue,i=t.actions,a=t.activities;return i&&(i.onEntry&&(r=x.onEntry).push.apply(r,i.onEntry),i.actions&&(o=x.actions).push.apply(o,i.actions),i.onExit&&(c=x.onExit).push.apply(c,i.onExit)),a&&Object.assign(_,a),n||s[e];var r,o,c}),actions:x,activities:_};var m},t.prototype.next=function(t,e,n){var i=this,o=r.getEventType(t),s={onEntry:[],onExit:[],actions:[]},c={};if(this.onExit&&(s.onExit=this.onExit),this.activities&&this.activities.forEach(function(t){c[r.getEventType(t)]=!1,s.onExit=s.onExit.concat(u.stop(t))}),!this.on||!this.on[o])return{stateValue:void 0,actions:s,activities:c};var l,h=this.on[o];if("string"==typeof h)l=h;else for(var v=Array.isArray(h)?h:Object.keys(h).map(function(t){return a({},h[t],{target:t})}),p=0,y=v;p<y.length;p++){var d=y[p],E=d,g=E.cond,S=E.actions,b=n||{},x="string"==typeof t||"number"==typeof t?{type:t}:t;if(!g||g(b,x)){l=d.target,S&&(s.actions=s.actions.concat(S));break}}if(!l)return{stateValue:void 0,actions:s,activities:c};var _=r.toStatePath(l),m=this.parent,T=e,V=this.key;if(_.forEach(function(e){if(!m||!m.states)throw new Error("Unable to read '"+e+"'");if("$history"===e)if(T)e="object"==typeof T?Object.keys(T)[0]:T;else{if(!m.initial)throw new Error("Cannot read '$history' from state '"+m.id+"': missing 'initial'");e=m.initial}else if(""===e)return s.onExit=[],void(m=m.states[i.key]);if(void 0===(m=m.states[e]))throw new Error("Event '"+t+"' on state '"+V+"' leads to undefined state '"+_.join(f)+"'.");m.onEntry&&(s.onEntry=s.onEntry.concat(m.onEntry)),m.activities&&m.activities.forEach(function(t){c[r.getEventType(t)]=!0,s.onEntry=s.onEntry.concat(u.start(t))}),V=e,T&&(T=T[e])}),!m)throw new Error("no state");for(;m.initial;){if(!m||!m.states)throw new Error("Invalid initial state");m=m.states[m.initial],m.onEntry&&(s.onEntry=s.onEntry.concat(m.onEntry)),m.activities&&m.activities.forEach(function(t){c[r.getEventType(t)]=!0,s.onEntry=s.onEntry.concat(u.start(t))})}return{stateValue:m.getRelativeValue(this.parent),actions:s,activities:c}},Object.defineProperty(t.prototype,"resolvedStateValue",{get:function(){var t=this.key;return this.parallel?(e={},e[t]=r.mapValues(this.states,function(t){return t.resolvedStateValue[t.key]}),e):this.initial?(n={},n[t]=this.states[this.initial].resolvedStateValue,n):t;var e,n},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"initialStateValue",{get:function(){var t=this.__cache.initialState||(this.parallel?r.mapValues(this.states,function(t){return t.initialStateValue}):this.resolvedStateValue[this.key]);return this.__cache.initialState=t,this.__cache.initialState},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"initialState",{get:function(){var t=this.initialStateValue;if(!t)throw new Error("Cannot retrieve initial state from simple state '"+this.id+".'");var e=this.getStateNodes(t).reduce(function(t,e){return e.onEntry?t.concat(e.onEntry):t},[]);return new c.State(t,void 0,e)},enumerable:!0,configurable:!0}),t.prototype.getStates=function(t){var e=this;if("string"==typeof t)return[this.states[t]];var n=[];return Object.keys(t).forEach(function(i){n.push.apply(n,e.states[i].getStates(t[i]))}),n},t.prototype.getState=function(t){var e=r.toStatePath(t);try{return e.reduce(function(t,e){if(!t.states)throw new Error("Cannot retrieve subPath '"+e+"' from node with no states");return t.states[e]},this)}catch(e){throw new Error("State '"+t+" does not exist on machine '"+this.id+"'")}},Object.defineProperty(t.prototype,"events",{get:function(){if(this.__cache.events)return this.__cache.events;var t=this.states,e=new Set(this.on?Object.keys(this.on):void 0);return t&&Object.keys(t).forEach(function(n){var i=t[n];if(i.states)for(var a=0,r=i.events;a<r.length;a++){var o=r[a];e.add(""+o)}}),this.__cache.events=Array.from(e)},enumerable:!0,configurable:!0}),t.prototype.getRelativeValue=function(t){var e=t?this.__cache.relativeValue.get(t):void 0;if(e)return e;for(var n=this.initialStateValue,i=n?(s={},s[this.key]=n,s):this.key,r=this.parent;r&&r!==t;){var o=r.initialStateValue;c={},c[r.key]=r.parallel&&"object"==typeof o&&"object"==typeof i?a({},o,i):i,i=c,r=r.parent}return this.__cache.relativeValue.set(t,i),i;var s,c},t}();e.StateNode=l,e.Machine=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n(5),a=n(0),r=function(){function t(t,e,n,a,r){void 0===n&&(n=[]),void 0===a&&(a=i.EMPTY_ACTIVITY_MAP),void 0===r&&(r={}),this.value=t,this.history=e,this.actions=n,this.activities=a,this.data=r}return t.from=function(e){return e instanceof t?e:new t(a.toTrie(e))},t.inert=function(e){return e instanceof t?e.actions.length?new t(e.value,e.history,[]):e:t.from(e)},t.prototype.toString=function(){if("string"==typeof this.value)return this.value;for(var t=[],e=this.value;;){if("string"==typeof e){t.push(e);break}var n=Object.keys(e),a=n[0];if(n.slice(1).length)return;t.push(a),e=e[a]}return t.join(i.STATE_DELIMITER)},t}();e.State=r},function(t,e,n){"use strict";function i(t,e){var n=a.toTrie(t),r=a.toTrie(e);return"string"==typeof r?"string"==typeof n?r===n:r in n:"string"==typeof n?n in r:Object.keys(n).every(function(t){return t in r&&i(n[t],r[t])})}Object.defineProperty(e,"__esModule",{value:!0});var a=n(0);e.default=i},function(t,e,n){n(1),t.exports=n(1)},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.STATE_DELIMITER=".",e.EMPTY_ACTIVITY_MAP={}},function(t,e,n){"use strict";function i(t,e){var n;return Object.keys(t).forEach(function(t){a.default(t,e)&&(!n||e.length>n.length)&&(n=t)}),t[n]}Object.defineProperty(e,"__esModule",{value:!0});var a=n(3);e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n(0);e.actionTypes={start:"xstate.start",stop:"xstate.stop",raise:"xstate.raise",send:"xstate.send",cancel:"xstate.cancel"};var a=function(t){return function(e){var n="string"==typeof e||"number"==typeof e?{type:e}:e;return{type:t,activity:i.getEventType(e),data:n}}},r=function(t){return"string"==typeof t||"number"==typeof t?{type:t}:t};e.raise=function(t){return{type:e.actionTypes.raise,event:t}},e.send=function(t,n){return{type:e.actionTypes.send,event:r(t),delay:n?n.delay:void 0,id:n&&void 0!==n.id?n.id:i.getEventType(t)}},e.cancel=function(t){return{type:e.actionTypes.cancel,sendId:t}},e.start=a(e.actionTypes.start),e.stop=a(e.actionTypes.stop)}])}); |
@@ -1,1 +0,1 @@ | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.xstateUtils=e():t.xstateUtils=e()}(this,function(){return function(t){function e(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var r={};return e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=2)}([function(t,e,r){"use strict";function n(t){var e=t.states;return Object.keys(e).reduce(function(t,r){var o=e[r],i=n(e[r]);return t.push.apply(t,[o].concat(i)),t},[])}function o(t){return"string"==typeof t?[t]:Object.keys(t)}function i(t,e){void 0===e&&(e={});var r=t.states;e[t.key]=!0;var n=Object.keys(r).reduce(function(t,n){if(e[n])return t;var o=r[n];return t.push.apply(t,i(o,e)),e[n]=!0,t},[]);if(!t.on)return n;var a=Object.keys(t.on).reduce(function(r,n){if(!t.on||!t.parent)return r;var a=t.parent,s=t.on[n];return s?(o(s).forEach(function(o){var s=a.getState(o),u={event:n,source:t,target:s};r.push(u),e[o]||(r.push.apply(r,i(s,e)),e[o]=!0)}),r):r},[]);return n.concat(a)}function a(t){var e=t.parent?{}:void 0,r={};if(t.on)for(var n=0,o=Object.keys(t.on);n<o.length;n++){var i=o[n];if(t.parent&&e){var s=t.machine.transition(t.relativeId,i);s&&(e[i]={state:s.value})}}if(e&&(r[t.relativeId]=e),t.states)for(var u=0,c=Object.keys(t.states);u<c.length;u++){var f=c[u],v=t.states[f],y=l.mapValues(a(v),function(t){return p({},e,t)});Object.assign(r,y)}return r}function s(t){if(t.states&&t.initial){var e=a(t),r=u(t.initialState),n=(o={},o[r]=[],o);return c(e,r,n),n;var o}}function u(t){if("string"==typeof t)return t;var e=Object.keys(t)[0];return[e].concat(u(t[e])).join(".")}function c(t,e,r,n){void 0===n&&(n=new Set),n.add(e);for(var o=t[e],i=0,a=Object.keys(o);i<a.length;i++){var s=a[i],f=o[s].state;if(f){var p=u(f);(!r[p]||r[p].length>r[e].length+1)&&(r[p]=r[e].concat([{state:e,event:s}]))}}for(var l=0,v=Object.keys(o);l<v.length;l++){var y=v[l],f=o[y].state;if(f){var p=u(f);n.has(p)||c(t,p,r,n)}}return r}function f(t){function e(t,i){if(n.add(t),o.push(t),t===i)console.log(o.join(" > "));else for(var a=0,s=Object.keys(r[t]);a<s.length;a++){var c=s[a],f=r[t][c].state;if(f){var p=u(f);n.has(p)||e(p,i)}}o.pop(),n.delete(t)}if(t.states&&t.initial){var r=a(t),n=new Set,o=[];Object.keys(r).forEach(function(r){e(t.initial,r)})}}var p=this&&this.__assign||Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++){e=arguments[r];for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}return t};Object.defineProperty(e,"__esModule",{value:!0});var l=r(1);e.getNodes=n,e.getEdges=i,e.getAdjacencyMap=a,e.getShortestPaths=s,e.getSimplePaths=f},function(t,e,r){"use strict";function n(t){try{return"string"==typeof t||"number"==typeof t?""+t:t.type}catch(t){throw new Error("Events must be strings or objects with a string event.type property.")}}function o(t){try{return Array.isArray(t)?t:t.toString().split(".")}catch(e){throw new Error("'"+t+"' is not a valid state path.")}}function i(t){if("object"==typeof t&&!(t instanceof s.default))return t;var e=o(t);if(1===e.length)return e[0];for(var r={},n=r,i=0;i<e.length-1;i++)i===e.length-2?n[e[i]]=e[i+1]:(n[e[i]]={},n=n[e[i]]);return r}function a(t,e){var r={};return Object.keys(t).forEach(function(n){r[n]=e(t[n],n,t)}),r}Object.defineProperty(e,"__esModule",{value:!0});var s=r(3);e.getEventType=n,e.toStatePath=o,e.toTrie=i,e.mapValues=a},function(t,e,r){r(0),t.exports=r(0)},function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=r(4),o=r(1),i=function(){function t(t,e,r){this.value=t,this.history=e,this.effects=r}return t.from=function(e){return e instanceof t?e:new t(o.toTrie(e))},t.prototype.toString=function(){if("string"==typeof this.value)return this.value;for(var t=[],e=this.value;;){if("string"==typeof e){t.push(e);break}var r=Object.keys(e),o=r[0];if(r.slice(1).length)return;t.push(o),e=e[o]}return t.join(n.STATE_DELIMITER)},t}();e.default=i},function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.STATE_DELIMITER="."}])}); | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.xstateUtils=e():t.xstateUtils=e()}(this,function(){return function(t){function e(n){if(r[n])return r[n].exports;var a=r[n]={i:n,l:!1,exports:{}};return t[n].call(a.exports,a,a.exports,e),a.l=!0,a.exports}var r={};return e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=2)}([function(t,e,r){"use strict";function n(t){var e=t.states;return Object.keys(e).reduce(function(t,r){var a=e[r],i=n(e[r]);return t.push.apply(t,[a].concat(i)),t},[])}function a(t){return"string"==typeof t?[{target:t}]:Array.isArray(t)?t:Object.keys(t).map(function(e){return p({target:e},t[e])})}function i(t,e){if(void 0===e&&(e={}),t.parallel)return Object.keys(t.states).map(function(e){return i(t.states[e])}).reduce(function(t,e){return t.concat(e)},[]);var r=t.states;e[t.key]=!0;var n=Object.keys(r).reduce(function(t,n){if(e[n])return t;var a=r[n];return t.push.apply(t,i(a,e)),e[n]=!0,t},[]);if(!t.on)return n;var o=Object.keys(t.on).reduce(function(r,n){if(!t.on||!t.parent)return r;var o=t.parent,s=t.on[n];return s?(a(s).forEach(function(a){var s=a.target,u=a.cond,c=o.getState(s),f={event:n,source:t,target:c,cond:u};r.push(f),e[s]||(r.push.apply(r,i(c,e)),e[s]=!0)}),r):r},[]);return n.concat(o)}function o(t){function e(a){var i=JSON.stringify(a);if(!r[i]){r[i]={};for(var o=0,s=n;o<s.length;o++){var u=s[o],c=t.transition(a,u);r[i][u]={state:c.value},e(c.value)}}}var r={},n=t.events;return e(t.initialState.value),r}function s(t){function e(t){var n=JSON.stringify(t);i.add(n);for(var o=r[n],s=0,u=Object.keys(o);s<u.length;s++){var c=u[s],f=o[c].state;if(f){var p=JSON.stringify(v.toTrie(f));(!a[p]||a[p].length>a[n].length+1)&&(a[p]=(a[n]||[]).concat([{state:t,event:c}]))}}for(var l=0,y=Object.keys(o);l<y.length;l++){var h=y[l],f=o[h].state;if(f){var p=JSON.stringify(f);i.has(p)||e(f)}}return a}if(!t.states)return l;var r=o(t),n=JSON.stringify(t.initialState.value),a=(s={},s[n]=[],s),i=new Set;return e(t.initialState.value),a;var s}function u(t){var e=s(t);return Object.keys(e).map(function(t){return{state:JSON.parse(t),path:e[t]}})}function c(t){function e(t,o){if(n.add(t),t===o)i[o]=i[o]||[],i[o].push(a.slice());else for(var s=0,u=Object.keys(r[t]);s<u.length;s++){var c=u[s],f=r[t][c].state;if(f){var p=JSON.stringify(f);n.has(p)||(a.push({state:JSON.parse(t),event:c}),e(p,o))}}a.pop(),n.delete(t)}if(!t.states)return l;var r=o(t),n=new Set,a=[],i={},s=JSON.stringify(t.initialState.value);return Object.keys(r).forEach(function(t){e(s,t)}),i}function f(t){var e=c(t);return Object.keys(e).map(function(t){return{state:JSON.parse(t),paths:e[t]}})}var p=this&&this.__assign||Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++){e=arguments[r];for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a])}return t};Object.defineProperty(e,"__esModule",{value:!0});var v=r(1),l={};e.getNodes=n,e.getEdges=i,e.getAdjacencyMap=o,e.getShortestPaths=s,e.getShortestPathsAsArray=u,e.getSimplePaths=c,e.getSimplePathsAsArray=f},function(t,e,r){"use strict";function n(t){try{return"string"==typeof t||"number"==typeof t?""+t:t.type}catch(t){throw new Error("Events must be strings or objects with a string event.type property.")}}function a(t){try{return Array.isArray(t)?t:t.toString().split(".")}catch(e){throw new Error("'"+t+"' is not a valid state path.")}}function i(t){if(t instanceof s.State)return t.value;if("object"==typeof t&&!(t instanceof s.State))return t;var e=a(t);if(1===e.length)return e[0];for(var r={},n=r,i=0;i<e.length-1;i++)i===e.length-2?n[e[i]]=e[i+1]:(n[e[i]]={},n=n[e[i]]);return r}function o(t,e){var r={};return Object.keys(t).forEach(function(n){r[n]=e(t[n],n,t)}),r}Object.defineProperty(e,"__esModule",{value:!0});var s=r(3);e.getEventType=n,e.toStatePath=a,e.toTrie=i,e.mapValues=o},function(t,e,r){r(0),t.exports=r(0)},function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=r(4),a=r(1),i=function(){function t(t,e,r,a,i){void 0===r&&(r=[]),void 0===a&&(a=n.EMPTY_ACTIVITY_MAP),void 0===i&&(i={}),this.value=t,this.history=e,this.actions=r,this.activities=a,this.data=i}return t.from=function(e){return e instanceof t?e:new t(a.toTrie(e))},t.inert=function(e){return e instanceof t?e.actions.length?new t(e.value,e.history,[]):e:t.from(e)},t.prototype.toString=function(){if("string"==typeof this.value)return this.value;for(var t=[],e=this.value;;){if("string"==typeof e){t.push(e);break}var r=Object.keys(e),a=r[0];if(r.slice(1).length)return;t.push(a),e=e[a]}return t.join(n.STATE_DELIMITER)},t}();e.State=i},function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.STATE_DELIMITER=".",e.EMPTY_ACTIVITY_MAP={}}])}); |
@@ -0,1 +1,3 @@ | ||
import { ActivityMap } from './types'; | ||
export declare const STATE_DELIMITER = "."; | ||
export declare const EMPTY_ACTIVITY_MAP: ActivityMap; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.STATE_DELIMITER = '.'; | ||
exports.EMPTY_ACTIVITY_MAP = {}; |
import { StateNode } from './index'; | ||
import { StateValue, Machine, Event } from './types'; | ||
export interface IEdge { | ||
import { StateValue, Machine, Event, Condition, Action } from './types'; | ||
export interface Edge { | ||
event: string; | ||
source: StateNode; | ||
target: StateNode; | ||
cond?: Condition; | ||
actions: Action[]; | ||
} | ||
export interface INodesAndEdges { | ||
nodes: StateNode[]; | ||
edges: IEdge[]; | ||
edges: Edge[]; | ||
} | ||
export declare function getNodes(node: StateNode): StateNode[]; | ||
export declare function getEdges(node: StateNode, visited?: Record<string, true>): IEdge[]; | ||
export declare function getEdges(node: StateNode): Edge[]; | ||
export interface Segment { | ||
@@ -15,0 +17,0 @@ state: StateValue; |
@@ -16,46 +16,48 @@ "use strict"; | ||
exports.getNodes = getNodes; | ||
function getTransitionStateKeys(transition) { | ||
if (typeof transition === 'string') { | ||
return [transition]; | ||
function getEventEdges(node, event) { | ||
var transitions = node.on[event]; | ||
if (typeof transitions === 'string') { | ||
return [ | ||
{ | ||
source: node, | ||
target: node.parent.getState(transitions), | ||
event: event, | ||
actions: [] | ||
} | ||
]; | ||
} | ||
return Object.keys(transition); | ||
if (Array.isArray(transitions)) { | ||
return transitions.map(function (transition) { | ||
return { | ||
source: node, | ||
target: node.parent.getState(transition.target), | ||
event: event, | ||
actions: transition.actions || [], | ||
cond: transition.cond | ||
}; | ||
}); | ||
} | ||
return Object.keys(transitions).map(function (stateKey) { | ||
return { | ||
source: node, | ||
target: node.parent.getState(stateKey), | ||
event: event, | ||
actions: transitions[stateKey].actions || [], | ||
cond: transitions[stateKey].cond | ||
}; | ||
}); | ||
} | ||
function getEdges(node, visited) { | ||
if (visited === void 0) { visited = {}; } | ||
var states = node.states; | ||
visited[node.key] = true; | ||
var subNodeEdges = Object.keys(states).reduce(function (_edges, key) { | ||
if (visited[key]) { | ||
return _edges; | ||
} | ||
var subState = states[key]; | ||
_edges.push.apply(_edges, getEdges(subState, visited)); | ||
visited[key] = true; | ||
return _edges; | ||
}, []); | ||
if (!node.on) { | ||
return subNodeEdges; | ||
function getEdges(node) { | ||
var edges = []; | ||
if (node.states) { | ||
Object.keys(node.states).forEach(function (stateKey) { | ||
edges.push.apply(edges, getEdges(node.states[stateKey])); | ||
}); | ||
} | ||
var edges = Object.keys(node.on).reduce(function (accEdges, event) { | ||
if (!node.on || !node.parent) { | ||
return accEdges; | ||
} | ||
var parent = node.parent; | ||
var transition = node.on[event]; | ||
if (!transition) { | ||
return accEdges; | ||
} | ||
var subStateKeys = getTransitionStateKeys(transition); | ||
subStateKeys.forEach(function (subStateKey) { | ||
var subNode = parent.getState(subStateKey); | ||
var edge = { event: event, source: node, target: subNode }; | ||
accEdges.push(edge); | ||
if (!visited[subStateKey]) { | ||
accEdges.push.apply(accEdges, getEdges(subNode, visited)); | ||
visited[subStateKey] = true; | ||
} | ||
if (node.on) { | ||
Object.keys(node.on).forEach(function (event) { | ||
edges.push.apply(edges, getEventEdges(node, event)); | ||
}); | ||
return accEdges; | ||
}, []); | ||
return subNodeEdges.concat(edges); | ||
} | ||
return edges; | ||
} | ||
@@ -62,0 +64,0 @@ exports.getEdges = getEdges; |
@@ -1,6 +0,6 @@ | ||
import { Event, StateValue, Transition, Action, StandardMachine, ParallelMachine, SimpleOrCompoundStateNodeConfig, MachineConfig, ParallelMachineConfig, EventType, StandardMachineConfig } from './types'; | ||
import { Event, StateValue, Transition, Action, StandardMachine, ParallelMachine, SimpleOrCompoundStateNodeConfig, MachineConfig, ParallelMachineConfig, EventType, StandardMachineConfig, StateNodeConfig, Activity } from './types'; | ||
import matchesState from './matchesState'; | ||
import mapState from './mapState'; | ||
import { State } from './State'; | ||
declare class StateNode { | ||
declare class StateNode implements StateNodeConfig { | ||
config: SimpleOrCompoundStateNodeConfig | StandardMachineConfig | ParallelMachineConfig; | ||
@@ -16,5 +16,7 @@ key: string; | ||
onExit?: Action[]; | ||
activities?: Activity[]; | ||
strict: boolean; | ||
parent?: StateNode; | ||
machine: StateNode; | ||
data: object | undefined; | ||
private __cache; | ||
@@ -25,4 +27,6 @@ constructor(config: SimpleOrCompoundStateNodeConfig | StandardMachineConfig | ParallelMachineConfig); | ||
transition(state: StateValue | State, event: Event, extendedState?: any): State; | ||
private stateTransitionToState(stateTransition, prevState); | ||
private transitionStateValue(state, event, extendedState?); | ||
private next(event, history?, extendedState?); | ||
private readonly resolvedStateValue; | ||
private readonly initialStateValue; | ||
@@ -29,0 +33,0 @@ readonly initialState: State; |
227
lib/index.js
@@ -18,4 +18,6 @@ "use strict"; | ||
exports.State = State_1.State; | ||
var actions_1 = require("./actions"); | ||
var STATE_DELIMITER = '.'; | ||
var HISTORY_KEY = '$history'; | ||
var NULL_EVENT = ''; | ||
var StateNode = /** @class */ (function () { | ||
@@ -55,2 +57,4 @@ function StateNode(config) { | ||
: undefined; | ||
this.data = config.data; | ||
this.activities = config.activities; | ||
} | ||
@@ -89,7 +93,25 @@ StateNode.prototype.getStateNodes = function (state) { | ||
} | ||
// const stateValue = toTrie(state); | ||
var _a = this.transitionStateValue(state, event, extendedState), nextStateValue = _a[0], nextActions = _a[1]; | ||
if (!nextStateValue) { | ||
var stateTransition = this.transitionStateValue(state, event, extendedState); | ||
var nextState = this.stateTransitionToState(stateTransition, state); | ||
if (!nextState) { | ||
return State_1.State.inert(state); | ||
} | ||
// Try transitioning from "transient" states from the NULL_EVENT | ||
// until a state with non-transient transitions is found | ||
var maybeNextState = nextState; | ||
var nextStateFromInternalTransition; | ||
do { | ||
nextStateFromInternalTransition = maybeNextState; | ||
maybeNextState = this.stateTransitionToState(this.transitionStateValue(nextStateFromInternalTransition, NULL_EVENT, extendedState), nextStateFromInternalTransition); | ||
} while (maybeNextState); | ||
// TODO: handle internally raised events | ||
return nextStateFromInternalTransition; | ||
}; | ||
StateNode.prototype.stateTransitionToState = function (stateTransition, prevState) { | ||
var nextStateValue = stateTransition.stateValue, nextActions = stateTransition.actions, nextActivities = stateTransition.activities; | ||
if (!nextStateValue) { | ||
return undefined; | ||
} | ||
var prevActivities = prevState instanceof State_1.State ? prevState.activities : undefined; | ||
var activities = __assign({}, prevActivities, nextActivities); | ||
return new State_1.State( | ||
@@ -99,5 +121,16 @@ // next state value | ||
// history | ||
State_1.State.from(state), | ||
State_1.State.from(prevState), | ||
// effects | ||
nextActions.onExit.concat(nextActions.actions).concat(nextActions.onEntry)); | ||
nextActions | ||
? nextActions.onExit | ||
.concat(nextActions.actions) | ||
.concat(nextActions.onEntry) | ||
: [], | ||
// activities | ||
activities, | ||
// data | ||
this.getStateNodes(nextStateValue).reduce(function (data, stateNode) { | ||
data[stateNode.id] = stateNode.data; | ||
return data; | ||
}, {})); | ||
}; | ||
@@ -114,2 +147,3 @@ StateNode.prototype.transitionStateValue = function (state, event, extendedState) { | ||
if (subStateNode.states && subStateNode.initial) { | ||
// Get the initial state value | ||
var initialStateValue = subStateNode.initialState.value; | ||
@@ -119,5 +153,8 @@ stateValue = (_a = {}, _a[stateValue] = initialStateValue, _a); | ||
else { | ||
// Transition from the substate | ||
return subStateNode.next(event, history ? history.value : undefined, extendedState); | ||
} | ||
} | ||
// Potential transition tuples from parent state nodes | ||
var potentialStateTransitions = []; | ||
var nextStateValue = utils_1.mapValues(stateValue, function (subStateValue, subStateKey) { | ||
@@ -127,29 +164,48 @@ var subHistory = history ? history.value[subStateKey] : undefined; | ||
var subStateNode = _this.states[subStateKey]; | ||
var nextTuple = subStateNode.transitionStateValue(subState, event, extendedState); | ||
return nextTuple; | ||
var subStateTransition = subStateNode.transitionStateValue(subState, event, extendedState); | ||
if (!subStateTransition.stateValue) { | ||
potentialStateTransitions.push(subStateNode.next(event, history ? history.value : undefined, extendedState)); | ||
} | ||
return subStateTransition; | ||
}); | ||
if (Array.prototype.every.call(Object.keys(nextStateValue), function (key) { | ||
return nextStateValue[key][0] === undefined; | ||
return nextStateValue[key].stateValue === undefined; | ||
})) { | ||
if (this.parallel) { | ||
return [undefined, { onEntry: [], onExit: [], actions: [] }]; | ||
if (potentialStateTransitions.length) { | ||
return potentialStateTransitions[0]; | ||
} | ||
return { | ||
stateValue: undefined, | ||
actions: { onEntry: [], onExit: [], actions: [] }, | ||
activities: undefined | ||
}; | ||
} | ||
var subStateKey = Object.keys(nextStateValue)[0]; | ||
// try with parent | ||
var _b = this.states[subStateKey].next(event, history ? history.value : undefined), parentNextValue = _b[0], parentNextActions = _b[1]; | ||
var nextActions = nextStateValue[subStateKey][1]; | ||
return [ | ||
parentNextValue, | ||
{ | ||
onEntry: nextActions.onEntry.concat(parentNextActions.onEntry), | ||
actions: nextActions.actions.concat(parentNextActions.actions), | ||
onExit: nextActions.onExit.concat(parentNextActions.onExit) | ||
} | ||
]; | ||
var _b = this.states[subStateKey].next(event, history ? history.value : undefined, extendedState), parentNextValue = _b.stateValue, parentNextActions = _b.actions, parentActivities = _b.activities; | ||
var nextActions = nextStateValue[subStateKey].actions; | ||
var activities = nextStateValue[subStateKey].activities; | ||
var allActivities = __assign({}, activities, parentActivities); | ||
var allActions = parentNextActions | ||
? nextActions | ||
? { | ||
onEntry: nextActions.onEntry.concat(parentNextActions.onEntry), | ||
actions: nextActions.actions.concat(parentNextActions.actions), | ||
onExit: nextActions.onExit.concat(parentNextActions.onExit) | ||
} | ||
: parentNextActions | ||
: nextActions; | ||
return { | ||
stateValue: parentNextValue, | ||
actions: allActions, | ||
activities: allActivities | ||
}; | ||
} | ||
if (this.parallel) { | ||
nextStateValue = __assign({}, utils_1.mapValues(this.initialState.value, function (subStateValue) { return [ | ||
subStateValue, | ||
{ onEntry: [], onExit: [], actions: [] } | ||
]; }), nextStateValue); | ||
nextStateValue = __assign({}, utils_1.mapValues(this.initialState.value, function (subStateValue) { return ({ | ||
stateValue: subStateValue, | ||
actions: { onEntry: [], onExit: [], actions: [] }, | ||
activities: undefined | ||
}); }), nextStateValue); | ||
} | ||
@@ -161,13 +217,19 @@ var finalActions = { | ||
}; | ||
var finalStateValue = utils_1.mapValues(nextStateValue, function (_a, key) { | ||
var nextSubStateValue = _a[0], nextSubActions = _a[1]; | ||
if (nextSubActions.onEntry) { | ||
(_b = finalActions.onEntry).push.apply(_b, nextSubActions.onEntry); | ||
var finalActivities = {}; | ||
var finalStateValue = utils_1.mapValues(nextStateValue, function (subStateTransition, key) { | ||
var nextSubStateValue = subStateTransition.stateValue, nextSubActions = subStateTransition.actions, nextSubActivities = subStateTransition.activities; | ||
if (nextSubActions) { | ||
if (nextSubActions.onEntry) { | ||
(_a = finalActions.onEntry).push.apply(_a, nextSubActions.onEntry); | ||
} | ||
if (nextSubActions.actions) { | ||
(_b = finalActions.actions).push.apply(_b, nextSubActions.actions); | ||
} | ||
if (nextSubActions.onExit) { | ||
(_c = finalActions.onExit).push.apply(_c, nextSubActions.onExit); | ||
} | ||
} | ||
if (nextSubActions.actions) { | ||
(_c = finalActions.actions).push.apply(_c, nextSubActions.actions); | ||
if (nextSubActivities) { | ||
Object.assign(finalActivities, nextSubActivities); | ||
} | ||
if (nextSubActions.onExit) { | ||
(_d = finalActions.onExit).push.apply(_d, nextSubActions.onExit); | ||
} | ||
if (!nextSubStateValue) { | ||
@@ -177,15 +239,31 @@ return stateValue[key]; | ||
return nextSubStateValue; | ||
var _b, _c, _d; | ||
var _a, _b, _c; | ||
}); | ||
return [finalStateValue, finalActions]; | ||
return { | ||
stateValue: finalStateValue, | ||
actions: finalActions, | ||
activities: finalActivities | ||
}; | ||
var _a; | ||
}; | ||
StateNode.prototype.next = function (event, history, extendedState) { | ||
var _this = this; | ||
var eventType = utils_1.getEventType(event); | ||
var actionMap = { onEntry: [], onExit: [], actions: [] }; | ||
var activityMap = {}; | ||
if (this.onExit) { | ||
actionMap.onExit = this.onExit; | ||
} | ||
if (this.activities) { | ||
this.activities.forEach(function (activity) { | ||
activityMap[utils_1.getEventType(activity)] = false; | ||
actionMap.onExit = actionMap.onExit.concat(actions_1.stop(activity)); | ||
}); | ||
} | ||
if (!this.on || !this.on[eventType]) { | ||
return [undefined, actionMap]; | ||
return { | ||
stateValue: undefined, | ||
actions: actionMap, | ||
activities: activityMap | ||
}; | ||
} | ||
@@ -198,11 +276,14 @@ var transition = this.on[eventType]; | ||
else { | ||
for (var _i = 0, _a = Object.keys(transition); _i < _a.length; _i++) { | ||
var candidate = _a[_i]; | ||
// if (Array.isArray(transition[candidate])) {break;} | ||
var _b = transition[candidate], cond = _b.cond, transitionActions = _b.actions; | ||
var candidates = Array.isArray(transition) | ||
? transition | ||
: Object.keys(transition).map(function (key) { return (__assign({}, transition[key], { target: key })); }); | ||
for (var _i = 0, candidates_1 = candidates; _i < candidates_1.length; _i++) { | ||
var candidate = candidates_1[_i]; | ||
var _a = candidate, cond = _a.cond, transitionActions = _a.actions; | ||
var extendedStateObject = extendedState || {}; | ||
var eventObject = typeof event === 'string' || typeof event === 'number' | ||
? { type: event } | ||
: event; | ||
if (!cond || cond(extendedState, eventObject)) { | ||
nextStateString = candidate; | ||
if (!cond || cond(extendedStateObject, eventObject)) { | ||
nextStateString = candidate.target; | ||
if (transitionActions) { | ||
@@ -216,3 +297,7 @@ actionMap.actions = actionMap.actions.concat(transitionActions); | ||
if (!nextStateString) { | ||
return [undefined, actionMap]; | ||
return { | ||
stateValue: undefined, | ||
actions: actionMap, | ||
activities: activityMap | ||
}; | ||
} | ||
@@ -241,5 +326,10 @@ var nextStatePath = utils_1.toStatePath(nextStateString); | ||
} | ||
else if (subPath === NULL_EVENT) { | ||
actionMap.onExit = []; | ||
currentState = currentState.states[_this.key]; | ||
return; | ||
} | ||
currentState = currentState.states[subPath]; | ||
if (currentState === undefined) { | ||
throw new Error("Event '" + event + "' on state '" + currentPath + "' leads to undefined state '" + nextStatePath + "'."); | ||
throw new Error("Event '" + event + "' on state '" + currentPath + "' leads to undefined state '" + nextStatePath.join(STATE_DELIMITER) + "'."); | ||
} | ||
@@ -249,2 +339,8 @@ if (currentState.onEntry) { | ||
} | ||
if (currentState.activities) { | ||
currentState.activities.forEach(function (activity) { | ||
activityMap[utils_1.getEventType(activity)] = true; | ||
actionMap.onEntry = actionMap.onEntry.concat(actions_1.start(activity)); | ||
}); | ||
} | ||
currentPath = subPath; | ||
@@ -266,12 +362,42 @@ if (currentHistory) { | ||
} | ||
if (currentState.activities) { | ||
currentState.activities.forEach(function (activity) { | ||
activityMap[utils_1.getEventType(activity)] = true; | ||
actionMap.onEntry = actionMap.onEntry.concat(actions_1.start(activity)); | ||
}); | ||
} | ||
} | ||
return [currentState.getRelativeValue(this.parent), actionMap]; | ||
return { | ||
stateValue: currentState.getRelativeValue(this.parent), | ||
actions: actionMap, | ||
activities: activityMap | ||
}; | ||
}; | ||
Object.defineProperty(StateNode.prototype, "resolvedStateValue", { | ||
get: function () { | ||
var key = this.key; | ||
if (this.parallel) { | ||
return _a = {}, | ||
_a[key] = utils_1.mapValues(this.states, function (stateNode) { return stateNode.resolvedStateValue[stateNode.key]; }), | ||
_a; | ||
} | ||
if (!this.initial) { | ||
// If leaf node, value is just the state node's key | ||
return key; | ||
} | ||
return _b = {}, | ||
_b[key] = this.states[this.initial].resolvedStateValue, | ||
_b; | ||
var _a, _b; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(StateNode.prototype, "initialStateValue", { | ||
get: function () { | ||
this.__cache.initialState = | ||
this.__cache.initialState || | ||
(this.parallel | ||
? utils_1.mapValues(this.states, function (state) { return state.initialStateValue; }) | ||
: this.initial); | ||
var initialStateValue = this.__cache.initialState || | ||
(this.parallel | ||
? utils_1.mapValues(this.states, function (state) { return state.initialStateValue; }) | ||
: this.resolvedStateValue[this.key]); | ||
this.__cache.initialState = initialStateValue; | ||
return this.__cache.initialState; | ||
@@ -360,3 +486,4 @@ }, | ||
relativeValue = (_b = {}, | ||
_b[currentNode.key] = typeof currentInitialState === 'object' && | ||
_b[currentNode.key] = currentNode.parallel && | ||
typeof currentInitialState === 'object' && | ||
typeof relativeValue === 'object' | ||
@@ -363,0 +490,0 @@ ? __assign({}, currentInitialState, relativeValue) : relativeValue, |
@@ -1,2 +0,2 @@ | ||
import { StateValue, Action } from './types'; | ||
import { StateValue, Action, ActivityMap } from './types'; | ||
export declare class State { | ||
@@ -6,6 +6,8 @@ value: StateValue; | ||
actions: Action[]; | ||
activities: ActivityMap; | ||
data: Record<string, any>; | ||
static from(stateValue: State | StateValue): State; | ||
static inert(stateValue: State | StateValue): State; | ||
constructor(value: StateValue, history?: State | undefined, actions?: Action[]); | ||
constructor(value: StateValue, history?: State | undefined, actions?: Action[], activities?: ActivityMap, data?: Record<string, any>); | ||
toString(): string | undefined; | ||
} |
@@ -6,7 +6,11 @@ "use strict"; | ||
var State = /** @class */ (function () { | ||
function State(value, history, actions) { | ||
function State(value, history, actions, activities, data) { | ||
if (actions === void 0) { actions = []; } | ||
if (activities === void 0) { activities = constants_1.EMPTY_ACTIVITY_MAP; } | ||
if (data === void 0) { data = {}; } | ||
this.value = value; | ||
this.history = history; | ||
this.actions = actions; | ||
this.activities = activities; | ||
this.data = data; | ||
} | ||
@@ -13,0 +17,0 @@ State.from = function (stateValue) { |
@@ -14,2 +14,4 @@ import { StateNode } from './index'; | ||
export declare type Event = EventType | EventObject; | ||
export declare type InternalEvent = EventType | EventObject; | ||
export declare type Action = ActionType | ActionObject; | ||
export declare type StateKey = string | State; | ||
@@ -20,3 +22,3 @@ export interface StateValueMap { | ||
export declare type StateValue = string | StateValueMap; | ||
export declare type Condition = (extendedState: any) => boolean; | ||
export declare type Condition = (extendedState: any, event?: EventObject) => boolean; | ||
export interface TransitionConfig { | ||
@@ -30,3 +32,4 @@ cond?: (extendedState: any, event: EventObject) => boolean; | ||
export declare type ConditionalTransitionConfig = TargetTransitionConfig[]; | ||
export declare type Transition = string | Record<string, TransitionConfig>; | ||
export declare type Transition = string | Record<string, TransitionConfig> | ConditionalTransitionConfig; | ||
export declare type Activity = string | ActionObject; | ||
export interface StateNodeConfig { | ||
@@ -40,4 +43,6 @@ key?: string; | ||
onExit?: Action | Action[]; | ||
activities?: Activity[]; | ||
parent?: StateNode; | ||
strict?: boolean | undefined; | ||
data?: object | undefined; | ||
} | ||
@@ -66,4 +71,4 @@ export interface SimpleStateNodeConfig extends StateNodeConfig { | ||
parallel: true; | ||
states: Record<string, CompoundStateNodeConfig>; | ||
} | ||
export declare type Action = string | ActionObject; | ||
export interface EntryExitEffectMap { | ||
@@ -117,2 +122,15 @@ entry: Action[]; | ||
} | ||
export declare type MaybeStateValueActionsTuple = [StateValue | undefined, ActionMap]; | ||
export interface ActivityMap { | ||
[activityKey: string]: boolean; | ||
} | ||
export declare type MaybeStateValueActionsTuple = [StateValue | undefined, ActionMap, ActivityMap | undefined]; | ||
export interface StateTransition { | ||
stateValue: StateValue | undefined; | ||
actions: ActionMap | undefined; | ||
activities: ActivityMap | undefined; | ||
} | ||
export interface TransitionData { | ||
value: StateValue | undefined; | ||
actions: ActionMap; | ||
activities?: ActivityMap; | ||
} |
{ | ||
"name": "xstate", | ||
"version": "3.0.4", | ||
"version": "3.1.0", | ||
"description": "Simple JavaScript Finite State Machines and Statecharts", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -0,1 +1,4 @@ | ||
import { ActivityMap } from './types'; | ||
export const STATE_DELIMITER = '.'; | ||
export const EMPTY_ACTIVITY_MAP: ActivityMap = {}; |
111
src/graph.ts
import { StateNode } from './index'; | ||
import { toTrie } from './utils'; | ||
import { Transition, StateValue, Machine, Event } from './types'; | ||
import { | ||
// Transition, | ||
StateValue, | ||
Machine, | ||
Event, | ||
// TargetTransitionConfig, | ||
Condition, | ||
Action | ||
} from './types'; | ||
const EMPTY_MAP = {}; | ||
export interface IEdge { | ||
export interface Edge { | ||
event: string; | ||
source: StateNode; | ||
target: StateNode; | ||
cond?: Condition; | ||
actions: Action[]; | ||
} | ||
export interface INodesAndEdges { | ||
nodes: StateNode[]; | ||
edges: IEdge[]; | ||
edges: Edge[]; | ||
} | ||
@@ -31,61 +41,54 @@ | ||
function getTransitionStateKeys(transition: Transition): string[] { | ||
if (typeof transition === 'string') { | ||
return [transition]; | ||
function getEventEdges(node: StateNode, event: string): Edge[] { | ||
const transitions = node.on![event]!; | ||
if (typeof transitions === 'string') { | ||
return [ | ||
{ | ||
source: node, | ||
target: node.parent!.getState(transitions)!, | ||
event, | ||
actions: [] | ||
} | ||
]; | ||
} | ||
return Object.keys(transition) as string[]; | ||
} | ||
export function getEdges( | ||
node: StateNode, | ||
visited: Record<string, true> = {} | ||
): IEdge[] { | ||
const { states } = node; | ||
visited[node.key] = true; | ||
const subNodeEdges = Object.keys(states).reduce((_edges: IEdge[], key) => { | ||
if (visited[key]) { | ||
return _edges; | ||
} | ||
const subState = states[key]; | ||
_edges.push(...getEdges(subState, visited)); | ||
visited[key] = true; | ||
return _edges; | ||
}, []); | ||
if (!node.on) { | ||
return subNodeEdges; | ||
if (Array.isArray(transitions)) { | ||
return transitions.map(transition => { | ||
return { | ||
source: node, | ||
target: node.parent!.getState(transition.target)!, | ||
event, | ||
actions: transition.actions || [], | ||
cond: transition.cond | ||
}; | ||
}); | ||
} | ||
const edges = Object.keys(node.on).reduce((accEdges: IEdge[], event) => { | ||
if (!node.on || !node.parent) { | ||
return accEdges; | ||
} | ||
return Object.keys(transitions).map(stateKey => { | ||
return { | ||
source: node, | ||
target: node.parent!.getState(stateKey)!, | ||
event, | ||
actions: transitions[stateKey].actions || [], | ||
cond: transitions[stateKey].cond | ||
}; | ||
}); | ||
} | ||
const { parent } = node; | ||
export function getEdges(node: StateNode): Edge[] { | ||
const edges: Edge[] = []; | ||
const transition = node.on[event]; | ||
if (!transition) { | ||
return accEdges; | ||
} | ||
const subStateKeys = getTransitionStateKeys(transition); | ||
subStateKeys.forEach(subStateKey => { | ||
const subNode = parent!.getState(subStateKey) as StateNode; | ||
const edge: IEdge = { event, source: node, target: subNode }; | ||
accEdges.push(edge); | ||
if (!visited[subStateKey]) { | ||
accEdges.push(...getEdges(subNode, visited)); | ||
visited[subStateKey] = true; | ||
} | ||
if (node.states) { | ||
Object.keys(node.states).forEach(stateKey => { | ||
edges.push(...getEdges(node.states[stateKey])); | ||
}); | ||
} | ||
if (node.on) { | ||
Object.keys(node.on).forEach(event => { | ||
edges.push(...getEventEdges(node, event)); | ||
}); | ||
} | ||
return accEdges; | ||
}, []); | ||
return subNodeEdges.concat(edges); | ||
return edges; | ||
} | ||
@@ -92,0 +95,0 @@ |
308
src/index.ts
@@ -16,5 +16,8 @@ import { getEventType, toStatePath, toTrie, mapValues } from './utils'; | ||
ActionMap, | ||
MaybeStateValueActionsTuple, | ||
StandardMachineConfig, | ||
TransitionConfig | ||
TransitionConfig, | ||
ActivityMap, | ||
StateNodeConfig, | ||
Activity, | ||
StateTransition | ||
} from './types'; | ||
@@ -24,7 +27,8 @@ import matchesState from './matchesState'; | ||
import { State } from './State'; | ||
import { start, stop } from './actions'; | ||
const STATE_DELIMITER = '.'; | ||
const HISTORY_KEY = '$history'; | ||
class StateNode { | ||
const NULL_EVENT = ''; | ||
class StateNode implements StateNodeConfig { | ||
public key: string; | ||
@@ -39,5 +43,7 @@ public id: string; | ||
public onExit?: Action[]; | ||
public activities?: Activity[]; | ||
public strict: boolean; | ||
public parent?: StateNode; | ||
public machine: StateNode; | ||
public data: object | undefined; | ||
@@ -88,2 +94,4 @@ private __cache = { | ||
: undefined; | ||
this.data = config.data; | ||
this.activities = config.activities; | ||
} | ||
@@ -108,5 +116,7 @@ public getStateNodes(state: StateValue | State): StateNode[] { | ||
subStateKeys | ||
.map(subStateKey => | ||
this.states[subStateKey].getStateNodes(stateValue[subStateKey]) | ||
) | ||
.map(subStateKey => { | ||
return this.states[subStateKey].getStateNodes( | ||
stateValue[subStateKey] | ||
); | ||
}) | ||
.reduce((a, b) => a.concat(b)) | ||
@@ -138,4 +148,3 @@ ); | ||
// const stateValue = toTrie(state); | ||
const [nextStateValue, nextActions] = this.transitionStateValue( | ||
const stateTransition = this.transitionStateValue( | ||
state, | ||
@@ -145,7 +154,47 @@ event, | ||
); | ||
const nextState = this.stateTransitionToState(stateTransition, state); | ||
if (!nextStateValue) { | ||
if (!nextState) { | ||
return State.inert(state); | ||
} | ||
// Try transitioning from "transient" states from the NULL_EVENT | ||
// until a state with non-transient transitions is found | ||
let maybeNextState: State | undefined = nextState; | ||
let nextStateFromInternalTransition: State; | ||
do { | ||
nextStateFromInternalTransition = maybeNextState; | ||
maybeNextState = this.stateTransitionToState( | ||
this.transitionStateValue( | ||
nextStateFromInternalTransition, | ||
NULL_EVENT, | ||
extendedState | ||
), | ||
nextStateFromInternalTransition | ||
); | ||
} while (maybeNextState); | ||
// TODO: handle internally raised events | ||
return nextStateFromInternalTransition; | ||
} | ||
private stateTransitionToState( | ||
stateTransition: StateTransition, | ||
prevState: StateValue | State | ||
): State | undefined { | ||
const { | ||
stateValue: nextStateValue, | ||
actions: nextActions, | ||
activities: nextActivities | ||
} = stateTransition; | ||
if (!nextStateValue) { | ||
return undefined; | ||
} | ||
const prevActivities = | ||
prevState instanceof State ? prevState.activities : undefined; | ||
const activities = { ...prevActivities, ...nextActivities }; | ||
return new State( | ||
@@ -155,5 +204,19 @@ // next state value | ||
// history | ||
State.from(state), | ||
State.from(prevState), | ||
// effects | ||
nextActions.onExit.concat(nextActions.actions).concat(nextActions.onEntry) | ||
nextActions | ||
? nextActions.onExit | ||
.concat(nextActions.actions) | ||
.concat(nextActions.onEntry) | ||
: [], | ||
// activities | ||
activities, | ||
// data | ||
this.getStateNodes(nextStateValue).reduce( | ||
(data, stateNode) => { | ||
data[stateNode.id] = stateNode.data; | ||
return data; | ||
}, | ||
{} as Record<string, any> | ||
) | ||
); | ||
@@ -165,3 +228,3 @@ } | ||
extendedState?: any | ||
): MaybeStateValueActionsTuple { | ||
): StateTransition { | ||
const history = state instanceof State ? state.history : undefined; | ||
@@ -179,6 +242,7 @@ let stateValue = toTrie(state); | ||
if (subStateNode.states && subStateNode.initial) { | ||
// Get the initial state value | ||
const initialStateValue = subStateNode.initialState.value; | ||
stateValue = { [stateValue]: initialStateValue }; | ||
} else { | ||
// Transition from the substate | ||
return subStateNode.next( | ||
@@ -192,2 +256,5 @@ event, | ||
// Potential transition tuples from parent state nodes | ||
const potentialStateTransitions: StateTransition[] = []; | ||
let nextStateValue = mapValues(stateValue, (subStateValue, subStateKey) => { | ||
@@ -199,4 +266,4 @@ const subHistory = history ? history.value[subStateKey] : undefined; | ||
); | ||
const subStateNode = this.states[subStateKey] as StateNode; | ||
const nextTuple = subStateNode.transitionStateValue( | ||
const subStateNode = this.states[subStateKey]; | ||
const subStateTransition = subStateNode.transitionStateValue( | ||
subState, | ||
@@ -207,3 +274,13 @@ event, | ||
return nextTuple; | ||
if (!subStateTransition.stateValue) { | ||
potentialStateTransitions.push( | ||
subStateNode.next( | ||
event, | ||
history ? history.value : undefined, | ||
extendedState | ||
) | ||
); | ||
} | ||
return subStateTransition; | ||
}); | ||
@@ -213,7 +290,15 @@ | ||
Array.prototype.every.call(Object.keys(nextStateValue), key => { | ||
return nextStateValue[key][0] === undefined; | ||
return nextStateValue[key].stateValue === undefined; | ||
}) | ||
) { | ||
if (this.parallel) { | ||
return [undefined, { onEntry: [], onExit: [], actions: [] }]; | ||
if (potentialStateTransitions.length) { | ||
return potentialStateTransitions[0]; | ||
} | ||
return { | ||
stateValue: undefined, | ||
actions: { onEntry: [], onExit: [], actions: [] }, | ||
activities: undefined | ||
}; | ||
} | ||
@@ -224,15 +309,34 @@ | ||
// try with parent | ||
const [parentNextValue, parentNextActions] = this.states[ | ||
subStateKey | ||
].next(event, history ? history.value : undefined); | ||
const nextActions = nextStateValue[subStateKey][1]; | ||
const { | ||
stateValue: parentNextValue, | ||
actions: parentNextActions, | ||
activities: parentActivities | ||
} = this.states[subStateKey].next( | ||
event, | ||
history ? history.value : undefined, | ||
extendedState | ||
); | ||
const nextActions = nextStateValue[subStateKey].actions; | ||
const activities = nextStateValue[subStateKey].activities; | ||
return [ | ||
parentNextValue, | ||
{ | ||
onEntry: [...nextActions.onEntry, ...parentNextActions.onEntry], | ||
actions: [...nextActions.actions, ...parentNextActions.actions], | ||
onExit: [...nextActions.onExit, ...parentNextActions.onExit] | ||
} | ||
]; | ||
const allActivities = { | ||
...activities, | ||
...parentActivities | ||
}; | ||
const allActions = parentNextActions | ||
? nextActions | ||
? { | ||
onEntry: [...nextActions.onEntry, ...parentNextActions.onEntry], | ||
actions: [...nextActions.actions, ...parentNextActions.actions], | ||
onExit: [...nextActions.onExit, ...parentNextActions.onExit] | ||
} | ||
: parentNextActions | ||
: nextActions; | ||
return { | ||
stateValue: parentNextValue, | ||
actions: allActions, | ||
activities: allActivities | ||
}; | ||
} | ||
@@ -242,6 +346,10 @@ | ||
nextStateValue = { | ||
...(mapValues(this.initialState.value as {}, subStateValue => [ | ||
subStateValue, | ||
{ onEntry: [], onExit: [], actions: [] } | ||
]) as Record<string, MaybeStateValueActionsTuple>), | ||
...mapValues( | ||
this.initialState.value as Record<string, StateValue>, | ||
subStateValue => ({ | ||
stateValue: subStateValue, | ||
actions: { onEntry: [], onExit: [], actions: [] }, | ||
activities: undefined | ||
}) | ||
), | ||
...nextStateValue | ||
@@ -256,14 +364,25 @@ }; | ||
}; | ||
const finalActivities: ActivityMap = {}; | ||
const finalStateValue = mapValues( | ||
nextStateValue, | ||
([nextSubStateValue, nextSubActions], key) => { | ||
if (nextSubActions.onEntry) { | ||
finalActions.onEntry.push(...nextSubActions.onEntry); | ||
(subStateTransition, key) => { | ||
const { | ||
stateValue: nextSubStateValue, | ||
actions: nextSubActions, | ||
activities: nextSubActivities | ||
} = subStateTransition; | ||
if (nextSubActions) { | ||
if (nextSubActions.onEntry) { | ||
finalActions.onEntry.push(...nextSubActions.onEntry); | ||
} | ||
if (nextSubActions.actions) { | ||
finalActions.actions.push(...nextSubActions.actions); | ||
} | ||
if (nextSubActions.onExit) { | ||
finalActions.onExit.push(...nextSubActions.onExit); | ||
} | ||
} | ||
if (nextSubActions.actions) { | ||
finalActions.actions.push(...nextSubActions.actions); | ||
if (nextSubActivities) { | ||
Object.assign(finalActivities, nextSubActivities); | ||
} | ||
if (nextSubActions.onExit) { | ||
finalActions.onExit.push(...nextSubActions.onExit); | ||
} | ||
@@ -278,3 +397,7 @@ if (!nextSubStateValue) { | ||
return [finalStateValue, finalActions]; | ||
return { | ||
stateValue: finalStateValue, | ||
actions: finalActions, | ||
activities: finalActivities | ||
}; | ||
} | ||
@@ -286,5 +409,6 @@ | ||
extendedState?: any | ||
): MaybeStateValueActionsTuple { | ||
): StateTransition { | ||
const eventType = getEventType(event); | ||
const actionMap: ActionMap = { onEntry: [], onExit: [], actions: [] }; | ||
const activityMap: ActivityMap = {}; | ||
@@ -294,5 +418,15 @@ if (this.onExit) { | ||
} | ||
if (this.activities) { | ||
this.activities.forEach(activity => { | ||
activityMap[getEventType(activity)] = false; | ||
actionMap.onExit = actionMap.onExit.concat(stop(activity)); | ||
}); | ||
} | ||
if (!this.on || !this.on[eventType]) { | ||
return [undefined, actionMap]; | ||
return { | ||
stateValue: undefined, | ||
actions: actionMap, | ||
activities: activityMap | ||
}; | ||
} | ||
@@ -306,7 +440,15 @@ | ||
} else { | ||
for (const candidate of Object.keys(transition)) { | ||
// if (Array.isArray(transition[candidate])) {break;} | ||
const { cond, actions: transitionActions } = transition[ | ||
candidate | ||
] as TransitionConfig; | ||
const candidates = Array.isArray(transition) | ||
? transition | ||
: Object.keys(transition).map(key => ({ | ||
...transition[key], | ||
target: key | ||
})); | ||
for (const candidate of candidates) { | ||
const { | ||
cond, | ||
actions: transitionActions | ||
} = candidate as TransitionConfig; | ||
const extendedStateObject = extendedState || {}; | ||
const eventObject: EventObject = | ||
@@ -316,4 +458,4 @@ typeof event === 'string' || typeof event === 'number' | ||
: event; | ||
if (!cond || cond(extendedState, eventObject)) { | ||
nextStateString = candidate; | ||
if (!cond || cond(extendedStateObject, eventObject)) { | ||
nextStateString = candidate.target; | ||
if (transitionActions) { | ||
@@ -328,3 +470,7 @@ actionMap.actions = actionMap.actions.concat(transitionActions); | ||
if (!nextStateString) { | ||
return [undefined, actionMap]; | ||
return { | ||
stateValue: undefined, | ||
actions: actionMap, | ||
activities: activityMap | ||
}; | ||
} | ||
@@ -355,2 +501,6 @@ | ||
} | ||
} else if (subPath === NULL_EVENT) { | ||
actionMap.onExit = []; | ||
currentState = currentState.states[this.key]; | ||
return; | ||
} | ||
@@ -362,3 +512,5 @@ | ||
throw new Error( | ||
`Event '${event}' on state '${currentPath}' leads to undefined state '${nextStatePath}'.` | ||
`Event '${event}' on state '${currentPath}' leads to undefined state '${nextStatePath.join( | ||
STATE_DELIMITER | ||
)}'.` | ||
); | ||
@@ -370,2 +522,8 @@ } | ||
} | ||
if (currentState.activities) { | ||
currentState.activities.forEach(activity => { | ||
activityMap[getEventType(activity)] = true; | ||
actionMap.onEntry = actionMap.onEntry.concat(start(activity)); | ||
}); | ||
} | ||
@@ -392,8 +550,39 @@ currentPath = subPath; | ||
} | ||
if (currentState.activities) { | ||
currentState.activities.forEach(activity => { | ||
activityMap[getEventType(activity)] = true; | ||
actionMap.onEntry = actionMap.onEntry.concat(start(activity)); | ||
}); | ||
} | ||
} | ||
return [currentState.getRelativeValue(this.parent), actionMap]; | ||
return { | ||
stateValue: currentState.getRelativeValue(this.parent), | ||
actions: actionMap, | ||
activities: activityMap | ||
}; | ||
} | ||
private get resolvedStateValue(): StateValue { | ||
const { key } = this; | ||
if (this.parallel) { | ||
return { | ||
[key]: mapValues( | ||
this.states, | ||
stateNode => stateNode.resolvedStateValue[stateNode.key] | ||
) | ||
}; | ||
} | ||
if (!this.initial) { | ||
// If leaf node, value is just the state node's key | ||
return key; | ||
} | ||
return { | ||
[key]: this.states[this.initial].resolvedStateValue | ||
}; | ||
} | ||
private get initialStateValue(): StateValue | undefined { | ||
this.__cache.initialState = | ||
const initialStateValue = | ||
this.__cache.initialState || | ||
@@ -405,4 +594,6 @@ ((this.parallel | ||
) | ||
: this.initial) as StateValue); | ||
: this.resolvedStateValue[this.key]) as StateValue); | ||
this.__cache.initialState = initialStateValue; | ||
return this.__cache.initialState; | ||
@@ -502,2 +693,3 @@ } | ||
[currentNode.key]: | ||
currentNode.parallel && | ||
typeof currentInitialState === 'object' && | ||
@@ -504,0 +696,0 @@ typeof relativeValue === 'object' |
@@ -1,3 +0,3 @@ | ||
import { StateValue, Action } from './types'; | ||
import { STATE_DELIMITER } from './constants'; | ||
import { StateValue, Action, ActivityMap } from './types'; | ||
import { STATE_DELIMITER, EMPTY_ACTIVITY_MAP } from './constants'; | ||
import { toTrie } from './utils'; | ||
@@ -23,6 +23,9 @@ | ||
} | ||
constructor( | ||
public value: StateValue, | ||
public history?: State, | ||
public actions: Action[] = [] | ||
public actions: Action[] = [], | ||
public activities: ActivityMap = EMPTY_ACTIVITY_MAP, | ||
public data: Record<string, any> = {} | ||
) {} | ||
@@ -29,0 +32,0 @@ public toString(): string | undefined { |
@@ -17,2 +17,4 @@ import { StateNode } from './index'; | ||
export type Event = EventType | EventObject; | ||
export type InternalEvent = EventType | EventObject; | ||
export type Action = ActionType | ActionObject; | ||
export type StateKey = string | State; | ||
@@ -26,3 +28,3 @@ | ||
export type Condition = (extendedState: any) => boolean; | ||
export type Condition = (extendedState: any, event?: EventObject) => boolean; | ||
@@ -40,4 +42,9 @@ export interface TransitionConfig { | ||
export type Transition = string | Record<string, TransitionConfig>; | ||
export type Transition = | ||
| string | ||
| Record<string, TransitionConfig> | ||
| ConditionalTransitionConfig; | ||
export type Activity = string | ActionObject; | ||
export interface StateNodeConfig { | ||
@@ -51,4 +58,6 @@ key?: string; | ||
onExit?: Action | Action[]; | ||
activities?: Activity[]; | ||
parent?: StateNode; | ||
strict?: boolean | undefined; | ||
data?: object | undefined; | ||
} | ||
@@ -83,5 +92,5 @@ export interface SimpleStateNodeConfig extends StateNodeConfig { | ||
parallel: true; | ||
states: Record<string, CompoundStateNodeConfig>; | ||
} | ||
export type Action = string | ActionObject; | ||
export interface EntryExitEffectMap { | ||
@@ -141,2 +150,22 @@ entry: Action[]; | ||
} | ||
export type MaybeStateValueActionsTuple = [StateValue | undefined, ActionMap]; | ||
export interface ActivityMap { | ||
[activityKey: string]: boolean; | ||
} | ||
export type MaybeStateValueActionsTuple = [ | ||
StateValue | undefined, | ||
ActionMap, | ||
ActivityMap | undefined | ||
]; | ||
export interface StateTransition { | ||
stateValue: StateValue | undefined; | ||
actions: ActionMap | undefined; | ||
activities: ActivityMap | undefined; | ||
} | ||
export interface TransitionData { | ||
value: StateValue | undefined; | ||
actions: ActionMap; | ||
activities?: ActivityMap; | ||
} |
@@ -22,3 +22,7 @@ import { assert } from 'chai'; | ||
on: { | ||
PED_COUNTDOWN: 'wait' | ||
PED_COUNTDOWN: { | ||
wait: { | ||
actions: ['startCountdown'] | ||
} | ||
} | ||
} | ||
@@ -136,15 +140,27 @@ }, | ||
); | ||
assert.deepEqual( | ||
assert.sameDeepMembers( | ||
edges.map(edge => ({ | ||
event: edge.event, | ||
source: edge.source.id, | ||
target: edge.target.id | ||
target: edge.target.id, | ||
actions: edge.actions | ||
})), | ||
[ | ||
{ event: 'TIMER', source: 'light.green', target: 'light.yellow' }, | ||
{ event: 'TIMER', source: 'light.yellow', target: 'light.red' }, | ||
{ | ||
event: 'TIMER', | ||
source: 'light.green', | ||
target: 'light.yellow', | ||
actions: [] | ||
}, | ||
{ | ||
event: 'TIMER', | ||
source: 'light.yellow', | ||
target: 'light.red', | ||
actions: [] | ||
}, | ||
{ | ||
event: 'PED_COUNTDOWN', | ||
source: 'light.red.walk', | ||
target: 'light.red.wait' | ||
target: 'light.red.wait', | ||
actions: ['startCountdown'] | ||
}, | ||
@@ -154,9 +170,16 @@ { | ||
source: 'light.red.wait', | ||
target: 'light.red.stop' | ||
target: 'light.red.stop', | ||
actions: [] | ||
}, | ||
{ event: 'TIMER', source: 'light.red', target: 'light.green' }, | ||
{ | ||
event: 'TIMER', | ||
source: 'light.red', | ||
target: 'light.green', | ||
actions: [] | ||
}, | ||
{ | ||
event: 'POWER_OUTAGE', | ||
source: 'light.red', | ||
target: 'light.red.flashing' | ||
target: 'light.red.flashing', | ||
actions: [] | ||
}, | ||
@@ -166,3 +189,4 @@ { | ||
source: 'light.yellow', | ||
target: 'light.red.flashing' | ||
target: 'light.red.flashing', | ||
actions: [] | ||
}, | ||
@@ -172,3 +196,4 @@ { | ||
source: 'light.green', | ||
target: 'light.red.flashing' | ||
target: 'light.red.flashing', | ||
actions: [] | ||
} | ||
@@ -190,3 +215,3 @@ ] | ||
); | ||
assert.deepEqual( | ||
assert.sameDeepMembers( | ||
edges.map(edge => ({ | ||
@@ -324,2 +349,22 @@ event: edge.event, | ||
}); | ||
it('should not throw when a condition is present', () => { | ||
const condMachine = Machine({ | ||
initial: 'a', | ||
states: { | ||
a: { | ||
on: { | ||
NEXT: { | ||
b: { | ||
cond: payload => payload.foo | ||
} | ||
} | ||
} | ||
}, | ||
b: {} | ||
} | ||
}); | ||
assert.doesNotThrow(() => getShortestPaths(condMachine)); | ||
}); | ||
}); | ||
@@ -326,0 +371,0 @@ |
@@ -82,4 +82,4 @@ import { assert } from 'chai'; | ||
it('should mix/match string state values and object state values', () => { | ||
assert.ok(matchesState('a.b.c', {a: {b: 'c'}})); | ||
assert.ok(matchesState('a.b.c', { a: { b: 'c' } })); | ||
}); | ||
}); |
@@ -106,5 +106,5 @@ import { assert } from 'chai'; | ||
it(`should go from ${fromState} to ${JSON.stringify( | ||
toState | ||
)} on ${eventTypes}`, () => { | ||
it(`should go from ${fromState} to ${JSON.stringify(toState)} on ${ | ||
eventTypes | ||
}`, () => { | ||
const resultState = testMultiTransition( | ||
@@ -111,0 +111,0 @@ wordMachine, |
@@ -14,3 +14,4 @@ { | ||
"interface-name": false, | ||
"member-ordering": false | ||
"member-ordering": false, | ||
"no-namespace": false | ||
}, | ||
@@ -17,0 +18,0 @@ "rulesDirectory": [], |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
710233
92
9538