@alwatr/fsm 1.1.2 → 2.0.0
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/CHANGELOG.md +73 -64
- package/base.d.ts +47 -0
- package/base.d.ts.map +1 -0
- package/base.js +90 -0
- package/base.js.map +1 -0
- package/fsm.d.ts +15 -0
- package/fsm.d.ts.map +1 -0
- package/fsm.js +19 -0
- package/fsm.js.map +1 -0
- package/index.d.ts +3 -21
- package/index.d.ts.map +1 -1
- package/index.js +3 -11
- package/index.js.map +1 -1
- package/package.json +9 -9
- package/type.d.ts +10 -106
- package/type.d.ts.map +1 -1
- package/type.js.map +1 -1
- package/core.d.ts +0 -158
- package/core.d.ts.map +0 -1
- package/core.js +0 -351
- package/core.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,11 +3,20 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# 2.0.0 (2023-09-19)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* all new repo path and packages dependencies ([21a6afa](https://github.com/AliMD/alwatr-signal/commit/21a6afa0badafe4051617d9a9e3bbfbaabd0c4ad)) by @AliMD
|
|
11
|
+
* cleanup old signal and fsm v1 ([bde0bea](https://github.com/AliMD/alwatr-signal/commit/bde0bea06a6750bebad49a127b75b57fd5e55ddd)) by @AliMD
|
|
12
|
+
* **fsm:** import issue ([9674f34](https://github.com/AliMD/alwatr-signal/commit/9674f34a7c63137fb9597d2b465b4fb123c963c1)) by @AliMD
|
|
13
|
+
* ts refrence path ([c2baa44](https://github.com/AliMD/alwatr-signal/commit/c2baa44999c72a0015481fc8fea25439329c3f37)) by @AliMD
|
|
14
|
+
|
|
15
|
+
## [1.1.2](https://github.com/AliMD/alwatr-signal/compare/@alwatr/fsm@1.1.1...@alwatr/fsm@1.1.2) (2023-09-12)
|
|
7
16
|
|
|
8
17
|
**Note:** Version bump only for package @alwatr/fsm
|
|
9
18
|
|
|
10
|
-
## [1.1.1](https://github.com/AliMD/alwatr/compare/@alwatr/fsm@1.1.0...@alwatr/fsm@1.1.1) (2023-09-12)
|
|
19
|
+
## [1.1.1](https://github.com/AliMD/alwatr-signal/compare/@alwatr/fsm@1.1.0...@alwatr/fsm@1.1.1) (2023-09-12)
|
|
11
20
|
|
|
12
21
|
**Note:** Version bump only for package @alwatr/fsm
|
|
13
22
|
|
|
@@ -21,96 +30,96 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
|
|
21
30
|
|
|
22
31
|
### Bug Fixes
|
|
23
32
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
- **fms:** import path ([f6770a0](https://github.com/AliMD/alwatr-signal/commit/f6770a07fdf6855ccd63a85822d44d5ef9c72dee))
|
|
34
|
+
- **fsm:** action maybe async ([50efffa](https://github.com/AliMD/alwatr-signal/commit/50efffa34a2ea5a3515561d7425da0c109631f36))
|
|
35
|
+
- **fsm:** autoSignalUnsubscribe type ([f7db30b](https://github.com/AliMD/alwatr-signal/commit/f7db30bf5a90ff3d163f036b313a412a5149ff2b))
|
|
36
|
+
- **fsm:** call render states function in there own this ([a950478](https://github.com/AliMD/alwatr-signal/commit/a95047811366e375785b2cd8fb176b1176638cab))
|
|
37
|
+
- **fsm:** fix order of `initFsmInstance` args ([3b60138](https://github.com/AliMD/alwatr-signal/commit/3b60138ecebcbcb4d732e4d1a3e79f5b8661ae47))
|
|
38
|
+
- **fsm:** initial exec actions ([e7dd5c8](https://github.com/AliMD/alwatr-signal/commit/e7dd5c8aaf9760c9856e4392cc899020f7e796d9))
|
|
39
|
+
- **fsm:** last reported bugs in set state ([e7435c8](https://github.com/AliMD/alwatr-signal/commit/e7435c870a054b0ec3e4004f13c6db7610610be0))
|
|
40
|
+
- **fsm:** review reset process ([af6e81c](https://github.com/AliMD/alwatr-signal/commit/af6e81c068b467d8b3aa96f2431e13ac479f018c))
|
|
41
|
+
- **fsm:** run init entry actions ([777ae45](https://github.com/AliMD/alwatr-signal/commit/777ae459f2b77f79696daf3a0ca355d6d78e57d3))
|
|
42
|
+
- new logger api ([9d83a7d](https://github.com/AliMD/alwatr-signal/commit/9d83a7dc5c103bc3bb4282dacfd85fa998915300))
|
|
34
43
|
|
|
35
44
|
### Features
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
- **fsm:** add `signalRecord` to config ([1a35291](https://github.com/AliMD/alwatr-signal/commit/1a352915fba978da141513517655d1e07350c3ec))
|
|
47
|
+
- **fsm:** add unsubscribe ([85ed3c3](https://github.com/AliMD/alwatr-signal/commit/85ed3c3439e1f40c2760f6011df112242f10be06))
|
|
48
|
+
- **fsm:** callback in provider signals ([772818b](https://github.com/AliMD/alwatr-signal/commit/772818baa7953b6fbb4d4128fcee76733f42cc2d))
|
|
49
|
+
- **fsm:** custom signal callback ([47c22e9](https://github.com/AliMD/alwatr-signal/commit/47c22e92a8a8085148b44b316d649b695ff8071a))
|
|
50
|
+
- **fsm:** destroy and expire api ([e1a1c15](https://github.com/AliMD/alwatr-signal/commit/e1a1c150d81f4428718bd18f039235c7fce9caf2))
|
|
51
|
+
- **fsm:** new types ([2866e3b](https://github.com/AliMD/alwatr-signal/commit/2866e3bd5ff56fd2b5bddcaed3673a5868bae4bb))
|
|
52
|
+
- **fsm:** rewrite state machine ([7f24695](https://github.com/AliMD/alwatr-signal/commit/7f246959e5a80b21c1c4b21e895e75f8fbe56798))
|
|
53
|
+
- **fsm:** subscribe ([2af4f44](https://github.com/AliMD/alwatr-signal/commit/2af4f44f0e8a2dee39cde10dcaa3281075632e6a))
|
|
45
54
|
|
|
46
55
|
# 0.30.0 (2023-03-06)
|
|
47
56
|
|
|
48
57
|
### Bug Fixes
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
- **fsm:** every signal mather ([0dc504d](https://github.com/AliMD/alwatr-signal/commit/0dc504dacbb1ec68f154244619d644ff8e43cc04))
|
|
60
|
+
- **fsm:** remove additional import ([231337b](https://github.com/AliMD/alwatr-signal/commit/231337b95ee7b046fe35429f50931ddf85be291f))
|
|
61
|
+
- **fsm:** update context in transition bug ([28a21d0](https://github.com/AliMD/alwatr-signal/commit/28a21d00d903b6189d814303c72ba6e784852f33))
|
|
53
62
|
|
|
54
63
|
### Features
|
|
55
64
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
- Alwatr Finite State Machines ([d5900b4](https://github.com/AliMD/alwatr-signal/commit/d5900b4ee8685b120188888871405853f5a69417))
|
|
66
|
+
- **fsm:** $all and $self state ([69adf41](https://github.com/AliMD/alwatr-signal/commit/69adf41064ca0f55497484c50e298ebc26c42dcc))
|
|
67
|
+
- **fsm:** enhance types ([3b13046](https://github.com/AliMD/alwatr-signal/commit/3b130463a102f59c38603b0de470be5c87ee88c9))
|
|
68
|
+
- **fsm:** make simple state machine ([ff9ae1c](https://github.com/AliMD/alwatr-signal/commit/ff9ae1ca04156e8b811899ff0f62480e1c37af72))
|
|
69
|
+
- **fsm:** new state context type with {to, from, by} ([11423e6](https://github.com/AliMD/alwatr-signal/commit/11423e6a89159b92e82cfd1e774ad37983581090))
|
|
70
|
+
- **fsm:** rewrite with signal power ([01a1651](https://github.com/AliMD/alwatr-signal/commit/01a1651e231a817d5eebb54cf84d51d620bfd6e8))
|
|
71
|
+
- **fsm:** share state events ([de42522](https://github.com/AliMD/alwatr-signal/commit/de42522a97fdf6be8bee73d91a35820e2a5e6efb))
|
|
72
|
+
- **fsm:** transition with partial context set ([823377e](https://github.com/AliMD/alwatr-signal/commit/823377e65028ea3e713f060ae678776c609c1661))
|
|
64
73
|
|
|
65
|
-
# [1.0.0](https://github.com/AliMD/alwatr/compare/v0.32.0...v1.0.0) (2023-06-14)
|
|
74
|
+
# [1.0.0](https://github.com/AliMD/alwatr-signal/compare/v0.32.0...v1.0.0) (2023-06-14)
|
|
66
75
|
|
|
67
76
|
**Note:** Version bump only for package @alwatr/fsm
|
|
68
77
|
|
|
69
|
-
# [0.32.0](https://github.com/AliMD/alwatr/compare/v0.31.0...v0.32.0) (2023-05-27)
|
|
78
|
+
# [0.32.0](https://github.com/AliMD/alwatr-signal/compare/v0.31.0...v0.32.0) (2023-05-27)
|
|
70
79
|
|
|
71
80
|
**Note:** Version bump only for package @alwatr/fsm
|
|
72
81
|
|
|
73
|
-
# [0.31.0](https://github.com/AliMD/alwatr/compare/v0.30.0...v0.31.0) (2023-05-08)
|
|
82
|
+
# [0.31.0](https://github.com/AliMD/alwatr-signal/compare/v0.30.0...v0.31.0) (2023-05-08)
|
|
74
83
|
|
|
75
84
|
### Bug Fixes
|
|
76
85
|
|
|
77
|
-
- **fms:** import path ([f6770a0](https://github.com/AliMD/alwatr/commit/f6770a07fdf6855ccd63a85822d44d5ef9c72dee))
|
|
78
|
-
- **fsm:** action maybe async ([50efffa](https://github.com/AliMD/alwatr/commit/50efffa34a2ea5a3515561d7425da0c109631f36))
|
|
79
|
-
- **fsm:** autoSignalUnsubscribe type ([f7db30b](https://github.com/AliMD/alwatr/commit/f7db30bf5a90ff3d163f036b313a412a5149ff2b))
|
|
80
|
-
- **fsm:** call render states function in there own this ([a950478](https://github.com/AliMD/alwatr/commit/a95047811366e375785b2cd8fb176b1176638cab))
|
|
81
|
-
- **fsm:** fix order of `initFsmInstance` args ([3b60138](https://github.com/AliMD/alwatr/commit/3b60138ecebcbcb4d732e4d1a3e79f5b8661ae47))
|
|
82
|
-
- **fsm:** initial exec actions ([e7dd5c8](https://github.com/AliMD/alwatr/commit/e7dd5c8aaf9760c9856e4392cc899020f7e796d9))
|
|
83
|
-
- **fsm:** last reported bugs in set state ([e7435c8](https://github.com/AliMD/alwatr/commit/e7435c870a054b0ec3e4004f13c6db7610610be0))
|
|
84
|
-
- **fsm:** review reset process ([af6e81c](https://github.com/AliMD/alwatr/commit/af6e81c068b467d8b3aa96f2431e13ac479f018c))
|
|
85
|
-
- **fsm:** run init entry actions ([777ae45](https://github.com/AliMD/alwatr/commit/777ae459f2b77f79696daf3a0ca355d6d78e57d3))
|
|
86
|
-
- new logger api ([9d83a7d](https://github.com/AliMD/alwatr/commit/9d83a7dc5c103bc3bb4282dacfd85fa998915300))
|
|
86
|
+
- **fms:** import path ([f6770a0](https://github.com/AliMD/alwatr-signal/commit/f6770a07fdf6855ccd63a85822d44d5ef9c72dee))
|
|
87
|
+
- **fsm:** action maybe async ([50efffa](https://github.com/AliMD/alwatr-signal/commit/50efffa34a2ea5a3515561d7425da0c109631f36))
|
|
88
|
+
- **fsm:** autoSignalUnsubscribe type ([f7db30b](https://github.com/AliMD/alwatr-signal/commit/f7db30bf5a90ff3d163f036b313a412a5149ff2b))
|
|
89
|
+
- **fsm:** call render states function in there own this ([a950478](https://github.com/AliMD/alwatr-signal/commit/a95047811366e375785b2cd8fb176b1176638cab))
|
|
90
|
+
- **fsm:** fix order of `initFsmInstance` args ([3b60138](https://github.com/AliMD/alwatr-signal/commit/3b60138ecebcbcb4d732e4d1a3e79f5b8661ae47))
|
|
91
|
+
- **fsm:** initial exec actions ([e7dd5c8](https://github.com/AliMD/alwatr-signal/commit/e7dd5c8aaf9760c9856e4392cc899020f7e796d9))
|
|
92
|
+
- **fsm:** last reported bugs in set state ([e7435c8](https://github.com/AliMD/alwatr-signal/commit/e7435c870a054b0ec3e4004f13c6db7610610be0))
|
|
93
|
+
- **fsm:** review reset process ([af6e81c](https://github.com/AliMD/alwatr-signal/commit/af6e81c068b467d8b3aa96f2431e13ac479f018c))
|
|
94
|
+
- **fsm:** run init entry actions ([777ae45](https://github.com/AliMD/alwatr-signal/commit/777ae459f2b77f79696daf3a0ca355d6d78e57d3))
|
|
95
|
+
- new logger api ([9d83a7d](https://github.com/AliMD/alwatr-signal/commit/9d83a7dc5c103bc3bb4282dacfd85fa998915300))
|
|
87
96
|
|
|
88
97
|
### Features
|
|
89
98
|
|
|
90
|
-
- **fsm:** add `signalRecord` to config ([1a35291](https://github.com/AliMD/alwatr/commit/1a352915fba978da141513517655d1e07350c3ec))
|
|
91
|
-
- **fsm:** add unsubscribe ([85ed3c3](https://github.com/AliMD/alwatr/commit/85ed3c3439e1f40c2760f6011df112242f10be06))
|
|
92
|
-
- **fsm:** callback in provider signals ([772818b](https://github.com/AliMD/alwatr/commit/772818baa7953b6fbb4d4128fcee76733f42cc2d))
|
|
93
|
-
- **fsm:** custom signal callback ([47c22e9](https://github.com/AliMD/alwatr/commit/47c22e92a8a8085148b44b316d649b695ff8071a))
|
|
94
|
-
- **fsm:** destroy and expire api ([e1a1c15](https://github.com/AliMD/alwatr/commit/e1a1c150d81f4428718bd18f039235c7fce9caf2))
|
|
95
|
-
- **fsm:** new types ([2866e3b](https://github.com/AliMD/alwatr/commit/2866e3bd5ff56fd2b5bddcaed3673a5868bae4bb))
|
|
96
|
-
- **fsm:** rewrite state machine ([7f24695](https://github.com/AliMD/alwatr/commit/7f246959e5a80b21c1c4b21e895e75f8fbe56798))
|
|
97
|
-
- **fsm:** subscribe ([2af4f44](https://github.com/AliMD/alwatr/commit/2af4f44f0e8a2dee39cde10dcaa3281075632e6a))
|
|
99
|
+
- **fsm:** add `signalRecord` to config ([1a35291](https://github.com/AliMD/alwatr-signal/commit/1a352915fba978da141513517655d1e07350c3ec))
|
|
100
|
+
- **fsm:** add unsubscribe ([85ed3c3](https://github.com/AliMD/alwatr-signal/commit/85ed3c3439e1f40c2760f6011df112242f10be06))
|
|
101
|
+
- **fsm:** callback in provider signals ([772818b](https://github.com/AliMD/alwatr-signal/commit/772818baa7953b6fbb4d4128fcee76733f42cc2d))
|
|
102
|
+
- **fsm:** custom signal callback ([47c22e9](https://github.com/AliMD/alwatr-signal/commit/47c22e92a8a8085148b44b316d649b695ff8071a))
|
|
103
|
+
- **fsm:** destroy and expire api ([e1a1c15](https://github.com/AliMD/alwatr-signal/commit/e1a1c150d81f4428718bd18f039235c7fce9caf2))
|
|
104
|
+
- **fsm:** new types ([2866e3b](https://github.com/AliMD/alwatr-signal/commit/2866e3bd5ff56fd2b5bddcaed3673a5868bae4bb))
|
|
105
|
+
- **fsm:** rewrite state machine ([7f24695](https://github.com/AliMD/alwatr-signal/commit/7f246959e5a80b21c1c4b21e895e75f8fbe56798))
|
|
106
|
+
- **fsm:** subscribe ([2af4f44](https://github.com/AliMD/alwatr-signal/commit/2af4f44f0e8a2dee39cde10dcaa3281075632e6a))
|
|
98
107
|
|
|
99
|
-
# [0.30.0](https://github.com/AliMD/alwatr/compare/v0.29.0...v0.30.0) (2023-03-06)
|
|
108
|
+
# [0.30.0](https://github.com/AliMD/alwatr-signal/compare/v0.29.0...v0.30.0) (2023-03-06)
|
|
100
109
|
|
|
101
110
|
### Bug Fixes
|
|
102
111
|
|
|
103
|
-
- **fsm:** every signal mather ([0dc504d](https://github.com/AliMD/alwatr/commit/0dc504dacbb1ec68f154244619d644ff8e43cc04))
|
|
104
|
-
- **fsm:** remove additional import ([231337b](https://github.com/AliMD/alwatr/commit/231337b95ee7b046fe35429f50931ddf85be291f))
|
|
105
|
-
- **fsm:** update context in transition bug ([28a21d0](https://github.com/AliMD/alwatr/commit/28a21d00d903b6189d814303c72ba6e784852f33))
|
|
112
|
+
- **fsm:** every signal mather ([0dc504d](https://github.com/AliMD/alwatr-signal/commit/0dc504dacbb1ec68f154244619d644ff8e43cc04))
|
|
113
|
+
- **fsm:** remove additional import ([231337b](https://github.com/AliMD/alwatr-signal/commit/231337b95ee7b046fe35429f50931ddf85be291f))
|
|
114
|
+
- **fsm:** update context in transition bug ([28a21d0](https://github.com/AliMD/alwatr-signal/commit/28a21d00d903b6189d814303c72ba6e784852f33))
|
|
106
115
|
|
|
107
116
|
### Features
|
|
108
117
|
|
|
109
|
-
- Alwatr Finite State Machines ([d5900b4](https://github.com/AliMD/alwatr/commit/d5900b4ee8685b120188888871405853f5a69417))
|
|
110
|
-
- **fsm:** $all and $self state ([69adf41](https://github.com/AliMD/alwatr/commit/69adf41064ca0f55497484c50e298ebc26c42dcc))
|
|
111
|
-
- **fsm:** enhance types ([3b13046](https://github.com/AliMD/alwatr/commit/3b130463a102f59c38603b0de470be5c87ee88c9))
|
|
112
|
-
- **fsm:** make simple state machine ([ff9ae1c](https://github.com/AliMD/alwatr/commit/ff9ae1ca04156e8b811899ff0f62480e1c37af72))
|
|
113
|
-
- **fsm:** new state context type with {to, from, by} ([11423e6](https://github.com/AliMD/alwatr/commit/11423e6a89159b92e82cfd1e774ad37983581090))
|
|
114
|
-
- **fsm:** rewrite with signal power ([01a1651](https://github.com/AliMD/alwatr/commit/01a1651e231a817d5eebb54cf84d51d620bfd6e8))
|
|
115
|
-
- **fsm:** share state events ([de42522](https://github.com/AliMD/alwatr/commit/de42522a97fdf6be8bee73d91a35820e2a5e6efb))
|
|
116
|
-
- **fsm:** transition with partial context set ([823377e](https://github.com/AliMD/alwatr/commit/823377e65028ea3e713f060ae678776c609c1661))
|
|
118
|
+
- Alwatr Finite State Machines ([d5900b4](https://github.com/AliMD/alwatr-signal/commit/d5900b4ee8685b120188888871405853f5a69417))
|
|
119
|
+
- **fsm:** $all and $self state ([69adf41](https://github.com/AliMD/alwatr-signal/commit/69adf41064ca0f55497484c50e298ebc26c42dcc))
|
|
120
|
+
- **fsm:** enhance types ([3b13046](https://github.com/AliMD/alwatr-signal/commit/3b130463a102f59c38603b0de470be5c87ee88c9))
|
|
121
|
+
- **fsm:** make simple state machine ([ff9ae1c](https://github.com/AliMD/alwatr-signal/commit/ff9ae1ca04156e8b811899ff0f62480e1c37af72))
|
|
122
|
+
- **fsm:** new state context type with {to, from, by} ([11423e6](https://github.com/AliMD/alwatr-signal/commit/11423e6a89159b92e82cfd1e774ad37983581090))
|
|
123
|
+
- **fsm:** rewrite with signal power ([01a1651](https://github.com/AliMD/alwatr-signal/commit/01a1651e231a817d5eebb54cf84d51d620bfd6e8))
|
|
124
|
+
- **fsm:** share state events ([de42522](https://github.com/AliMD/alwatr-signal/commit/de42522a97fdf6be8bee73d91a35820e2a5e6efb))
|
|
125
|
+
- **fsm:** transition with partial context set ([823377e](https://github.com/AliMD/alwatr-signal/commit/823377e65028ea3e713f060ae678776c609c1661))
|
package/base.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AlwatrObservable } from '@alwatr/signal/observable.js';
|
|
2
|
+
import type { ActionName, ActionRecord, StateEventDetail, StateRecord } from './type.js';
|
|
3
|
+
import type { MaybePromise } from '@alwatr/type';
|
|
4
|
+
/**
|
|
5
|
+
* Finite State Machine Base Class
|
|
6
|
+
*/
|
|
7
|
+
export declare abstract class FiniteStateMachineBase<S extends string, E extends string> extends AlwatrObservable<S> {
|
|
8
|
+
/**
|
|
9
|
+
* Current state
|
|
10
|
+
*/
|
|
11
|
+
protected get _state(): S;
|
|
12
|
+
/**
|
|
13
|
+
* States and transitions config.
|
|
14
|
+
*/
|
|
15
|
+
protected _stateRecord: StateRecord<S, E>;
|
|
16
|
+
/**
|
|
17
|
+
* Bind actions name to class methods
|
|
18
|
+
*/
|
|
19
|
+
protected _actionRecord: ActionRecord<S, E>;
|
|
20
|
+
protected _initialState: S;
|
|
21
|
+
constructor(config: {
|
|
22
|
+
name: string;
|
|
23
|
+
loggerPrefix?: string;
|
|
24
|
+
initialState: S;
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Transition condition.
|
|
28
|
+
*/
|
|
29
|
+
protected _shouldTransition(_eventDetail: StateEventDetail<S, E>): MaybePromise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Transition finite state machine instance to new state.
|
|
32
|
+
*/
|
|
33
|
+
protected _transition(event: E): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Execute all actions for current state.
|
|
36
|
+
*/
|
|
37
|
+
protected _transitioned(eventDetail: StateEventDetail<S, E>): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Execute action name if defined in _actionRecord.
|
|
40
|
+
*/
|
|
41
|
+
protected _$execAction(name: ActionName<S, E>, eventDetail: StateEventDetail<S, E>): MaybePromise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Reset machine to initial state.
|
|
44
|
+
*/
|
|
45
|
+
protected _reset(): void;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=base.d.ts.map
|
package/base.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["src/base.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,gBAAgB,EAAC,MAAM,8BAA8B,CAAC;AAE9D,OAAO,KAAK,EAAC,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAC,MAAM,WAAW,CAAC;AACvF,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,cAAc,CAAC;AAE/C;;GAEG;AACH,8BAAsB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;IAC1G;;OAEG;IACH,SAAS,KAAK,MAAM,IAAI,CAAC,CAExB;IAED;;OAEG;IACH,SAAS,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAM;IAE/C;;OAEG;IACH,SAAS,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAM;IAEjD,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC;gBAEf,MAAM,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,CAAC,CAAA;KAAC;IAO1E;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC;IAKxF;;OAEG;cACa,WAAW,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BpD;;OAEG;cACa,aAAa,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBjF;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC;IAQvG;;OAEG;IACH,SAAS,CAAC,MAAM,IAAI,IAAI;CAGzB"}
|
package/base.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import { AlwatrObservable } from '@alwatr/signal/observable.js';
|
|
3
|
+
/**
|
|
4
|
+
* Finite State Machine Base Class
|
|
5
|
+
*/
|
|
6
|
+
export class FiniteStateMachineBase extends AlwatrObservable {
|
|
7
|
+
/**
|
|
8
|
+
* Current state
|
|
9
|
+
*/
|
|
10
|
+
get _state() {
|
|
11
|
+
return this._getData();
|
|
12
|
+
}
|
|
13
|
+
constructor(config) {
|
|
14
|
+
config.loggerPrefix ?? (config.loggerPrefix = 'fsm');
|
|
15
|
+
super(config);
|
|
16
|
+
/**
|
|
17
|
+
* States and transitions config.
|
|
18
|
+
*/
|
|
19
|
+
this._stateRecord = {};
|
|
20
|
+
/**
|
|
21
|
+
* Bind actions name to class methods
|
|
22
|
+
*/
|
|
23
|
+
this._actionRecord = {};
|
|
24
|
+
this._initialState = config.initialState;
|
|
25
|
+
this._reset();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Transition condition.
|
|
29
|
+
*/
|
|
30
|
+
_shouldTransition(_eventDetail) {
|
|
31
|
+
this._logger.logMethodFull?.('_shouldTransition', _eventDetail, true);
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Transition finite state machine instance to new state.
|
|
36
|
+
*/
|
|
37
|
+
async _transition(event) {
|
|
38
|
+
const fromState = this._state;
|
|
39
|
+
const toState = this._stateRecord[fromState]?.[event] ?? this._stateRecord._all?.[event];
|
|
40
|
+
this._logger.logMethodArgs?.('_transition', { fromState, event, toState });
|
|
41
|
+
if (toState == null) {
|
|
42
|
+
this._logger.incident?.('transition', 'invalid_target_state', 'Defined target state for this event not found in state config', {
|
|
43
|
+
fromState,
|
|
44
|
+
event,
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const eventDetail = { from: fromState, event, to: toState };
|
|
49
|
+
if ((await this._shouldTransition(eventDetail)) !== true)
|
|
50
|
+
return;
|
|
51
|
+
this._notify(toState);
|
|
52
|
+
this._transitioned(eventDetail);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Execute all actions for current state.
|
|
56
|
+
*/
|
|
57
|
+
async _transitioned(eventDetail) {
|
|
58
|
+
this._logger.logMethodArgs?.('_transitioned', eventDetail);
|
|
59
|
+
await this._$execAction(`_on_${eventDetail.event}`, eventDetail);
|
|
60
|
+
if (eventDetail.from !== eventDetail.to) {
|
|
61
|
+
await this._$execAction(`_on_state_exit`, eventDetail);
|
|
62
|
+
await this._$execAction(`_on_${eventDetail.from}_exit`, eventDetail);
|
|
63
|
+
await this._$execAction(`_on_state_enter`, eventDetail);
|
|
64
|
+
await this._$execAction(`_on_${eventDetail.to}_enter`, eventDetail);
|
|
65
|
+
}
|
|
66
|
+
if (`_on_${eventDetail.from}_${eventDetail.event}` in this) {
|
|
67
|
+
this._$execAction(`_on_${eventDetail.from}_${eventDetail.event}`, eventDetail);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this._$execAction(`_on_all_${eventDetail.event}`, eventDetail);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Execute action name if defined in _actionRecord.
|
|
75
|
+
*/
|
|
76
|
+
_$execAction(name, eventDetail) {
|
|
77
|
+
const actionFn = this._actionRecord[name];
|
|
78
|
+
if (typeof actionFn === 'function') {
|
|
79
|
+
this._logger.logMethodArgs?.('_$execAction', name);
|
|
80
|
+
return this._actionRecord[name]?.call(this, eventDetail);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Reset machine to initial state.
|
|
85
|
+
*/
|
|
86
|
+
_reset() {
|
|
87
|
+
this._$data = this._initialState;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=base.js.map
|
package/base.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["src/base.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\nimport {AlwatrObservable} from '@alwatr/signal/observable.js';\n\nimport type {ActionName, ActionRecord, StateEventDetail, StateRecord} from './type.js';\nimport type {MaybePromise} from '@alwatr/type';\n\n/**\n * Finite State Machine Base Class\n */\nexport abstract class FiniteStateMachineBase<S extends string, E extends string> extends AlwatrObservable<S> {\n /**\n * Current state\n */\n protected get _state(): S {\n return this._getData()!;\n }\n\n /**\n * States and transitions config.\n */\n protected _stateRecord: StateRecord<S, E> = {};\n\n /**\n * Bind actions name to class methods\n */\n protected _actionRecord: ActionRecord<S, E> = {};\n\n protected _initialState: S;\n\n constructor(config: {name: string; loggerPrefix?: string; initialState: S}) {\n config.loggerPrefix ??= 'fsm';\n super(config);\n this._initialState = config.initialState;\n this._reset();\n }\n\n /**\n * Transition condition.\n */\n protected _shouldTransition(_eventDetail: StateEventDetail<S, E>): MaybePromise<boolean> {\n this._logger.logMethodFull?.('_shouldTransition', _eventDetail, true);\n return true;\n }\n\n /**\n * Transition finite state machine instance to new state.\n */\n protected async _transition(event: E): Promise<void> {\n const fromState = this._state;\n const toState = this._stateRecord[fromState]?.[event] ?? this._stateRecord._all?.[event];\n\n this._logger.logMethodArgs?.('_transition', {fromState, event, toState});\n\n if (toState == null) {\n this._logger.incident?.(\n 'transition',\n 'invalid_target_state',\n 'Defined target state for this event not found in state config',\n {\n fromState,\n event,\n },\n );\n return;\n }\n\n const eventDetail: StateEventDetail<S, E> = {from: fromState, event, to: toState};\n\n if ((await this._shouldTransition(eventDetail)) !== true) return;\n\n this._notify(toState);\n\n this._transitioned(eventDetail);\n }\n\n /**\n * Execute all actions for current state.\n */\n protected async _transitioned(eventDetail: StateEventDetail<S, E>): Promise<void> {\n this._logger.logMethodArgs?.('_transitioned', eventDetail);\n\n await this._$execAction(`_on_${eventDetail.event}`, eventDetail);\n\n if (eventDetail.from !== eventDetail.to) {\n await this._$execAction(`_on_state_exit`, eventDetail);\n await this._$execAction(`_on_${eventDetail.from}_exit`, eventDetail);\n await this._$execAction(`_on_state_enter`, eventDetail);\n await this._$execAction(`_on_${eventDetail.to}_enter`, eventDetail);\n }\n\n if (`_on_${eventDetail.from}_${eventDetail.event}` in this) {\n this._$execAction(`_on_${eventDetail.from}_${eventDetail.event}`, eventDetail);\n }\n else {\n this._$execAction(`_on_all_${eventDetail.event}`, eventDetail);\n }\n }\n\n /**\n * Execute action name if defined in _actionRecord.\n */\n protected _$execAction(name: ActionName<S, E>, eventDetail: StateEventDetail<S, E>): MaybePromise<void> {\n const actionFn = this._actionRecord[name];\n if (typeof actionFn === 'function') {\n this._logger.logMethodArgs?.('_$execAction', name);\n return this._actionRecord[name]?.call(this, eventDetail);\n }\n }\n\n /**\n * Reset machine to initial state.\n */\n protected _reset(): void {\n this._$data = this._initialState;\n }\n}\n"]}
|
package/fsm.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FiniteStateMachineBase } from './base.js';
|
|
2
|
+
/**
|
|
3
|
+
* Finite State Machine Base Class
|
|
4
|
+
*/
|
|
5
|
+
export declare abstract class FiniteStateMachine<S extends string, E extends string> extends FiniteStateMachineBase<S, E> {
|
|
6
|
+
/**
|
|
7
|
+
* Current state.
|
|
8
|
+
*/
|
|
9
|
+
get state(): S;
|
|
10
|
+
/**
|
|
11
|
+
* Transition finite state machine instance to new state.
|
|
12
|
+
*/
|
|
13
|
+
transition(event: E): void;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=fsm.d.ts.map
|
package/fsm.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsm.d.ts","sourceRoot":"","sources":["src/fsm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,WAAW,CAAC;AAEjD;;GAEG;AACH,8BAAsB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAE,SAAQ,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/G;;OAEG;IACH,IAAI,KAAK,IAAI,CAAC,CAEb;IAED;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;CAG3B"}
|
package/fsm.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FiniteStateMachineBase } from './base.js';
|
|
2
|
+
/**
|
|
3
|
+
* Finite State Machine Base Class
|
|
4
|
+
*/
|
|
5
|
+
export class FiniteStateMachine extends FiniteStateMachineBase {
|
|
6
|
+
/**
|
|
7
|
+
* Current state.
|
|
8
|
+
*/
|
|
9
|
+
get state() {
|
|
10
|
+
return super._state;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Transition finite state machine instance to new state.
|
|
14
|
+
*/
|
|
15
|
+
transition(event) {
|
|
16
|
+
super._transition(event);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=fsm.js.map
|
package/fsm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsm.js","sourceRoot":"","sources":["src/fsm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,WAAW,CAAC;AAEjD;;GAEG;AACH,MAAM,OAAgB,kBAAuD,SAAQ,sBAA4B;IAC/G;;OAEG;IACH,IAAI,KAAK;QACP,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,KAAQ;QACjB,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;CACF","sourcesContent":["import {FiniteStateMachineBase} from './base.js';\n\n/**\n * Finite State Machine Base Class\n */\nexport abstract class FiniteStateMachine<S extends string, E extends string> extends FiniteStateMachineBase<S, E> {\n /**\n * Current state.\n */\n get state(): S {\n return super._state;\n }\n\n /**\n * Transition finite state machine instance to new state.\n */\n transition(event: E): void {\n super._transition(event);\n }\n}\n"]}
|
package/index.d.ts
CHANGED
|
@@ -1,22 +1,4 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
*/
|
|
5
|
-
export declare const finiteStateMachineProvider: {
|
|
6
|
-
readonly defineConstructor: <TState extends string = string, TEventId extends string = string, TActionName extends string = string, TContext extends import("@alwatr/type").StringifyableRecord = import("@alwatr/type").StringifyableRecord>(id: string, config: import("./type.js").FsmConstructorConfig<TState, TEventId, TActionName, TContext>) => import("./type.js").FsmConstructorConfig<TState, TEventId, TActionName, TContext>;
|
|
7
|
-
readonly defineActions: <T extends Readonly<{
|
|
8
|
-
TState: string;
|
|
9
|
-
TEventId: string;
|
|
10
|
-
TActionName: string;
|
|
11
|
-
TContext: import("@alwatr/type").StringifyableRecord;
|
|
12
|
-
}>>(constructorId: string, actionRecord: import("./type.js").ActionRecord<T>) => void;
|
|
13
|
-
readonly defineSignals: <T_1 extends Readonly<{
|
|
14
|
-
TState: string;
|
|
15
|
-
TEventId: string;
|
|
16
|
-
TActionName: string;
|
|
17
|
-
TContext: import("@alwatr/type").StringifyableRecord;
|
|
18
|
-
}>>(constructorId: string, signalList: import("./type.js").SignalConfig<T_1>[]) => void;
|
|
19
|
-
readonly subscribe: (instanceId: string, callback: () => void, options?: Partial<import("@alwatr/signal/type.js").SubscribeOptions> | undefined) => import("@alwatr/signal").ListenerSpec;
|
|
20
|
-
};
|
|
21
|
-
export type { FsmTypeHelper, FsmConstructorConfig, FsmConsumerInterface } from './type.js';
|
|
1
|
+
export * from './base.js';
|
|
2
|
+
export * from './fsm.js';
|
|
3
|
+
export * from './type.js';
|
|
22
4
|
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC"}
|
package/index.js
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
* Finite State Machine Provider.
|
|
5
|
-
*/
|
|
6
|
-
export const finiteStateMachineProvider = {
|
|
7
|
-
defineConstructor,
|
|
8
|
-
defineActions,
|
|
9
|
-
defineSignals: defineConstructorSignals,
|
|
10
|
-
subscribe,
|
|
11
|
-
};
|
|
1
|
+
export * from './base.js';
|
|
2
|
+
export * from './fsm.js';
|
|
3
|
+
export * from './type.js';
|
|
12
4
|
//# sourceMappingURL=index.js.map
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC","sourcesContent":["export * from './base.js';\nexport * from './fsm.js';\nexport * from './type.js';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alwatr/fsm",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Managing invocations finite-state machines for lit-element written in tiny TypeScript module.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state",
|
|
@@ -26,18 +26,18 @@
|
|
|
26
26
|
},
|
|
27
27
|
"repository": {
|
|
28
28
|
"type": "git",
|
|
29
|
-
"url": "https://github.com/AliMD/alwatr",
|
|
30
|
-
"directory": "
|
|
29
|
+
"url": "https://github.com/AliMD/alwatr-signal",
|
|
30
|
+
"directory": "packages/fsm"
|
|
31
31
|
},
|
|
32
|
-
"homepage": "https://github.com/AliMD/alwatr/tree/
|
|
32
|
+
"homepage": "https://github.com/AliMD/alwatr-signal/tree/next/packages/fsm#readme",
|
|
33
33
|
"bugs": {
|
|
34
|
-
"url": "https://github.com/AliMD/alwatr/issues"
|
|
34
|
+
"url": "https://github.com/AliMD/alwatr-signal/issues"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@alwatr/logger": "^1.1.
|
|
38
|
-
"@alwatr/signal": "^
|
|
39
|
-
"@alwatr/type": "^1.1.
|
|
37
|
+
"@alwatr/logger": "^1.1.5",
|
|
38
|
+
"@alwatr/signal": "^2.0.0",
|
|
39
|
+
"@alwatr/type": "^1.1.4",
|
|
40
40
|
"tslib": "^2.6.2"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "1196deebb143a163b2a4b520ff3bb60bfd5399c4"
|
|
43
43
|
}
|
package/type.d.ts
CHANGED
|
@@ -1,107 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
signalList: SignalConfig[];
|
|
12
|
-
}
|
|
13
|
-
export interface FsmConstructorConfig<TState extends string = string, TEventId extends string = string, TActionName extends string = string, TContext extends StringifyableRecord = StringifyableRecord> extends StringifyableRecord {
|
|
14
|
-
/**
|
|
15
|
-
* Initial context.
|
|
16
|
-
*/
|
|
17
|
-
readonly context: TContext;
|
|
18
|
-
/**
|
|
19
|
-
* Initial state.
|
|
20
|
-
*/
|
|
21
|
-
readonly initial: TState;
|
|
22
|
-
/**
|
|
23
|
-
* Define state list
|
|
24
|
-
*/
|
|
25
|
-
readonly stateRecord: StateRecord<TState, TEventId, TActionName>;
|
|
26
|
-
}
|
|
27
|
-
export type StateRecord<TState extends string = string, TEventId extends string = string, TActionName extends string = string> = {
|
|
28
|
-
readonly [S in TState | '$all']: {
|
|
29
|
-
/**
|
|
30
|
-
* On state exit actions
|
|
31
|
-
*/
|
|
32
|
-
readonly exit?: SingleOrArray<TActionName>;
|
|
33
|
-
/**
|
|
34
|
-
* On state entry actions
|
|
35
|
-
*/
|
|
36
|
-
readonly entry?: SingleOrArray<TActionName>;
|
|
37
|
-
/**
|
|
38
|
-
* An object mapping eventId to state.
|
|
39
|
-
*
|
|
40
|
-
* Example:
|
|
41
|
-
*
|
|
42
|
-
* ```ts
|
|
43
|
-
* stateRecord: {
|
|
44
|
-
* on: {
|
|
45
|
-
* TIMER: {
|
|
46
|
-
* target: 'green',
|
|
47
|
-
* condition: () => car.gas > 0,
|
|
48
|
-
* actions: () => car.go(),
|
|
49
|
-
* }
|
|
50
|
-
* }
|
|
51
|
-
* }
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
readonly on: {
|
|
55
|
-
readonly [E in TEventId]?: TransitionConfig<TState, TActionName> | undefined;
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
export interface FsmState<TState extends string = string, TEventId extends string = string> extends StringifyableRecord {
|
|
60
|
-
/**
|
|
61
|
-
* Current state
|
|
62
|
-
*/
|
|
63
|
-
target: TState;
|
|
64
|
-
/**
|
|
65
|
-
* Last state
|
|
66
|
-
*/
|
|
67
|
-
from: TState;
|
|
68
|
-
/**
|
|
69
|
-
* Transition event
|
|
70
|
-
*/
|
|
71
|
-
by: TEventId | 'INIT';
|
|
72
|
-
}
|
|
73
|
-
export interface TransitionConfig<TState extends string = string, TActionName extends string = string> extends StringifyableRecord {
|
|
74
|
-
readonly target?: TState;
|
|
75
|
-
readonly condition?: TActionName;
|
|
76
|
-
readonly actions?: SingleOrArray<TActionName>;
|
|
77
|
-
}
|
|
78
|
-
export interface FsmInstance<TState extends string = string, TEventId extends string = string, TContext extends StringifyableRecord = StringifyableRecord> extends StringifyableRecord {
|
|
79
|
-
readonly constructorId: string;
|
|
80
|
-
state: FsmState<TState, TEventId>;
|
|
81
|
-
context: TContext;
|
|
82
|
-
}
|
|
83
|
-
export type ActionRecord<T extends FsmTypeHelper = FsmTypeHelper> = {
|
|
84
|
-
readonly [P in T['TActionName']]?: (finiteStateMachine: FsmConsumerInterface<T>) => MaybePromise<void> | boolean;
|
|
85
|
-
};
|
|
86
|
-
export type SignalConfig<T extends FsmTypeHelper = FsmTypeHelper> = {
|
|
87
|
-
signalId?: string;
|
|
88
|
-
/**
|
|
89
|
-
* @default `No`
|
|
90
|
-
*/
|
|
91
|
-
receivePrevious?: DebounceType;
|
|
92
|
-
} & ({
|
|
93
|
-
transition: T['TEventId'];
|
|
94
|
-
contextName?: keyof T['TContext'];
|
|
95
|
-
callback?: never;
|
|
96
|
-
} | {
|
|
97
|
-
callback: (detail: any, fsmInstance: FsmConsumerInterface<T>) => void;
|
|
98
|
-
transition?: never;
|
|
99
|
-
});
|
|
100
|
-
export type FsmTypeHelper<T extends FsmConstructorConfig = FsmConstructorConfig> = Readonly<{
|
|
101
|
-
TState: Exclude<keyof T['stateRecord'], '$all'>;
|
|
102
|
-
TEventId: keyof T['stateRecord'][FsmTypeHelper<T>['TState']]['on'];
|
|
103
|
-
TActionName: NonNullable<ArrayItems<T['stateRecord'][FsmTypeHelper<T>['TState']]['entry']>>;
|
|
104
|
-
TContext: T['context'];
|
|
105
|
-
}>;
|
|
106
|
-
export type FsmConsumerInterface<T extends FsmTypeHelper = FsmTypeHelper, TContext extends T['TContext'] = T['TContext']> = ReturnType<typeof finiteStateMachineConsumer<T, TContext>>;
|
|
1
|
+
import type { MaybePromise } from '@alwatr/type';
|
|
2
|
+
export interface StateEventDetail<S, E> {
|
|
3
|
+
from: S;
|
|
4
|
+
event: E;
|
|
5
|
+
to: S;
|
|
6
|
+
}
|
|
7
|
+
export type StateRecord<S extends string, E extends string> = Partial<Record<S | '_all', Partial<Record<E, S>>>>;
|
|
8
|
+
export type Action<S extends string, E extends string> = (eventDetail?: StateEventDetail<S, E>) => MaybePromise<void>;
|
|
9
|
+
export type ActionName<S extends string, E extends string> = `_on_${E}` | `_on_state_exit` | `_on_state_enter` | `_on_${S}_exit` | `_on_${S}_enter` | `_on_${S}_${E}` | `_on_all_${E}`;
|
|
10
|
+
export type ActionRecord<S extends string, E extends string> = Partial<Record<ActionName<S, E>, Action<S, E>>>;
|
|
107
11
|
//# sourceMappingURL=type.d.ts.map
|
package/type.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["src/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["src/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,cAAc,CAAC;AAE/C,MAAM,WAAW,gBAAgB,CAAC,CAAC,EAAE,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,CAAC,CAAC;IACT,EAAE,EAAE,CAAC,CAAC;CACP;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjH,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;AAEtH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IACrD,OAAO,CAAC,EAAE,GACV,gBAAgB,GAChB,iBAAiB,GACjB,OAAO,CAAC,OAAO,GACf,OAAO,CAAC,QAAQ,GAChB,OAAO,CAAC,IAAI,CAAC,EAAE,GACf,WAAW,CAAC,EAAE,CAAC;AAEnB,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
package/type.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.js","sourceRoot":"","sources":["src/type.ts"],"names":[],"mappings":"","sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"type.js","sourceRoot":"","sources":["src/type.ts"],"names":[],"mappings":"","sourcesContent":["import type {MaybePromise} from '@alwatr/type';\n\nexport interface StateEventDetail<S, E> {\n from: S;\n event: E;\n to: S;\n}\n\nexport type StateRecord<S extends string, E extends string> = Partial<Record<S | '_all', Partial<Record<E, S>>>>;\n\nexport type Action<S extends string, E extends string> = (eventDetail?: StateEventDetail<S, E>) => MaybePromise<void>;\n\nexport type ActionName<S extends string, E extends string> =\n | `_on_${E}`\n | `_on_state_exit`\n | `_on_state_enter`\n | `_on_${S}_exit`\n | `_on_${S}_enter`\n | `_on_${S}_${E}`\n | `_on_all_${E}`;\n\nexport type ActionRecord<S extends string, E extends string> = Partial<Record<ActionName<S, E>, Action<S, E>>>;\n"]}
|
package/core.d.ts
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { ListenerSpec } from '@alwatr/signal';
|
|
2
|
-
import { SubscribeOptions } from '@alwatr/signal/type.js';
|
|
3
|
-
import type { ActionRecord, FsmConstructor, FsmConstructorConfig, FsmConsumerInterface, FsmInstance, FsmState, SignalConfig } from './type.js';
|
|
4
|
-
import type { MaybePromise, SingleOrArray, StringifyableRecord } from '@alwatr/type';
|
|
5
|
-
export declare const defineConstructor: <TState extends string = string, TEventId extends string = string, TActionName extends string = string, TContext extends StringifyableRecord = StringifyableRecord>(id: string, config: FsmConstructorConfig<TState, TEventId, TActionName, TContext>) => FsmConstructorConfig<TState, TEventId, TActionName, TContext>;
|
|
6
|
-
/**
|
|
7
|
-
* Get finite state machine instance by id.
|
|
8
|
-
*/
|
|
9
|
-
export declare const getFsmInstance: <TState extends string = string, TEventId extends string = string, TContext extends StringifyableRecord = StringifyableRecord>(instanceId: string) => FsmInstance<TState, TEventId, TContext>;
|
|
10
|
-
/**
|
|
11
|
-
* Get finite state machine constructor by id.
|
|
12
|
-
*/
|
|
13
|
-
export declare const getFsmConstructor: (constructorId: string) => FsmConstructor;
|
|
14
|
-
/**
|
|
15
|
-
* Get current state of finite state machine instance.
|
|
16
|
-
*/
|
|
17
|
-
export declare const getState: <TState extends string = string, TEventId extends string = string>(instanceId: string) => FsmState<TState, TEventId>;
|
|
18
|
-
/**
|
|
19
|
-
* Get current context of finite state machine instance.
|
|
20
|
-
*/
|
|
21
|
-
export declare const getContext: <TContext extends StringifyableRecord = StringifyableRecord>(instanceId: string) => TContext;
|
|
22
|
-
/**
|
|
23
|
-
* Set context of finite state machine instance.
|
|
24
|
-
*/
|
|
25
|
-
export declare const setContext: <TContext extends StringifyableRecord = StringifyableRecord>(instanceId: string, context: Partial<TContext>, notify?: boolean) => void;
|
|
26
|
-
/**
|
|
27
|
-
* Transition finite state machine instance to new state.
|
|
28
|
-
*/
|
|
29
|
-
export declare const transition: <TEventId extends string = string, TContext extends StringifyableRecord = StringifyableRecord>(instanceId: string, event: TEventId, context?: Partial<TContext> | undefined) => void;
|
|
30
|
-
/**
|
|
31
|
-
* Define actions for finite state machine constructor.
|
|
32
|
-
*/
|
|
33
|
-
export declare const defineActions: <T extends Readonly<{
|
|
34
|
-
TState: string;
|
|
35
|
-
TEventId: string;
|
|
36
|
-
TActionName: string;
|
|
37
|
-
TContext: StringifyableRecord;
|
|
38
|
-
}>>(constructorId: string, actionRecord: ActionRecord<T>) => void;
|
|
39
|
-
/**
|
|
40
|
-
* Execute all actions for current state.
|
|
41
|
-
*/
|
|
42
|
-
export declare const _execAllActions: (constructor: FsmConstructor, state: FsmState, consumerInterface: FsmConsumerInterface) => void;
|
|
43
|
-
/**
|
|
44
|
-
* Execute single action.
|
|
45
|
-
*/
|
|
46
|
-
export declare const _execAction: (constructor: FsmConstructor, actionNames: SingleOrArray<string> | undefined, finiteStateMachine: FsmConsumerInterface) => boolean | MaybePromise<void>;
|
|
47
|
-
/**
|
|
48
|
-
* Initialize new finite state machine instance.
|
|
49
|
-
*/
|
|
50
|
-
export declare const initFsmInstance: (instanceId: string, constructorId: string) => void;
|
|
51
|
-
/**
|
|
52
|
-
* Subscribe to all defined signals for finite state machine instance.
|
|
53
|
-
*/
|
|
54
|
-
export declare const subscribeSignals: (instanceId: string, signalList: SignalConfig[], subscribeConstructorSignals?: boolean) => ListenerSpec[];
|
|
55
|
-
/**
|
|
56
|
-
* Define signals for finite state machine constructor.
|
|
57
|
-
*/
|
|
58
|
-
export declare const defineConstructorSignals: <T extends Readonly<{
|
|
59
|
-
TState: string;
|
|
60
|
-
TEventId: string;
|
|
61
|
-
TActionName: string;
|
|
62
|
-
TContext: StringifyableRecord;
|
|
63
|
-
}>>(constructorId: string, signalList: SignalConfig<T>[]) => void;
|
|
64
|
-
/**
|
|
65
|
-
* Define signals for finite state machine instance.
|
|
66
|
-
*/
|
|
67
|
-
export declare const defineInstanceSignals: <T extends Readonly<{
|
|
68
|
-
TState: string;
|
|
69
|
-
TEventId: string;
|
|
70
|
-
TActionName: string;
|
|
71
|
-
TContext: StringifyableRecord;
|
|
72
|
-
}>>(instanceId: string, signalList: SignalConfig<T>[], subscribeConstructorSignals?: boolean) => ListenerSpec[];
|
|
73
|
-
/**
|
|
74
|
-
* Render helper for use finite state machine instance in UI.
|
|
75
|
-
*
|
|
76
|
-
* Example:
|
|
77
|
-
*
|
|
78
|
-
* ```ts
|
|
79
|
-
* render('myFsm', {
|
|
80
|
-
* state1: () => html`<div>State 1 Render...</div>`,
|
|
81
|
-
* state2: () => html`<div>State 2 Render...</div>`,
|
|
82
|
-
* state3: 'state1',
|
|
83
|
-
* });
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
export declare const render: <TState extends string = string>(instanceId: string, states: { [P in TState]: TState | (() => unknown); }, thisArg?: unknown) => unknown;
|
|
87
|
-
/**
|
|
88
|
-
* Subscribe to finite state machine instance state changes.
|
|
89
|
-
*/
|
|
90
|
-
export declare const subscribe: (instanceId: string, callback: () => void, options?: Partial<SubscribeOptions>) => ListenerSpec;
|
|
91
|
-
/**
|
|
92
|
-
* Destroy finite state machine instance object to clear memory.
|
|
93
|
-
*/
|
|
94
|
-
export declare const destroy: (instanceId: string) => void;
|
|
95
|
-
/**
|
|
96
|
-
* Reset finite state machine instance to initial state and context.
|
|
97
|
-
*/
|
|
98
|
-
export declare const reset: (instanceId: string) => void;
|
|
99
|
-
/**
|
|
100
|
-
* Finite state machine instance consumer.
|
|
101
|
-
* Lookup current finite state machine instance or initialize new one and return consumer object .
|
|
102
|
-
*/
|
|
103
|
-
export declare const finiteStateMachineConsumer: <T extends Readonly<{
|
|
104
|
-
TState: string;
|
|
105
|
-
TEventId: string;
|
|
106
|
-
TActionName: string;
|
|
107
|
-
TContext: StringifyableRecord;
|
|
108
|
-
}>, TContext extends T["TContext"] = T["TContext"]>(instanceId: string, makeFromConstructor?: string) => {
|
|
109
|
-
/**
|
|
110
|
-
* Finite state machine instance id.
|
|
111
|
-
*/
|
|
112
|
-
readonly id: string;
|
|
113
|
-
/**
|
|
114
|
-
* Finite state machine constructor id.
|
|
115
|
-
*/
|
|
116
|
-
readonly constructorId: string;
|
|
117
|
-
/**
|
|
118
|
-
* Render helper for use finite state machine instance in UI.
|
|
119
|
-
*/
|
|
120
|
-
readonly render: (states: { [P in T["TState"]]: (() => unknown) | T["TState"]; }, thisArg?: unknown) => unknown;
|
|
121
|
-
/**
|
|
122
|
-
* Subscribe to finite state machine instance state changes.
|
|
123
|
-
*/
|
|
124
|
-
readonly subscribe: (callback: () => void, options?: Partial<SubscribeOptions> | undefined) => ListenerSpec;
|
|
125
|
-
/**
|
|
126
|
-
* Unsubscribe from finite state machine instance state changes.
|
|
127
|
-
*/
|
|
128
|
-
readonly unsubscribe: (listener: ListenerSpec) => void;
|
|
129
|
-
/**
|
|
130
|
-
* Get current state of finite state machine instance.
|
|
131
|
-
*/
|
|
132
|
-
readonly getState: () => FsmState<T["TState"], T["TEventId"]>;
|
|
133
|
-
/**
|
|
134
|
-
* Get current context of finite state machine instance.
|
|
135
|
-
*/
|
|
136
|
-
readonly getContext: () => TContext;
|
|
137
|
-
/**
|
|
138
|
-
* Set context of finite state machine instance.
|
|
139
|
-
*/
|
|
140
|
-
readonly setContext: (context: Partial<TContext>, notify?: boolean | undefined) => void;
|
|
141
|
-
/**
|
|
142
|
-
* Transition finite state machine instance to new state.
|
|
143
|
-
*/
|
|
144
|
-
readonly transition: (event: T["TEventId"], context?: Partial<TContext> | undefined) => void;
|
|
145
|
-
/**
|
|
146
|
-
* Define signals for finite state machine instance.
|
|
147
|
-
*/
|
|
148
|
-
readonly defineSignals: (signalList: SignalConfig<T>[], subscribeConstructorSignals?: boolean | undefined) => ListenerSpec[];
|
|
149
|
-
/**
|
|
150
|
-
* Reset finite state machine instance to initial state and context.
|
|
151
|
-
*/
|
|
152
|
-
readonly reset: () => void;
|
|
153
|
-
/**
|
|
154
|
-
* Destroy finite state machine instance object to clear memory.
|
|
155
|
-
*/
|
|
156
|
-
readonly destroy: () => void;
|
|
157
|
-
};
|
|
158
|
-
//# sourceMappingURL=core.d.ts.map
|
package/core.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["src/core.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAmC,MAAM,gBAAgB,CAAC;AAE9E,OAAO,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AAExD,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,QAAQ,EAER,YAAY,EACb,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAC,YAAY,EAAkB,aAAa,EAAE,mBAAmB,EAAC,MAAM,cAAc,CAAC;AAcnG,eAAO,MAAM,iBAAiB,0KAMtB,MAAM,yIAYb,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,6IAKX,MAAM,4CAMrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,kBAAmB,MAAM,KAAG,cAKzD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,QAAQ,iFACP,MAAM,+BAInB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,2EACT,MAAM,aAInB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,2EACT,MAAM,uCAET,OAAO,KACf,IAWF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,6GAIP,MAAM,+DAGjB,IAgDJ,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;mBAA4C,MAAM,oCAAkC,IAO7G,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,gBACX,cAAc,SACpB,QAAQ,qBACI,oBAAoB,KACxC,IA0BF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,gBACP,cAAc,eACd,cAAc,MAAM,CAAC,GAAG,SAAS,sBAC1B,oBAAoB,KACzC,OAAO,GAAG,aAAa,IAAI,CA4B7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,eAAgB,MAAM,iBAAiB,MAAM,KAAG,IAgB3E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,eACb,MAAM,cACN,YAAY,EAAE,4CAE3B,YAAY,EAmCd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;mBACpB,MAAM,oCAEpB,IAIF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;gBACpB,MAAM,2EAGjB,YAAY,EAGd,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,+CACL,MAAM,2CACa,OAAO,gBAC7B,OAAO,KACf,OAcF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,eACN,MAAM,YACR,MAAM,IAAI,YACV,QAAQ,gBAAgB,CAAC,KACpC,YAGF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,eAAgB,MAAM,KAAG,IAG5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,KAAK,eAAgB,MAAM,KAAG,IAK1C,CAAC;AAEF;;;GAGG;AAEH,eAAO,MAAM,0BAA0B;;;;;gEACzB,MAAM,wBACI,MAAM;IAc1B;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;2DAjF0B,OAAO;IAoFpC;;OAEG;yCA/Da,IAAI;IAkEpB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAGN,CAAC"}
|
package/core.js
DELETED
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
import { createLogger, globalAlwatr } from '@alwatr/logger';
|
|
2
|
-
import { contextProvider, contextConsumer } from '@alwatr/signal';
|
|
3
|
-
import { destroySignal, unsubscribe } from '@alwatr/signal/core.js';
|
|
4
|
-
globalAlwatr.registeredList.push({
|
|
5
|
-
name: '@alwatr/fsm',
|
|
6
|
-
version: _ALWATR_VERSION_,
|
|
7
|
-
});
|
|
8
|
-
const logger = createLogger(`alwatr/fsm`);
|
|
9
|
-
/**
|
|
10
|
-
* Finite state machine constructor storage.
|
|
11
|
-
*/
|
|
12
|
-
const fsmConstructorStorage = {};
|
|
13
|
-
export const defineConstructor = (id, config) => {
|
|
14
|
-
logger.logMethodArgs?.('defineConstructor', { id, config });
|
|
15
|
-
if (fsmConstructorStorage[id] != null)
|
|
16
|
-
throw new Error('fsm_exist', { cause: { id } });
|
|
17
|
-
fsmConstructorStorage[id] = {
|
|
18
|
-
id,
|
|
19
|
-
config,
|
|
20
|
-
actionRecord: {},
|
|
21
|
-
signalList: [],
|
|
22
|
-
};
|
|
23
|
-
return config;
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Get finite state machine instance by id.
|
|
27
|
-
*/
|
|
28
|
-
export const getFsmInstance = (instanceId) => {
|
|
29
|
-
logger.logMethodArgs?.('_getFsmInstance', instanceId);
|
|
30
|
-
const fsmInstance = contextConsumer.getValue(instanceId);
|
|
31
|
-
if (fsmInstance == null)
|
|
32
|
-
throw new Error('fsm_undefined', { cause: { instanceId } });
|
|
33
|
-
return fsmInstance;
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* Get finite state machine constructor by id.
|
|
37
|
-
*/
|
|
38
|
-
export const getFsmConstructor = (constructorId) => {
|
|
39
|
-
logger.logMethodArgs?.('_getFsmConstructor', constructorId);
|
|
40
|
-
const fsmConstructor = fsmConstructorStorage[constructorId];
|
|
41
|
-
if (fsmConstructor == null)
|
|
42
|
-
throw new Error('fsm_undefined', { cause: { constructorId: constructorId } });
|
|
43
|
-
return fsmConstructor;
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* Get current state of finite state machine instance.
|
|
47
|
-
*/
|
|
48
|
-
export const getState = (instanceId) => {
|
|
49
|
-
logger.logMethodArgs?.('getState', instanceId);
|
|
50
|
-
return getFsmInstance(instanceId).state;
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* Get current context of finite state machine instance.
|
|
54
|
-
*/
|
|
55
|
-
export const getContext = (instanceId) => {
|
|
56
|
-
logger.logMethodArgs?.('getContext', instanceId);
|
|
57
|
-
return getFsmInstance(instanceId).context;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Set context of finite state machine instance.
|
|
61
|
-
*/
|
|
62
|
-
export const setContext = (instanceId, context, notify) => {
|
|
63
|
-
logger.logMethodArgs?.('setContext', { instanceId, context });
|
|
64
|
-
const fsmInstance = getFsmInstance(instanceId);
|
|
65
|
-
fsmInstance.context = {
|
|
66
|
-
...fsmInstance.context,
|
|
67
|
-
...context,
|
|
68
|
-
};
|
|
69
|
-
if (notify) {
|
|
70
|
-
contextProvider.setValue(instanceId, fsmInstance, { debounce: 'Timeout' });
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Transition finite state machine instance to new state.
|
|
75
|
-
*/
|
|
76
|
-
export const transition = (instanceId, event, context) => {
|
|
77
|
-
const fsmInstance = getFsmInstance(instanceId);
|
|
78
|
-
const fsmConstructor = getFsmConstructor(fsmInstance.constructorId);
|
|
79
|
-
const fromState = fsmInstance.state.target;
|
|
80
|
-
const stateRecord = fsmConstructor.config.stateRecord;
|
|
81
|
-
const transitionConfig = stateRecord[fromState]?.on[event] ?? stateRecord.$all.on[event];
|
|
82
|
-
logger.logMethodArgs?.('transition', { instanceId, fromState, event, context, target: transitionConfig?.target });
|
|
83
|
-
if (context !== undefined) {
|
|
84
|
-
fsmInstance.context = {
|
|
85
|
-
...fsmInstance.context,
|
|
86
|
-
...context,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
if (transitionConfig == null) {
|
|
90
|
-
logger.incident?.('transition', 'invalid_target_state', 'Defined target state for this event not found in state config', {
|
|
91
|
-
fromState,
|
|
92
|
-
event,
|
|
93
|
-
events: {
|
|
94
|
-
...stateRecord.$all?.on,
|
|
95
|
-
...stateRecord[fromState]?.on,
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
const consumerInterface = finiteStateMachineConsumer(instanceId);
|
|
101
|
-
if (transitionConfig.condition) {
|
|
102
|
-
if (_execAction(fsmConstructor, transitionConfig.condition, consumerInterface) === false)
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
fsmInstance.state = {
|
|
106
|
-
target: transitionConfig.target ?? fromState,
|
|
107
|
-
from: fromState,
|
|
108
|
-
by: event,
|
|
109
|
-
};
|
|
110
|
-
contextProvider.setValue(instanceId, fsmInstance, { debounce: 'Timeout' });
|
|
111
|
-
_execAllActions(fsmConstructor, fsmInstance.state, consumerInterface);
|
|
112
|
-
};
|
|
113
|
-
/**
|
|
114
|
-
* Define actions for finite state machine constructor.
|
|
115
|
-
*/
|
|
116
|
-
export const defineActions = (constructorId, actionRecord) => {
|
|
117
|
-
logger.logMethodArgs?.('defineActions', { constructorId, actionRecord });
|
|
118
|
-
const fmsConstructor = getFsmConstructor(constructorId);
|
|
119
|
-
fmsConstructor.actionRecord = {
|
|
120
|
-
...fmsConstructor.actionRecord,
|
|
121
|
-
...actionRecord,
|
|
122
|
-
};
|
|
123
|
-
};
|
|
124
|
-
/**
|
|
125
|
-
* Execute all actions for current state.
|
|
126
|
-
*/
|
|
127
|
-
export const _execAllActions = (constructor, state, consumerInterface) => {
|
|
128
|
-
logger.logMethodArgs?.('_execAllActions', consumerInterface.id);
|
|
129
|
-
const stateRecord = constructor.config.stateRecord;
|
|
130
|
-
if (state.by === 'INIT') {
|
|
131
|
-
_execAction(constructor, stateRecord.$all.entry, consumerInterface);
|
|
132
|
-
_execAction(constructor, stateRecord[state.target]?.entry, consumerInterface);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
// else
|
|
136
|
-
if (state.from !== state.target) {
|
|
137
|
-
_execAction(constructor, stateRecord.$all.exit, consumerInterface);
|
|
138
|
-
_execAction(constructor, stateRecord[state.from]?.exit, consumerInterface);
|
|
139
|
-
_execAction(constructor, stateRecord.$all.entry, consumerInterface);
|
|
140
|
-
_execAction(constructor, stateRecord[state.target]?.entry, consumerInterface);
|
|
141
|
-
}
|
|
142
|
-
_execAction(constructor, stateRecord[state.from]?.on[state.by] != null
|
|
143
|
-
? stateRecord[state.from].on[state.by]?.actions
|
|
144
|
-
: stateRecord.$all.on[state.by]?.actions, consumerInterface);
|
|
145
|
-
};
|
|
146
|
-
/**
|
|
147
|
-
* Execute single action.
|
|
148
|
-
*/
|
|
149
|
-
export const _execAction = (constructor, actionNames, finiteStateMachine) => {
|
|
150
|
-
if (actionNames == null)
|
|
151
|
-
return;
|
|
152
|
-
logger.logMethodArgs?.('execAction', { constructorId: constructor.id, actionNames });
|
|
153
|
-
if (Array.isArray(actionNames)) {
|
|
154
|
-
return actionNames
|
|
155
|
-
.map((actionName) => _execAction(constructor, actionName, finiteStateMachine))
|
|
156
|
-
.every((r) => r === true);
|
|
157
|
-
}
|
|
158
|
-
try {
|
|
159
|
-
const actionFn = constructor.actionRecord[actionNames];
|
|
160
|
-
if (actionFn == null) {
|
|
161
|
-
return logger.error('execAction', 'action_not_found', {
|
|
162
|
-
actionNames,
|
|
163
|
-
constructorId: constructor.id,
|
|
164
|
-
instanceId: finiteStateMachine.id,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
return actionFn(finiteStateMachine);
|
|
168
|
-
}
|
|
169
|
-
catch (error) {
|
|
170
|
-
return logger.error('execAction', 'action_error', error, {
|
|
171
|
-
actionNames,
|
|
172
|
-
constructorId: constructor.id,
|
|
173
|
-
instanceId: finiteStateMachine.id,
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
/**
|
|
178
|
-
* Initialize new finite state machine instance.
|
|
179
|
-
*/
|
|
180
|
-
export const initFsmInstance = (instanceId, constructorId) => {
|
|
181
|
-
logger.logMethodArgs?.('initializeMachine', { constructorId, instanceId });
|
|
182
|
-
const constructor = getFsmConstructor(constructorId);
|
|
183
|
-
const { initial, context } = constructor.config;
|
|
184
|
-
const newInstance = {
|
|
185
|
-
constructorId,
|
|
186
|
-
state: {
|
|
187
|
-
target: initial,
|
|
188
|
-
from: initial,
|
|
189
|
-
by: 'INIT',
|
|
190
|
-
},
|
|
191
|
-
context,
|
|
192
|
-
};
|
|
193
|
-
contextProvider.setValue(instanceId, newInstance, { debounce: 'NextCycle' });
|
|
194
|
-
_execAllActions(constructor, newInstance.state, finiteStateMachineConsumer(instanceId));
|
|
195
|
-
};
|
|
196
|
-
/**
|
|
197
|
-
* Subscribe to all defined signals for finite state machine instance.
|
|
198
|
-
*/
|
|
199
|
-
export const subscribeSignals = (instanceId, signalList, subscribeConstructorSignals = true) => {
|
|
200
|
-
logger.logMethodArgs?.('subscribeSignals', { instanceId, signalList });
|
|
201
|
-
const listenerList = [];
|
|
202
|
-
if (subscribeConstructorSignals) {
|
|
203
|
-
signalList = signalList.concat(getFsmConstructor(getFsmInstance(instanceId).constructorId).signalList);
|
|
204
|
-
}
|
|
205
|
-
for (const signalConfig of signalList) {
|
|
206
|
-
signalConfig.signalId ?? (signalConfig.signalId = instanceId);
|
|
207
|
-
listenerList.push(contextConsumer.subscribe(signalConfig.signalId, (signalDetail) => {
|
|
208
|
-
logger.logMethodArgs?.('execSignalCallback', { instanceId, signalId: signalConfig.signalId, signalDetail });
|
|
209
|
-
if (signalConfig.callback) {
|
|
210
|
-
signalConfig.callback(signalDetail, finiteStateMachineConsumer(instanceId));
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
// prettier-ignore
|
|
214
|
-
transition(instanceId, signalConfig.transition, signalConfig.contextName == null ? undefined : {
|
|
215
|
-
[signalConfig.contextName]: signalDetail,
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
}, { receivePrevious: signalConfig.receivePrevious ?? 'No' }));
|
|
219
|
-
}
|
|
220
|
-
return listenerList;
|
|
221
|
-
};
|
|
222
|
-
/**
|
|
223
|
-
* Define signals for finite state machine constructor.
|
|
224
|
-
*/
|
|
225
|
-
export const defineConstructorSignals = (constructorId, signalList) => {
|
|
226
|
-
logger.logMethodArgs?.('defineSignals', { constructorId, signalList: signalList });
|
|
227
|
-
const fsmConstructor = getFsmConstructor(constructorId);
|
|
228
|
-
fsmConstructor.signalList = fsmConstructor.signalList.concat(signalList);
|
|
229
|
-
};
|
|
230
|
-
/**
|
|
231
|
-
* Define signals for finite state machine instance.
|
|
232
|
-
*/
|
|
233
|
-
export const defineInstanceSignals = (instanceId, signalList, subscribeConstructorSignals = true) => {
|
|
234
|
-
logger.logMethodArgs?.('defineSignals', { instanceId, signals: signalList });
|
|
235
|
-
return subscribeSignals(instanceId, signalList, subscribeConstructorSignals);
|
|
236
|
-
};
|
|
237
|
-
/**
|
|
238
|
-
* Render helper for use finite state machine instance in UI.
|
|
239
|
-
*
|
|
240
|
-
* Example:
|
|
241
|
-
*
|
|
242
|
-
* ```ts
|
|
243
|
-
* render('myFsm', {
|
|
244
|
-
* state1: () => html`<div>State 1 Render...</div>`,
|
|
245
|
-
* state2: () => html`<div>State 2 Render...</div>`,
|
|
246
|
-
* state3: 'state1',
|
|
247
|
-
* });
|
|
248
|
-
* ```
|
|
249
|
-
*/
|
|
250
|
-
export const render = (instanceId, states, thisArg = null) => {
|
|
251
|
-
const state = getFsmInstance(instanceId).state;
|
|
252
|
-
logger.logMethodArgs?.('render', { instanceId, state: state.target });
|
|
253
|
-
let renderFn = states[state.target];
|
|
254
|
-
if (typeof renderFn === 'string') {
|
|
255
|
-
renderFn = states[renderFn];
|
|
256
|
-
}
|
|
257
|
-
if (typeof renderFn === 'function') {
|
|
258
|
-
return renderFn.call(thisArg);
|
|
259
|
-
}
|
|
260
|
-
return;
|
|
261
|
-
};
|
|
262
|
-
/**
|
|
263
|
-
* Subscribe to finite state machine instance state changes.
|
|
264
|
-
*/
|
|
265
|
-
export const subscribe = (instanceId, callback, options) => {
|
|
266
|
-
logger.logMethodArgs?.('subscribe', instanceId);
|
|
267
|
-
return contextConsumer.subscribe(instanceId, callback, options);
|
|
268
|
-
};
|
|
269
|
-
/**
|
|
270
|
-
* Destroy finite state machine instance object to clear memory.
|
|
271
|
-
*/
|
|
272
|
-
export const destroy = (instanceId) => {
|
|
273
|
-
logger.logMethodArgs?.('destroy', instanceId);
|
|
274
|
-
destroySignal(instanceId);
|
|
275
|
-
};
|
|
276
|
-
/**
|
|
277
|
-
* Reset finite state machine instance to initial state and context.
|
|
278
|
-
*/
|
|
279
|
-
export const reset = (instanceId) => {
|
|
280
|
-
logger.logMethodArgs?.('reset', instanceId);
|
|
281
|
-
const constructorId = getFsmInstance(instanceId).constructorId;
|
|
282
|
-
// contextProvider.expire(instanceId);
|
|
283
|
-
initFsmInstance(instanceId, constructorId);
|
|
284
|
-
};
|
|
285
|
-
/**
|
|
286
|
-
* Finite state machine instance consumer.
|
|
287
|
-
* Lookup current finite state machine instance or initialize new one and return consumer object .
|
|
288
|
-
*/
|
|
289
|
-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
290
|
-
export const finiteStateMachineConsumer = (instanceId, makeFromConstructor) => {
|
|
291
|
-
logger.logMethodArgs?.('stateMachineLookup', instanceId);
|
|
292
|
-
const machineInstance = contextConsumer.getValue(instanceId);
|
|
293
|
-
if (machineInstance == null) {
|
|
294
|
-
// instance not initialized.
|
|
295
|
-
if (makeFromConstructor == null) {
|
|
296
|
-
throw new Error('fsm_undefined', { cause: { instanceId } });
|
|
297
|
-
}
|
|
298
|
-
initFsmInstance(instanceId, makeFromConstructor);
|
|
299
|
-
}
|
|
300
|
-
return {
|
|
301
|
-
/**
|
|
302
|
-
* Finite state machine instance id.
|
|
303
|
-
*/
|
|
304
|
-
id: instanceId,
|
|
305
|
-
/**
|
|
306
|
-
* Finite state machine constructor id.
|
|
307
|
-
*/
|
|
308
|
-
constructorId: machineInstance?.constructorId ?? makeFromConstructor,
|
|
309
|
-
/**
|
|
310
|
-
* Render helper for use finite state machine instance in UI.
|
|
311
|
-
*/
|
|
312
|
-
render: render.bind(null, instanceId),
|
|
313
|
-
/**
|
|
314
|
-
* Subscribe to finite state machine instance state changes.
|
|
315
|
-
*/
|
|
316
|
-
subscribe: subscribe.bind(null, instanceId),
|
|
317
|
-
/**
|
|
318
|
-
* Unsubscribe from finite state machine instance state changes.
|
|
319
|
-
*/
|
|
320
|
-
unsubscribe: unsubscribe,
|
|
321
|
-
/**
|
|
322
|
-
* Get current state of finite state machine instance.
|
|
323
|
-
*/
|
|
324
|
-
getState: getState.bind(null, instanceId),
|
|
325
|
-
/**
|
|
326
|
-
* Get current context of finite state machine instance.
|
|
327
|
-
*/
|
|
328
|
-
getContext: getContext.bind(null, instanceId),
|
|
329
|
-
/**
|
|
330
|
-
* Set context of finite state machine instance.
|
|
331
|
-
*/
|
|
332
|
-
setContext: setContext.bind(null, instanceId),
|
|
333
|
-
/**
|
|
334
|
-
* Transition finite state machine instance to new state.
|
|
335
|
-
*/
|
|
336
|
-
transition: transition.bind(null, instanceId),
|
|
337
|
-
/**
|
|
338
|
-
* Define signals for finite state machine instance.
|
|
339
|
-
*/
|
|
340
|
-
defineSignals: defineInstanceSignals.bind(null, instanceId),
|
|
341
|
-
/**
|
|
342
|
-
* Reset finite state machine instance to initial state and context.
|
|
343
|
-
*/
|
|
344
|
-
reset: reset.bind(null, instanceId),
|
|
345
|
-
/**
|
|
346
|
-
* Destroy finite state machine instance object to clear memory.
|
|
347
|
-
*/
|
|
348
|
-
destroy: destroy.bind(null, instanceId),
|
|
349
|
-
};
|
|
350
|
-
};
|
|
351
|
-
//# sourceMappingURL=core.js.map
|
package/core.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["src/core.ts"],"names":[],"mappings":"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","sourcesContent":["import {createLogger, globalAlwatr} from '@alwatr/logger';\nimport {ListenerSpec, contextProvider, contextConsumer} from '@alwatr/signal';\nimport {destroySignal, unsubscribe} from '@alwatr/signal/core.js';\nimport {SubscribeOptions} from '@alwatr/signal/type.js';\n\nimport type {\n ActionRecord,\n FsmConstructor,\n FsmConstructorConfig,\n FsmConsumerInterface,\n FsmInstance,\n FsmState,\n FsmTypeHelper,\n SignalConfig,\n} from './type.js';\nimport type {MaybePromise, OmitFirstParam, SingleOrArray, StringifyableRecord} from '@alwatr/type';\n\nglobalAlwatr.registeredList.push({\n name: '@alwatr/fsm',\n version: _ALWATR_VERSION_,\n});\n\nconst logger = createLogger(`alwatr/fsm`);\n\n/**\n * Finite state machine constructor storage.\n */\nconst fsmConstructorStorage: Record<string, FsmConstructor | undefined> = {};\n\nexport const defineConstructor = <\n TState extends string = string,\n TEventId extends string = string,\n TActionName extends string = string,\n TContext extends StringifyableRecord = StringifyableRecord\n>(\n id: string,\n config: FsmConstructorConfig<TState, TEventId, TActionName, TContext>,\n ): FsmConstructorConfig<TState, TEventId, TActionName, TContext> => {\n logger.logMethodArgs?.('defineConstructor', {id, config});\n if (fsmConstructorStorage[id] != null) throw new Error('fsm_exist', {cause: {id}});\n fsmConstructorStorage[id] = {\n id,\n config,\n actionRecord: {},\n signalList: [],\n };\n return config;\n};\n\n/**\n * Get finite state machine instance by id.\n */\nexport const getFsmInstance = <\n TState extends string = string,\n TEventId extends string = string,\n TContext extends StringifyableRecord = StringifyableRecord\n>(\n instanceId: string,\n ): FsmInstance<TState, TEventId, TContext> => {\n logger.logMethodArgs?.('_getFsmInstance', instanceId);\n const fsmInstance = contextConsumer.getValue<FsmInstance<TState, TEventId, TContext>>(instanceId);\n if (fsmInstance == null) throw new Error('fsm_undefined', {cause: {instanceId}});\n return fsmInstance;\n};\n\n/**\n * Get finite state machine constructor by id.\n */\nexport const getFsmConstructor = (constructorId: string): FsmConstructor => {\n logger.logMethodArgs?.('_getFsmConstructor', constructorId);\n const fsmConstructor = fsmConstructorStorage[constructorId];\n if (fsmConstructor == null) throw new Error('fsm_undefined', {cause: {constructorId: constructorId}});\n return fsmConstructor;\n};\n\n/**\n * Get current state of finite state machine instance.\n */\nexport const getState = <TState extends string = string, TEventId extends string = string>(\n instanceId: string,\n): FsmState<TState, TEventId> => {\n logger.logMethodArgs?.('getState', instanceId);\n return getFsmInstance<TState, TEventId>(instanceId).state;\n};\n\n/**\n * Get current context of finite state machine instance.\n */\nexport const getContext = <TContext extends StringifyableRecord = StringifyableRecord>(\n instanceId: string,\n): TContext => {\n logger.logMethodArgs?.('getContext', instanceId);\n return getFsmInstance<string, string, TContext>(instanceId).context;\n};\n\n/**\n * Set context of finite state machine instance.\n */\nexport const setContext = <TContext extends StringifyableRecord = StringifyableRecord>(\n instanceId: string,\n context: Partial<TContext>,\n notify?: boolean,\n): void => {\n logger.logMethodArgs?.('setContext', {instanceId, context});\n const fsmInstance = getFsmInstance(instanceId);\n fsmInstance.context = {\n ...fsmInstance.context,\n ...context,\n };\n\n if (notify) {\n contextProvider.setValue(instanceId, fsmInstance, {debounce: 'Timeout'});\n }\n};\n\n/**\n * Transition finite state machine instance to new state.\n */\nexport const transition = <\n TEventId extends string = string,\n TContext extends StringifyableRecord = StringifyableRecord\n>(\n instanceId: string,\n event: TEventId,\n context?: Partial<TContext>,\n ): void => {\n const fsmInstance = getFsmInstance(instanceId);\n const fsmConstructor = getFsmConstructor(fsmInstance.constructorId);\n const fromState = fsmInstance.state.target;\n const stateRecord = fsmConstructor.config.stateRecord;\n const transitionConfig = stateRecord[fromState]?.on[event] ?? stateRecord.$all.on[event];\n\n logger.logMethodArgs?.('transition', {instanceId, fromState, event, context, target: transitionConfig?.target});\n\n if (context !== undefined) {\n fsmInstance.context = {\n ...fsmInstance.context,\n ...context,\n };\n }\n\n if (transitionConfig == null) {\n logger.incident?.(\n 'transition',\n 'invalid_target_state',\n 'Defined target state for this event not found in state config',\n {\n fromState,\n event,\n events: {\n ...stateRecord.$all?.on,\n ...stateRecord[fromState]?.on,\n },\n },\n );\n return;\n }\n\n const consumerInterface = finiteStateMachineConsumer(instanceId);\n\n if (transitionConfig.condition) {\n if (_execAction(fsmConstructor, transitionConfig.condition, consumerInterface) === false) return;\n }\n\n fsmInstance.state = {\n target: transitionConfig.target ?? fromState,\n from: fromState,\n by: event,\n };\n\n contextProvider.setValue(instanceId, fsmInstance, {debounce: 'Timeout'});\n\n _execAllActions(fsmConstructor, fsmInstance.state, consumerInterface);\n};\n\n/**\n * Define actions for finite state machine constructor.\n */\nexport const defineActions = <T extends FsmTypeHelper>(constructorId: string, actionRecord: ActionRecord<T>): void => {\n logger.logMethodArgs?.('defineActions', {constructorId, actionRecord});\n const fmsConstructor = getFsmConstructor(constructorId);\n fmsConstructor.actionRecord = {\n ...fmsConstructor.actionRecord,\n ...actionRecord,\n };\n};\n\n/**\n * Execute all actions for current state.\n */\nexport const _execAllActions = (\n constructor: FsmConstructor,\n state: FsmState,\n consumerInterface: FsmConsumerInterface,\n): void => {\n logger.logMethodArgs?.('_execAllActions', consumerInterface.id);\n\n const stateRecord = constructor.config.stateRecord;\n\n if (state.by === 'INIT') {\n _execAction(constructor, stateRecord.$all.entry, consumerInterface);\n _execAction(constructor, stateRecord[state.target]?.entry, consumerInterface);\n return;\n }\n\n // else\n if (state.from !== state.target) {\n _execAction(constructor, stateRecord.$all.exit, consumerInterface);\n _execAction(constructor, stateRecord[state.from]?.exit, consumerInterface);\n _execAction(constructor, stateRecord.$all.entry, consumerInterface);\n _execAction(constructor, stateRecord[state.target]?.entry, consumerInterface);\n }\n\n _execAction(\n constructor,\n stateRecord[state.from]?.on[state.by] != null\n ? stateRecord[state.from].on[state.by]?.actions\n : stateRecord.$all.on[state.by]?.actions,\n consumerInterface,\n );\n};\n\n/**\n * Execute single action.\n */\nexport const _execAction = (\n constructor: FsmConstructor,\n actionNames: SingleOrArray<string> | undefined,\n finiteStateMachine: FsmConsumerInterface,\n): boolean | MaybePromise<void> => {\n if (actionNames == null) return;\n logger.logMethodArgs?.('execAction', {constructorId: constructor.id, actionNames});\n\n if (Array.isArray(actionNames)) {\n return actionNames\n .map((actionName) => _execAction(constructor, actionName, finiteStateMachine))\n .every((r) => r === true);\n }\n\n try {\n const actionFn = constructor.actionRecord[actionNames];\n if (actionFn == null) {\n return logger.error('execAction', 'action_not_found', {\n actionNames,\n constructorId: constructor.id,\n instanceId: finiteStateMachine.id,\n });\n }\n return actionFn(finiteStateMachine);\n }\n catch (error) {\n return logger.error('execAction', 'action_error', error, {\n actionNames,\n constructorId: constructor.id,\n instanceId: finiteStateMachine.id,\n });\n }\n};\n\n/**\n * Initialize new finite state machine instance.\n */\nexport const initFsmInstance = (instanceId: string, constructorId: string): void => {\n logger.logMethodArgs?.('initializeMachine', {constructorId, instanceId});\n const constructor = getFsmConstructor(constructorId);\n const {initial, context} = constructor.config;\n const newInstance: FsmInstance = {\n constructorId,\n state: {\n target: initial,\n from: initial,\n by: 'INIT',\n },\n context,\n };\n contextProvider.setValue<FsmInstance>(instanceId, newInstance, {debounce: 'NextCycle'});\n\n _execAllActions(constructor, newInstance.state, finiteStateMachineConsumer(instanceId));\n};\n\n/**\n * Subscribe to all defined signals for finite state machine instance.\n */\nexport const subscribeSignals = (\n instanceId: string,\n signalList: SignalConfig[],\n subscribeConstructorSignals = true,\n): ListenerSpec[] => {\n logger.logMethodArgs?.('subscribeSignals', {instanceId, signalList});\n const listenerList: ListenerSpec[] = [];\n\n if (subscribeConstructorSignals) {\n signalList = signalList.concat(getFsmConstructor(getFsmInstance(instanceId).constructorId).signalList);\n }\n\n for (const signalConfig of signalList) {\n signalConfig.signalId ??= instanceId;\n listenerList.push(\n contextConsumer.subscribe(\n signalConfig.signalId,\n (signalDetail: StringifyableRecord): void => {\n logger.logMethodArgs?.('execSignalCallback', {instanceId, signalId: signalConfig.signalId, signalDetail});\n if (signalConfig.callback) {\n signalConfig.callback(signalDetail, finiteStateMachineConsumer(instanceId));\n }\n else {\n // prettier-ignore\n transition(\n instanceId,\n signalConfig.transition,\n signalConfig.contextName == null ? undefined : {\n [signalConfig.contextName]: signalDetail,\n },\n );\n }\n },\n {receivePrevious: signalConfig.receivePrevious ?? 'No'},\n ),\n );\n }\n\n return listenerList;\n};\n\n/**\n * Define signals for finite state machine constructor.\n */\nexport const defineConstructorSignals = <T extends FsmTypeHelper>(\n constructorId: string,\n signalList: SignalConfig<T>[],\n): void => {\n logger.logMethodArgs?.('defineSignals', {constructorId, signalList: signalList});\n const fsmConstructor = getFsmConstructor(constructorId);\n fsmConstructor.signalList = fsmConstructor.signalList.concat(signalList as SignalConfig[]);\n};\n\n/**\n * Define signals for finite state machine instance.\n */\nexport const defineInstanceSignals = <T extends FsmTypeHelper>(\n instanceId: string,\n signalList: SignalConfig<T>[],\n subscribeConstructorSignals = true,\n): ListenerSpec[] => {\n logger.logMethodArgs?.('defineSignals', {instanceId, signals: signalList});\n return subscribeSignals(instanceId, signalList as SignalConfig[], subscribeConstructorSignals);\n};\n\n/**\n * Render helper for use finite state machine instance in UI.\n *\n * Example:\n *\n * ```ts\n * render('myFsm', {\n * state1: () => html`<div>State 1 Render...</div>`,\n * state2: () => html`<div>State 2 Render...</div>`,\n * state3: 'state1',\n * });\n * ```\n */\nexport const render = <TState extends string = string>(\n instanceId: string,\n states: {[P in TState]: (() => unknown) | TState},\n thisArg: unknown = null,\n): unknown => {\n const state = getFsmInstance(instanceId).state;\n logger.logMethodArgs?.('render', {instanceId, state: state.target});\n let renderFn = states[state.target as TState];\n\n if (typeof renderFn === 'string') {\n renderFn = states[renderFn as TState];\n }\n\n if (typeof renderFn === 'function') {\n return renderFn.call(thisArg);\n }\n\n return;\n};\n\n/**\n * Subscribe to finite state machine instance state changes.\n */\nexport const subscribe = (\n instanceId: string,\n callback: () => void,\n options?: Partial<SubscribeOptions>,\n): ListenerSpec => {\n logger.logMethodArgs?.('subscribe', instanceId);\n return contextConsumer.subscribe(instanceId, callback, options);\n};\n\n/**\n * Destroy finite state machine instance object to clear memory.\n */\nexport const destroy = (instanceId: string): void => {\n logger.logMethodArgs?.('destroy', instanceId);\n destroySignal(instanceId);\n};\n\n/**\n * Reset finite state machine instance to initial state and context.\n */\nexport const reset = (instanceId: string): void => {\n logger.logMethodArgs?.('reset', instanceId);\n const constructorId = getFsmInstance(instanceId).constructorId;\n // contextProvider.expire(instanceId);\n initFsmInstance(instanceId, constructorId);\n};\n\n/**\n * Finite state machine instance consumer.\n * Lookup current finite state machine instance or initialize new one and return consumer object .\n */\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type\nexport const finiteStateMachineConsumer = <T extends FsmTypeHelper, TContext extends T['TContext'] = T['TContext']>(\n instanceId: string,\n makeFromConstructor?: string,\n) => {\n logger.logMethodArgs?.('stateMachineLookup', instanceId);\n\n const machineInstance = contextConsumer.getValue<FsmInstance>(instanceId);\n if (machineInstance == null) {\n // instance not initialized.\n if (makeFromConstructor == null) {\n throw new Error('fsm_undefined', {cause: {instanceId}});\n }\n initFsmInstance(instanceId, makeFromConstructor);\n }\n\n return {\n /**\n * Finite state machine instance id.\n */\n id: instanceId,\n\n /**\n * Finite state machine constructor id.\n */\n constructorId: machineInstance?.constructorId as string ?? makeFromConstructor,\n\n /**\n * Render helper for use finite state machine instance in UI.\n */\n render: render.bind(null, instanceId) as OmitFirstParam<typeof render<T['TState']>>,\n\n /**\n * Subscribe to finite state machine instance state changes.\n */\n subscribe: subscribe.bind(null, instanceId) as OmitFirstParam<typeof subscribe>,\n\n /**\n * Unsubscribe from finite state machine instance state changes.\n */\n unsubscribe: unsubscribe,\n\n /**\n * Get current state of finite state machine instance.\n */\n getState: getState.bind(null, instanceId) as OmitFirstParam<typeof getState<T['TState'], T['TEventId']>>,\n\n /**\n * Get current context of finite state machine instance.\n */\n getContext: getContext.bind(null, instanceId) as OmitFirstParam<typeof getContext<TContext>>,\n\n /**\n * Set context of finite state machine instance.\n */\n setContext: setContext.bind(null, instanceId) as OmitFirstParam<typeof setContext<TContext>>,\n\n /**\n * Transition finite state machine instance to new state.\n */\n transition: transition.bind(null, instanceId) as OmitFirstParam<typeof transition<T['TEventId'], TContext>>,\n\n /**\n * Define signals for finite state machine instance.\n */\n defineSignals: defineInstanceSignals.bind(null, instanceId) as OmitFirstParam<typeof defineInstanceSignals<T>>,\n\n /**\n * Reset finite state machine instance to initial state and context.\n */\n reset: reset.bind(null, instanceId) as OmitFirstParam<typeof reset>,\n\n /**\n * Destroy finite state machine instance object to clear memory.\n */\n destroy: destroy.bind(null, instanceId) as OmitFirstParam<typeof destroy>,\n } as const;\n};\n"]}
|