@statewalker/fsm 0.9.4 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 statewalker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1 +1 @@
1
- # Hierarchical Finite State Machine Implementation
1
+ # @statewalker/fsm: Hierarchical Finite State Machine
@@ -1,65 +1,9 @@
1
- // @statewalker/fsm v0.9.4 https://github.com/statewalker/statewalker Copyright 2022 Mikhail Kotelnikov
1
+ // @statewalker/fsm v0.10.1 https://github.com/statewalker/statewalker-tree Copyright 2022 Mikhail Kotelnikov
2
2
  (function (global, factory) {
3
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
5
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.statewalker = global.statewalker || {}, global.statewalker.fsm = global.statewalker.fsm || {})));
6
- })(this, (function (exports) { 'use strict';
7
-
8
- const MODE = {
9
- NONE : 0,
10
- FIRST: 1, // old=true; new=true => ENTER + ENTER
11
- NEXT: 2, // old=false; new=true => EXIT + ENTER
12
- LEAF : 4, // old=true; new=false => ENTER + EXIT
13
- LAST : 8, // old=false; new=false => EXIT + EXIT
14
-
15
- ENTER: 1 | 2, // MODE.FIRST | MODE.NEXT
16
- EXIT : 4 | 8 // MODE.LEAF | MODE.LAST
17
- };
18
- var MODE$1 = MODE;
19
-
20
- function newTreeWalker(
21
- before, after,
22
- context = { stack: [], status: MODE$1.NONE }
23
- ) {
24
- return (getNode) => {
25
- let status = context.status;
26
- const prev = status & MODE$1.EXIT;
27
- if (prev) after(context);
28
- if (status & MODE$1.ENTER) context.stack.push(context.current);
29
- let node = getNode(context);
30
- if (node) {
31
- context.current = node;
32
- status = context.status = prev ? MODE$1.NEXT : MODE$1.FIRST;
33
- before(context);
34
- } else {
35
- node = context.current = context.stack.pop();
36
- status = context.status = node ? prev ? MODE$1.LAST : MODE$1.LEAF : MODE$1.NONE;
37
- }
38
- return status !== MODE$1.NONE;
39
- }
40
- }
41
-
42
- function newAsyncTreeWalker(
43
- before, after,
44
- context = { stack: [], status: MODE$1.NONE }
45
- ) {
46
- return async (getNode) => {
47
- let status = context.status;
48
- const prev = status & MODE$1.EXIT;
49
- if (prev) await after(context);
50
- if (status & MODE$1.ENTER) await context.stack.push(context.current);
51
- let node = await getNode(context);
52
- if (node) {
53
- context.current = node;
54
- status = context.status = prev ? MODE$1.NEXT : MODE$1.FIRST;
55
- await before(context);
56
- } else {
57
- node = context.current = await context.stack.pop();
58
- status = context.status = node ? prev ? MODE$1.LAST : MODE$1.LEAF : MODE$1.NONE;
59
- }
60
- return status !== MODE$1.NONE;
61
- }
62
- }
3
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@statewalker/tree')) :
4
+ typeof define === 'function' && define.amd ? define(['exports', '@statewalker/tree'], factory) :
5
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.statewalker = global.statewalker || {}, global.statewalker.fsm = global.statewalker.fsm || {}), global.statewalker.tree));
6
+ })(this, (function (exports, tree) { 'use strict';
63
7
 
64
8
  function buildStateDescriptor(config = {}) {
65
9
  const { key, transitions = [], states = {}, options, ...params } = config;
@@ -269,7 +213,7 @@ function newProcessInstance({
269
213
  } else {
270
214
  const eventKey = process.event.key || KEYS.EVENT_EMPTY;
271
215
  const parentDescriptor = process.stack[process.stack.length - 1].descriptor;
272
- const stateKey = process.status & MODE$1.ENTER
216
+ const stateKey = process.status & tree.MODE.ENTER
273
217
  ? KEYS.STATE_INITIAL
274
218
  : process.current ? process.current.key : KEYS.STATE_FINAL;
275
219
  key = getTargetStateKey(parentDescriptor, stateKey, eventKey);
@@ -297,7 +241,7 @@ function newAsyncProcess({
297
241
  newProcess,
298
242
  newState
299
243
  });
300
- const shift = newAsyncTreeWalker(before, after, process);
244
+ const shift = tree.newAsyncTreeWalker(before, after, process);
301
245
  process.finished = false;
302
246
  process.next = (event) => {
303
247
  process.nextEvent = event;
@@ -309,11 +253,11 @@ function newAsyncProcess({
309
253
  process.nextEvent = undefined;
310
254
  while (!process.finished && process.event) {
311
255
  process.finished = !await shift(loadNextState);
312
- if ((process.status & MODE$1.EXIT) && process.nextEvent) {
256
+ if ((process.status & tree.MODE.EXIT) && process.nextEvent) {
313
257
  // Consume the next event if it exists.
314
258
  process.event = process.nextEvent;
315
259
  process.nextEvent = undefined;
316
- } else if (process.status & MODE$1.LEAF) {
260
+ } else if (process.status & tree.MODE.LEAF) {
317
261
  // Returns control when the process is in a "leaf" state (a state without children)
318
262
  break;
319
263
  }
@@ -341,20 +285,19 @@ function newSyncProcess({
341
285
  newProcess,
342
286
  newState,
343
287
  });
344
- const shift = newTreeWalker(before, after, process);
288
+ const shift = tree.newTreeWalker(before, after, process);
345
289
  process.dispatch = process.next = (event) => {
346
290
  if (typeof event === 'string') event = { key : event };
347
291
  process.event = event;
348
292
  while (process.event) {
349
293
  if (!shift(loadNextState)) return false;
350
- if (process.status & MODE$1.LEAF) return true;
294
+ if (process.status & tree.MODE.LEAF) return true;
351
295
  }
352
296
  };
353
297
  return process;
354
298
  }
355
299
 
356
300
  exports.KEYS = KEYS;
357
- exports.MODE = MODE$1;
358
301
  exports.buildStateDescriptor = buildStateDescriptor;
359
302
  exports.checkProcessDescriptor = checkProcessDescriptor;
360
303
  exports.getAllStateKeys = getAllStateKeys;
@@ -362,10 +305,14 @@ exports.getAllTransitions = getAllTransitions;
362
305
  exports.getStateDescriptor = getStateDescriptor;
363
306
  exports.getTargetStateKey = getTargetStateKey;
364
307
  exports.newAsyncProcess = newAsyncProcess;
365
- exports.newAsyncTreeWalker = newAsyncTreeWalker;
366
308
  exports.newProcessInstance = newProcessInstance;
367
309
  exports.newSyncProcess = newSyncProcess;
368
- exports.newTreeWalker = newTreeWalker;
310
+ Object.keys(tree).forEach(function (k) {
311
+ if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
312
+ enumerable: true,
313
+ get: function () { return tree[k]; }
314
+ });
315
+ });
369
316
 
370
317
  Object.defineProperty(exports, '__esModule', { value: true });
371
318
 
@@ -0,0 +1,2 @@
1
+ // @statewalker/fsm v0.10.1 https://github.com/statewalker/statewalker-tree Copyright 2022 Mikhail Kotelnikov
2
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@statewalker/tree")):"function"==typeof define&&define.amd?define(["exports","@statewalker/tree"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).statewalker=e.statewalker||{},e.statewalker.fsm=e.statewalker.fsm||{}),e.statewalker.tree)}(this,(function(e,t){"use strict";function n(e={}){const{key:t,transitions:s=[],states:r={},options:o,...c}=e,i={key:t,transitions:{},states:{},options:Object.assign(o||{},c)};for(const e of s){let t,n,s;if(Array.isArray(e))t=e[0],n=e[1],s=e[2];else{const{from:r,event:o,to:c}=e;t=r,n=o,s=c}(i.transitions[t]=i.transitions[t]||{})[n]=s}if(Array.isArray(r))for(const e of r)i.states[e.key]=n(e);else if(r)for(const e of Object.keys(r))i.states[e]=n(r[e]);return i}var s={STATE_ANY:"*",STATE_INITIAL:"",STATE_FINAL:"",EVENT_ANY:"*",EVENT_EMPTY:""};function r(e,t){let n;for(let s=e.stack.length-1;!n&&s>=0;s--){n=(e.stack[s].descriptor.states||{})[t]}return n||{transitions:{},states:{}}}function o(e,t,n){const r=[[t,n],[s.STATE_ANY,n],[t,s.EVENT_ANY],[s.STATE_ANY,s.EVENT_ANY]];let o;for(let t=0,n=r.length;void 0===o&&t<n;t++){const[n,c]=r[t],i=e.transitions[n];i&&(o=i[c],void 0===o&&(o=i[s.EVENT_ANY]))}return void 0!==o?o:s.STATE_FINAL}function c({config:e,descriptor:c,newState:i=(e=>e),newProcess:a=(e=>({descriptor:e,status:0,stack:[],event:void 0,current:void 0}))}){const f=a(c=c||n(e));return[f,()=>{let e,n;if(f.status)if(f.stack.length){const c=f.event.key||s.EVENT_EMPTY;e=o(f.stack[f.stack.length-1].descriptor,f.status&t.MODE.ENTER?s.STATE_INITIAL:f.current?f.current.key:s.STATE_FINAL,c),e&&(n=r(f,e))}else e=s.STATE_FINAL;else n=f.descriptor,e=n.key;return e?i({process:f,key:e,descriptor:n}):null}]}e.KEYS=s,e.buildStateDescriptor=n,e.checkProcessDescriptor=function(e){return function e(t,n=[],r=[]){r=[...r,t.key];const o=Object.assign({key:t.key},function(e){const t={},n={};for(const[s,r]of Object.entries(e.transitions)){t[s]=(t[s]||0)+1;for(const e of Object.values(r))n[e]=(n[e]||0)+1}const r=[],o=[];for(const e of Object.keys(t))e===s.STATE_ANY||e===s.STATE_FINAL||e===s.STATE_INITIAL||e in n||r.push(e);for(const e of Object.keys(n))e===s.STATE_FINAL||e in t||o.push(e);return{unreachableStates:r,deadendStates:o}}(t));if(o.deadendStates.length||o.unreachableStates.length){const e={path:r};n.push(e),o.deadendStates.length&&(e.deadendStates=o.deadendStates),o.unreachableStates.length&&(e.unreachableStates=o.unreachableStates)}for(const s of Object.values(t.states))e(s,n,r);return n}(e)},e.getAllStateKeys=function(e){const t={},n=e=>t[e]=(t[e]||0)+1;return function e(t){n(t.key);for(const[e,s]of Object.entries(t.transitions)){n(e);for(const e of Object.values(s))n(e)}for(const[s,r]of Object.entries(t.states))n(s),e(r)}(e),Object.keys(t).sort()},e.getAllTransitions=function(e){const t=[];let n=e.current?e.current.key:s.STATE_INITIAL;for(let r=e.stack.length-1;r>=0;r--){const o=e.stack[r],c=o.key,i=o.descriptor;for(const e of[n,s.STATE_ANY]){const n=i.transitions[e];if(n)for(const[s,r]of Object.entries(n))t.push([c,e,s,r])}n=c}return t},e.getStateDescriptor=r,e.getTargetStateKey=o,e.newAsyncProcess=function({config:e,descriptor:n,before:s,after:r,newProcess:o,newState:i,handleError:a=console.error}){const[f,u]=c({config:e,descriptor:n,newProcess:o,newState:i}),l=t.newAsyncTreeWalker(s,r,f);return f.finished=!1,f.next=e=>(f.nextEvent=e,f.running=f.running||Promise.resolve().then((async()=>{try{for(f.event=f.nextEvent,f.nextEvent=void 0;!f.finished&&f.event;)if(f.finished=!await l(u),f.status&t.MODE.EXIT&&f.nextEvent)f.event=f.nextEvent,f.nextEvent=void 0;else if(f.status&t.MODE.LEAF)break}catch(e){a(e)}})).finally((()=>f.running=void 0)).then((()=>!f.finished))),f},e.newProcessInstance=c,e.newSyncProcess=function({config:e,descriptor:n,before:s,after:r,newProcess:o,newState:i}){const[a,f]=c({config:e,descriptor:n,newProcess:o,newState:i}),u=t.newTreeWalker(s,r,a);return a.dispatch=a.next=e=>{for("string"==typeof e&&(e={key:e}),a.event=e;a.event;){if(!u(f))return!1;if(a.status&t.MODE.LEAF)return!0}},a},Object.keys(t).forEach((function(n){"default"===n||e.hasOwnProperty(n)||Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[n]}})})),Object.defineProperty(e,"__esModule",{value:!0})}));
@@ -1,59 +1,6 @@
1
- // @statewalker/fsm v0.9.4 https://github.com/statewalker/statewalker Copyright 2022 Mikhail Kotelnikov
2
- const MODE = {
3
- NONE : 0,
4
- FIRST: 1, // old=true; new=true => ENTER + ENTER
5
- NEXT: 2, // old=false; new=true => EXIT + ENTER
6
- LEAF : 4, // old=true; new=false => ENTER + EXIT
7
- LAST : 8, // old=false; new=false => EXIT + EXIT
8
-
9
- ENTER: 1 | 2, // MODE.FIRST | MODE.NEXT
10
- EXIT : 4 | 8 // MODE.LEAF | MODE.LAST
11
- };
12
- var MODE$1 = MODE;
13
-
14
- function newTreeWalker(
15
- before, after,
16
- context = { stack: [], status: MODE$1.NONE }
17
- ) {
18
- return (getNode) => {
19
- let status = context.status;
20
- const prev = status & MODE$1.EXIT;
21
- if (prev) after(context);
22
- if (status & MODE$1.ENTER) context.stack.push(context.current);
23
- let node = getNode(context);
24
- if (node) {
25
- context.current = node;
26
- status = context.status = prev ? MODE$1.NEXT : MODE$1.FIRST;
27
- before(context);
28
- } else {
29
- node = context.current = context.stack.pop();
30
- status = context.status = node ? prev ? MODE$1.LAST : MODE$1.LEAF : MODE$1.NONE;
31
- }
32
- return status !== MODE$1.NONE;
33
- }
34
- }
35
-
36
- function newAsyncTreeWalker(
37
- before, after,
38
- context = { stack: [], status: MODE$1.NONE }
39
- ) {
40
- return async (getNode) => {
41
- let status = context.status;
42
- const prev = status & MODE$1.EXIT;
43
- if (prev) await after(context);
44
- if (status & MODE$1.ENTER) await context.stack.push(context.current);
45
- let node = await getNode(context);
46
- if (node) {
47
- context.current = node;
48
- status = context.status = prev ? MODE$1.NEXT : MODE$1.FIRST;
49
- await before(context);
50
- } else {
51
- node = context.current = await context.stack.pop();
52
- status = context.status = node ? prev ? MODE$1.LAST : MODE$1.LEAF : MODE$1.NONE;
53
- }
54
- return status !== MODE$1.NONE;
55
- }
56
- }
1
+ // @statewalker/fsm v0.10.1 https://github.com/statewalker/statewalker-tree Copyright 2022 Mikhail Kotelnikov
2
+ import { MODE, newAsyncTreeWalker, newTreeWalker } from '@statewalker/tree';
3
+ export * from '@statewalker/tree';
57
4
 
58
5
  function buildStateDescriptor(config = {}) {
59
6
  const { key, transitions = [], states = {}, options, ...params } = config;
@@ -263,7 +210,7 @@ function newProcessInstance({
263
210
  } else {
264
211
  const eventKey = process.event.key || KEYS.EVENT_EMPTY;
265
212
  const parentDescriptor = process.stack[process.stack.length - 1].descriptor;
266
- const stateKey = process.status & MODE$1.ENTER
213
+ const stateKey = process.status & MODE.ENTER
267
214
  ? KEYS.STATE_INITIAL
268
215
  : process.current ? process.current.key : KEYS.STATE_FINAL;
269
216
  key = getTargetStateKey(parentDescriptor, stateKey, eventKey);
@@ -303,11 +250,11 @@ function newAsyncProcess({
303
250
  process.nextEvent = undefined;
304
251
  while (!process.finished && process.event) {
305
252
  process.finished = !await shift(loadNextState);
306
- if ((process.status & MODE$1.EXIT) && process.nextEvent) {
253
+ if ((process.status & MODE.EXIT) && process.nextEvent) {
307
254
  // Consume the next event if it exists.
308
255
  process.event = process.nextEvent;
309
256
  process.nextEvent = undefined;
310
- } else if (process.status & MODE$1.LEAF) {
257
+ } else if (process.status & MODE.LEAF) {
311
258
  // Returns control when the process is in a "leaf" state (a state without children)
312
259
  break;
313
260
  }
@@ -341,10 +288,10 @@ function newSyncProcess({
341
288
  process.event = event;
342
289
  while (process.event) {
343
290
  if (!shift(loadNextState)) return false;
344
- if (process.status & MODE$1.LEAF) return true;
291
+ if (process.status & MODE.LEAF) return true;
345
292
  }
346
293
  };
347
294
  return process;
348
295
  }
349
296
 
350
- export { KEYS, MODE$1 as MODE, buildStateDescriptor, checkProcessDescriptor, getAllStateKeys, getAllTransitions, getStateDescriptor, getTargetStateKey, newAsyncProcess, newAsyncTreeWalker, newProcessInstance, newSyncProcess, newTreeWalker };
297
+ export { KEYS, buildStateDescriptor, checkProcessDescriptor, getAllStateKeys, getAllTransitions, getStateDescriptor, getTargetStateKey, newAsyncProcess, newProcessInstance, newSyncProcess };
@@ -0,0 +1,2 @@
1
+ // @statewalker/fsm v0.10.1 https://github.com/statewalker/statewalker-tree Copyright 2022 Mikhail Kotelnikov
2
+ import{MODE as t,newAsyncTreeWalker as e,newTreeWalker as n}from"@statewalker/tree";export*from"@statewalker/tree";function s(t={}){const{key:e,transitions:n=[],states:r={},options:o,...c}=t,i={key:e,transitions:{},states:{},options:Object.assign(o||{},c)};for(const t of n){let e,n,s;if(Array.isArray(t))e=t[0],n=t[1],s=t[2];else{const{from:r,event:o,to:c}=t;e=r,n=o,s=c}(i.transitions[e]=i.transitions[e]||{})[n]=s}if(Array.isArray(r))for(const t of r)i.states[t.key]=s(t);else if(r)for(const t of Object.keys(r))i.states[t]=s(r[t]);return i}var r={STATE_ANY:"*",STATE_INITIAL:"",STATE_FINAL:"",EVENT_ANY:"*",EVENT_EMPTY:""};function o(t){return function t(e,n=[],s=[]){s=[...s,e.key];const o=Object.assign({key:e.key},function(t){const e={},n={};for(const[s,r]of Object.entries(t.transitions)){e[s]=(e[s]||0)+1;for(const t of Object.values(r))n[t]=(n[t]||0)+1}const s=[],o=[];for(const t of Object.keys(e))t===r.STATE_ANY||t===r.STATE_FINAL||t===r.STATE_INITIAL||t in n||s.push(t);for(const t of Object.keys(n))t===r.STATE_FINAL||t in e||o.push(t);return{unreachableStates:s,deadendStates:o}}(e));if(o.deadendStates.length||o.unreachableStates.length){const t={path:s};n.push(t),o.deadendStates.length&&(t.deadendStates=o.deadendStates),o.unreachableStates.length&&(t.unreachableStates=o.unreachableStates)}for(const r of Object.values(e.states))t(r,n,s);return n}(t)}function c(t,e){let n;for(let s=t.stack.length-1;!n&&s>=0;s--){n=(t.stack[s].descriptor.states||{})[e]}return n||{transitions:{},states:{}}}function i(t){const e={},n=t=>e[t]=(e[t]||0)+1;return function t(e){n(e.key);for(const[t,s]of Object.entries(e.transitions)){n(t);for(const t of Object.values(s))n(t)}for(const[s,r]of Object.entries(e.states))n(s),t(r)}(t),Object.keys(e).sort()}function a(t){const e=[];let n=t.current?t.current.key:r.STATE_INITIAL;for(let s=t.stack.length-1;s>=0;s--){const o=t.stack[s],c=o.key,i=o.descriptor;for(const t of[n,r.STATE_ANY]){const n=i.transitions[t];if(n)for(const[s,r]of Object.entries(n))e.push([c,t,s,r])}n=c}return e}function f(t,e,n){const s=[[e,n],[r.STATE_ANY,n],[e,r.EVENT_ANY],[r.STATE_ANY,r.EVENT_ANY]];let o;for(let e=0,n=s.length;void 0===o&&e<n;e++){const[n,c]=s[e],i=t.transitions[n];i&&(o=i[c],void 0===o&&(o=i[r.EVENT_ANY]))}return void 0!==o?o:r.STATE_FINAL}function u({config:e,descriptor:n,newState:o=(t=>t),newProcess:i=(t=>({descriptor:t,status:0,stack:[],event:void 0,current:void 0}))}){const a=i(n=n||s(e));return[a,()=>{let e,n;if(a.status)if(a.stack.length){const s=a.event.key||r.EVENT_EMPTY;e=f(a.stack[a.stack.length-1].descriptor,a.status&t.ENTER?r.STATE_INITIAL:a.current?a.current.key:r.STATE_FINAL,s),e&&(n=c(a,e))}else e=r.STATE_FINAL;else n=a.descriptor,e=n.key;return e?o({process:a,key:e,descriptor:n}):null}]}function T({config:n,descriptor:s,before:r,after:o,newProcess:c,newState:i,handleError:a=console.error}){const[f,T]=u({config:n,descriptor:s,newProcess:c,newState:i}),E=e(r,o,f);return f.finished=!1,f.next=e=>(f.nextEvent=e,f.running=f.running||Promise.resolve().then((async()=>{try{for(f.event=f.nextEvent,f.nextEvent=void 0;!f.finished&&f.event;)if(f.finished=!await E(T),f.status&t.EXIT&&f.nextEvent)f.event=f.nextEvent,f.nextEvent=void 0;else if(f.status&t.LEAF)break}catch(t){a(t)}})).finally((()=>f.running=void 0)).then((()=>!f.finished))),f}function E({config:e,descriptor:s,before:r,after:o,newProcess:c,newState:i}){const[a,f]=u({config:e,descriptor:s,newProcess:c,newState:i}),T=n(r,o,a);return a.dispatch=a.next=e=>{for("string"==typeof e&&(e={key:e}),a.event=e;a.event;){if(!T(f))return!1;if(a.status&t.LEAF)return!0}},a}export{r as KEYS,s as buildStateDescriptor,o as checkProcessDescriptor,i as getAllStateKeys,a as getAllTransitions,c as getStateDescriptor,f as getTargetStateKey,T as newAsyncProcess,u as newProcessInstance,E as newSyncProcess};
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@statewalker/fsm",
3
- "version": "0.9.4",
4
- "description": "Utility graph methods (iterators, tree builders etc)",
3
+ "version": "0.10.1",
4
+ "description": "HFSM Implementation",
5
5
  "keywords": [],
6
- "homepage": "https://github.com/statewalker/statewalker",
6
+ "homepage": "https://github.com/statewalker/statewalker-tree",
7
7
  "author": {
8
8
  "name": "Mikhail Kotelnikov",
9
9
  "email": "mikhail.kotelnikov@gmail.com"
@@ -15,31 +15,31 @@
15
15
  "src/**/*.js",
16
16
  "index.js"
17
17
  ],
18
- "main": "dist/esm/statewalker-fsm-esm.js",
19
- "module": "dist/esm/statewalker-fsm-esm.js",
20
- "jsdelivr": "dist/cjs/statewalker-fsm.min.js",
21
- "unpkg": "dist/cjs/statewalker-fsm.min.js",
18
+ "dependencies": {
19
+ "@statewalker/tree": "0.10.0"
20
+ },
21
+ "devDependencies": {
22
+ "@statewalker/rollup": "^0.1.4",
23
+ "eslint": "^8",
24
+ "expect.js": "^0.3",
25
+ "mocha": "^10",
26
+ "rollup": "^2"
27
+ },
28
+ "module": "src/index.js",
22
29
  "exports": {
23
- "package.json": "./package.json",
24
- "umd": "./dist/cjs/statewalker-fsm.min.js",
25
- "require": "./dist/cjs/statewalker-fsm.js",
26
30
  "import": "./src/index.js",
27
- "default": "./dist/esm/statewalker-fsm-esm.js"
31
+ "umd": "./dist/index-umd.min.js",
32
+ "default": "./dist/index.js"
28
33
  },
29
34
  "repository": {
30
35
  "type": "git",
31
- "url": "https://github.com/statewalker/statewalker.git"
32
- },
33
- "devDependencies": {
34
- "@statewalker/tree": "^0.9.1"
36
+ "url": "git@github.com:statewalker/statewalker-fsm.git"
35
37
  },
36
38
  "scripts": {
37
- "eslint": "../../node_modules/eslint/bin/eslint.js src",
38
- "rollup": "../../node_modules/rollup/dist/bin/rollup -c",
39
- "test": "../../node_modules/mocha/bin/mocha -R spec ./test/index.js && yarn eslint",
40
- "prepare": "yarn rollup",
41
- "prepublishOnly": "rm -rf dist && yarn test && yarn rollup",
42
- "postpublish": "zip -j dist/statewalker-fsm.zip -- ../../LICENSE README.md dist/*.js"
39
+ "eslint": "eslint src",
40
+ "rollup": "rollup -c",
41
+ "test": "mocha -R spec ./test/index.js && yarn eslint",
42
+ "prepublishOnly": "rm -rf dist && yarn test && yarn rollup"
43
43
  },
44
44
  "license": "MIT",
45
45
  "sideEffects": false,
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }
@@ -1,2 +0,0 @@
1
- // @statewalker/fsm v0.9.4 https://github.com/statewalker/statewalker Copyright 2022 Mikhail Kotelnikov
2
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(((t="undefined"!=typeof globalThis?globalThis:t||self).statewalker=t.statewalker||{},t.statewalker.fsm=t.statewalker.fsm||{}))}(this,(function(t){"use strict";var e={NONE:0,FIRST:1,NEXT:2,LEAF:4,LAST:8,ENTER:3,EXIT:12};function n(t,n,s={stack:[],status:e.NONE}){return r=>{let o=s.status;const c=o&e.EXIT;c&&n(s),o&e.ENTER&&s.stack.push(s.current);let a=r(s);return a?(s.current=a,o=s.status=c?e.NEXT:e.FIRST,t(s)):(a=s.current=s.stack.pop(),o=s.status=a?c?e.LAST:e.LEAF:e.NONE),o!==e.NONE}}function s(t,n,s={stack:[],status:e.NONE}){return async r=>{let o=s.status;const c=o&e.EXIT;c&&await n(s),o&e.ENTER&&await s.stack.push(s.current);let a=await r(s);return a?(s.current=a,o=s.status=c?e.NEXT:e.FIRST,await t(s)):(a=s.current=await s.stack.pop(),o=s.status=a?c?e.LAST:e.LEAF:e.NONE),o!==e.NONE}}function r(t={}){const{key:e,transitions:n=[],states:s={},options:o,...c}=t,a={key:e,transitions:{},states:{},options:Object.assign(o||{},c)};for(const t of n){let e,n,s;if(Array.isArray(t))e=t[0],n=t[1],s=t[2];else{const{from:r,event:o,to:c}=t;e=r,n=o,s=c}(a.transitions[e]=a.transitions[e]||{})[n]=s}if(Array.isArray(s))for(const t of s)a.states[t.key]=r(t);else if(s)for(const t of Object.keys(s))a.states[t]=r(s[t]);return a}var o={STATE_ANY:"*",STATE_INITIAL:"",STATE_FINAL:"",EVENT_ANY:"*",EVENT_EMPTY:""};function c(t,e){let n;for(let s=t.stack.length-1;!n&&s>=0;s--){n=(t.stack[s].descriptor.states||{})[e]}return n||{transitions:{},states:{}}}function a(t,e,n){const s=[[e,n],[o.STATE_ANY,n],[e,o.EVENT_ANY],[o.STATE_ANY,o.EVENT_ANY]];let r;for(let e=0,n=s.length;void 0===r&&e<n;e++){const[n,c]=s[e],a=t.transitions[n];a&&(r=a[c],void 0===r&&(r=a[o.EVENT_ANY]))}return void 0!==r?r:o.STATE_FINAL}function i({config:t,descriptor:n,newState:s=(t=>t),newProcess:i=(t=>({descriptor:t,status:0,stack:[],event:void 0,current:void 0}))}){const f=i(n=n||r(t));return[f,()=>{let t,n;if(f.status)if(f.stack.length){const s=f.event.key||o.EVENT_EMPTY;t=a(f.stack[f.stack.length-1].descriptor,f.status&e.ENTER?o.STATE_INITIAL:f.current?f.current.key:o.STATE_FINAL,s),t&&(n=c(f,t))}else t=o.STATE_FINAL;else n=f.descriptor,t=n.key;return t?s({process:f,key:t,descriptor:n}):null}]}t.KEYS=o,t.MODE=e,t.buildStateDescriptor=r,t.checkProcessDescriptor=function(t){return function t(e,n=[],s=[]){s=[...s,e.key];const r=Object.assign({key:e.key},function(t){const e={},n={};for(const[s,r]of Object.entries(t.transitions)){e[s]=(e[s]||0)+1;for(const t of Object.values(r))n[t]=(n[t]||0)+1}const s=[],r=[];for(const t of Object.keys(e))t===o.STATE_ANY||t===o.STATE_FINAL||t===o.STATE_INITIAL||t in n||s.push(t);for(const t of Object.keys(n))t===o.STATE_FINAL||t in e||r.push(t);return{unreachableStates:s,deadendStates:r}}(e));if(r.deadendStates.length||r.unreachableStates.length){const t={path:s};n.push(t),r.deadendStates.length&&(t.deadendStates=r.deadendStates),r.unreachableStates.length&&(t.unreachableStates=r.unreachableStates)}for(const r of Object.values(e.states))t(r,n,s);return n}(t)},t.getAllStateKeys=function(t){const e={},n=t=>e[t]=(e[t]||0)+1;return function t(e){n(e.key);for(const[t,s]of Object.entries(e.transitions)){n(t);for(const t of Object.values(s))n(t)}for(const[s,r]of Object.entries(e.states))n(s),t(r)}(t),Object.keys(e).sort()},t.getAllTransitions=function(t){const e=[];let n=t.current?t.current.key:o.STATE_INITIAL;for(let s=t.stack.length-1;s>=0;s--){const r=t.stack[s],c=r.key,a=r.descriptor;for(const t of[n,o.STATE_ANY]){const n=a.transitions[t];if(n)for(const[s,r]of Object.entries(n))e.push([c,t,s,r])}n=c}return e},t.getStateDescriptor=c,t.getTargetStateKey=a,t.newAsyncProcess=function({config:t,descriptor:n,before:r,after:o,newProcess:c,newState:a,handleError:f=console.error}){const[u,E]=i({config:t,descriptor:n,newProcess:c,newState:a}),T=s(r,o,u);return u.finished=!1,u.next=t=>(u.nextEvent=t,u.running=u.running||Promise.resolve().then((async()=>{try{for(u.event=u.nextEvent,u.nextEvent=void 0;!u.finished&&u.event;)if(u.finished=!await T(E),u.status&e.EXIT&&u.nextEvent)u.event=u.nextEvent,u.nextEvent=void 0;else if(u.status&e.LEAF)break}catch(t){f(t)}})).finally((()=>u.running=void 0)).then((()=>!u.finished))),u},t.newAsyncTreeWalker=s,t.newProcessInstance=i,t.newSyncProcess=function({config:t,descriptor:s,before:r,after:o,newProcess:c,newState:a}){const[f,u]=i({config:t,descriptor:s,newProcess:c,newState:a}),E=n(r,o,f);return f.dispatch=f.next=t=>{for("string"==typeof t&&(t={key:t}),f.event=t;f.event;){if(!E(u))return!1;if(f.status&e.LEAF)return!0}},f},t.newTreeWalker=n,Object.defineProperty(t,"__esModule",{value:!0})}));
@@ -1,2 +0,0 @@
1
- // @statewalker/fsm v0.9.4 https://github.com/statewalker/statewalker Copyright 2022 Mikhail Kotelnikov
2
- var t={NONE:0,FIRST:1,NEXT:2,LEAF:4,LAST:8,ENTER:3,EXIT:12};function e(e,n,s={stack:[],status:t.NONE}){return r=>{let o=s.status;const c=o&t.EXIT;c&&n(s),o&t.ENTER&&s.stack.push(s.current);let a=r(s);return a?(s.current=a,o=s.status=c?t.NEXT:t.FIRST,e(s)):(a=s.current=s.stack.pop(),o=s.status=a?c?t.LAST:t.LEAF:t.NONE),o!==t.NONE}}function n(e,n,s={stack:[],status:t.NONE}){return async r=>{let o=s.status;const c=o&t.EXIT;c&&await n(s),o&t.ENTER&&await s.stack.push(s.current);let a=await r(s);return a?(s.current=a,o=s.status=c?t.NEXT:t.FIRST,await e(s)):(a=s.current=await s.stack.pop(),o=s.status=a?c?t.LAST:t.LEAF:t.NONE),o!==t.NONE}}function s(t={}){const{key:e,transitions:n=[],states:r={},options:o,...c}=t,a={key:e,transitions:{},states:{},options:Object.assign(o||{},c)};for(const t of n){let e,n,s;if(Array.isArray(t))e=t[0],n=t[1],s=t[2];else{const{from:r,event:o,to:c}=t;e=r,n=o,s=c}(a.transitions[e]=a.transitions[e]||{})[n]=s}if(Array.isArray(r))for(const t of r)a.states[t.key]=s(t);else if(r)for(const t of Object.keys(r))a.states[t]=s(r[t]);return a}var r={STATE_ANY:"*",STATE_INITIAL:"",STATE_FINAL:"",EVENT_ANY:"*",EVENT_EMPTY:""};function o(t){return function t(e,n=[],s=[]){s=[...s,e.key];const o=Object.assign({key:e.key},function(t){const e={},n={};for(const[s,r]of Object.entries(t.transitions)){e[s]=(e[s]||0)+1;for(const t of Object.values(r))n[t]=(n[t]||0)+1}const s=[],o=[];for(const t of Object.keys(e))t===r.STATE_ANY||t===r.STATE_FINAL||t===r.STATE_INITIAL||t in n||s.push(t);for(const t of Object.keys(n))t===r.STATE_FINAL||t in e||o.push(t);return{unreachableStates:s,deadendStates:o}}(e));if(o.deadendStates.length||o.unreachableStates.length){const t={path:s};n.push(t),o.deadendStates.length&&(t.deadendStates=o.deadendStates),o.unreachableStates.length&&(t.unreachableStates=o.unreachableStates)}for(const r of Object.values(e.states))t(r,n,s);return n}(t)}function c(t,e){let n;for(let s=t.stack.length-1;!n&&s>=0;s--){n=(t.stack[s].descriptor.states||{})[e]}return n||{transitions:{},states:{}}}function a(t){const e={},n=t=>e[t]=(e[t]||0)+1;return function t(e){n(e.key);for(const[t,s]of Object.entries(e.transitions)){n(t);for(const t of Object.values(s))n(t)}for(const[s,r]of Object.entries(e.states))n(s),t(r)}(t),Object.keys(e).sort()}function i(t){const e=[];let n=t.current?t.current.key:r.STATE_INITIAL;for(let s=t.stack.length-1;s>=0;s--){const o=t.stack[s],c=o.key,a=o.descriptor;for(const t of[n,r.STATE_ANY]){const n=a.transitions[t];if(n)for(const[s,r]of Object.entries(n))e.push([c,t,s,r])}n=c}return e}function u(t,e,n){const s=[[e,n],[r.STATE_ANY,n],[e,r.EVENT_ANY],[r.STATE_ANY,r.EVENT_ANY]];let o;for(let e=0,n=s.length;void 0===o&&e<n;e++){const[n,c]=s[e],a=t.transitions[n];a&&(o=a[c],void 0===o&&(o=a[r.EVENT_ANY]))}return void 0!==o?o:r.STATE_FINAL}function f({config:e,descriptor:n,newState:o=(t=>t),newProcess:a=(t=>({descriptor:t,status:0,stack:[],event:void 0,current:void 0}))}){const i=a(n=n||s(e));return[i,()=>{let e,n;if(i.status)if(i.stack.length){const s=i.event.key||r.EVENT_EMPTY;e=u(i.stack[i.stack.length-1].descriptor,i.status&t.ENTER?r.STATE_INITIAL:i.current?i.current.key:r.STATE_FINAL,s),e&&(n=c(i,e))}else e=r.STATE_FINAL;else n=i.descriptor,e=n.key;return e?o({process:i,key:e,descriptor:n}):null}]}function E({config:e,descriptor:s,before:r,after:o,newProcess:c,newState:a,handleError:i=console.error}){const[u,E]=f({config:e,descriptor:s,newProcess:c,newState:a}),T=n(r,o,u);return u.finished=!1,u.next=e=>(u.nextEvent=e,u.running=u.running||Promise.resolve().then((async()=>{try{for(u.event=u.nextEvent,u.nextEvent=void 0;!u.finished&&u.event;)if(u.finished=!await T(E),u.status&t.EXIT&&u.nextEvent)u.event=u.nextEvent,u.nextEvent=void 0;else if(u.status&t.LEAF)break}catch(t){i(t)}})).finally((()=>u.running=void 0)).then((()=>!u.finished))),u}function T({config:n,descriptor:s,before:r,after:o,newProcess:c,newState:a}){const[i,u]=f({config:n,descriptor:s,newProcess:c,newState:a}),E=e(r,o,i);return i.dispatch=i.next=e=>{for("string"==typeof e&&(e={key:e}),i.event=e;i.event;){if(!E(u))return!1;if(i.status&t.LEAF)return!0}},i}export{r as KEYS,t as MODE,s as buildStateDescriptor,o as checkProcessDescriptor,a as getAllStateKeys,i as getAllTransitions,c as getStateDescriptor,u as getTargetStateKey,E as newAsyncProcess,n as newAsyncTreeWalker,f as newProcessInstance,T as newSyncProcess,e as newTreeWalker};