@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 +21 -0
- package/README.md +1 -1
- package/dist/{cjs/statewalker-fsm.js → index-umd.js} +17 -70
- package/dist/index-umd.min.js +2 -0
- package/dist/{esm/statewalker-fsm-esm.js → index.js} +8 -61
- package/dist/index.min.js +2 -0
- package/package.json +21 -21
- package/dist/cjs/package.json +0 -3
- package/dist/cjs/statewalker-fsm.min.js +0 -2
- package/dist/esm/statewalker-fsm-esm.min.js +0 -2
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
|
|
1
|
+
# @statewalker/fsm: Hierarchical Finite State Machine
|
|
@@ -1,65 +1,9 @@
|
|
|
1
|
-
// @statewalker/fsm v0.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
2
|
-
|
|
3
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
291
|
+
if (process.status & MODE.LEAF) return true;
|
|
345
292
|
}
|
|
346
293
|
};
|
|
347
294
|
return process;
|
|
348
295
|
}
|
|
349
296
|
|
|
350
|
-
export { KEYS,
|
|
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.
|
|
4
|
-
"description": "
|
|
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
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
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
|
-
"
|
|
31
|
+
"umd": "./dist/index-umd.min.js",
|
|
32
|
+
"default": "./dist/index.js"
|
|
28
33
|
},
|
|
29
34
|
"repository": {
|
|
30
35
|
"type": "git",
|
|
31
|
-
"url": "
|
|
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": "
|
|
38
|
-
"rollup": "
|
|
39
|
-
"test": "
|
|
40
|
-
"
|
|
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,
|
package/dist/cjs/package.json
DELETED
|
@@ -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};
|