@peter.naydenov/fsm 4.0.1 → 5.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 +90 -0
- package/LICENSE +21 -0
- package/Migration.guide.md +86 -0
- package/README.md +96 -173
- package/README_v.4.x.x.md +491 -0
- package/blueprint.md +22 -0
- package/coverage/lcov-report/index.html +1 -1
- package/coverage/lcov-report/src/index.html +1 -1
- package/coverage/lcov-report/src/index.js.html +1 -1
- package/coverage/lcov-report/src/methods/_getChain.js.html +1 -1
- package/coverage/lcov-report/src/methods/_onUpdateTask.js.html +1 -1
- package/coverage/lcov-report/src/methods/_setTransitions.js.html +1 -1
- package/coverage/lcov-report/src/methods/_transit.js.html +1 -1
- package/coverage/lcov-report/src/methods/_triggerCacheUpdate.js.html +1 -1
- package/coverage/lcov-report/src/methods/_updateStep.js.html +1 -1
- package/coverage/lcov-report/src/methods/_warn.js.html +1 -1
- package/coverage/lcov-report/src/methods/exportState.js.html +1 -1
- package/coverage/lcov-report/src/methods/getState.js.html +1 -1
- package/coverage/lcov-report/src/methods/ignoreCacheUpdates.js.html +1 -1
- package/coverage/lcov-report/src/methods/importState.js.html +1 -1
- package/coverage/lcov-report/src/methods/index.html +1 -1
- package/coverage/lcov-report/src/methods/index.js.html +1 -1
- package/coverage/lcov-report/src/methods/off.js.html +1 -1
- package/coverage/lcov-report/src/methods/on.js.html +1 -1
- package/coverage/lcov-report/src/methods/reset.js.html +1 -1
- package/coverage/lcov-report/src/methods/setDependencies.js.html +1 -1
- package/coverage/lcov-report/src/methods/update.js.html +1 -1
- package/coverage/tmp/coverage-51040-1691437648869-0.json +1 -0
- package/package.json +8 -7
- package/src/main.js +75 -0
- package/src/methods/_getChain.js +3 -2
- package/src/methods/_onUpdateTask.js +1 -1
- package/src/methods/_setTransitions.js +3 -3
- package/src/methods/_transit.js +7 -4
- package/src/methods/_triggerCacheUpdate.js +2 -0
- package/src/methods/_updateStateData.js +43 -0
- package/src/methods/_updateStep.js +10 -13
- package/src/methods/_warn.js +1 -1
- package/src/methods/exportState.js +5 -8
- package/src/methods/extractList.js +26 -0
- package/src/methods/getDependencies.js +10 -0
- package/src/methods/importState.js +3 -1
- package/src/methods/index.js +23 -15
- package/src/methods/reset.js +3 -2
- package/src/methods/setDependencies.js +1 -1
- package/src/methods/update.js +14 -4
- package/src/queryStateUpdate.js +38 -0
- package/coverage/tmp/coverage-29775-1668580484020-0.json +0 -1
- package/src/index.js +0 -41
package/Changelog.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
## Release History
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### 5.0.0 ( 2023-09-16 )
|
|
6
|
+
- [x] Machine description `table` was renamed to `behavior`;
|
|
7
|
+
- [x] All default dependencies are available on top level: Fsm.dependencies;
|
|
8
|
+
- [x] stateData is a dt-object(uses dt-toolbox library);
|
|
9
|
+
- [x] Transition functions have different arrangement of arguments;
|
|
10
|
+
- [x] Transition functions can receive multiple data arguments(single is still the preference);
|
|
11
|
+
- [x] Transition functions can update only defined stateData fields. Not defined data-segments or properties will be ignored;
|
|
12
|
+
- [x] Method `exportState` returns an object with two properties: `state` and `stateData`. `state` is a string. `stateData` is a DT-model. Method `importState` expect exact same object as argument;
|
|
13
|
+
- [x] Method `importState` will filter the imported stateData to only predefined fields;
|
|
14
|
+
- [x] Transion result.command was removed permanently from the code. Was depricated in version 4;
|
|
15
|
+
- [x] Internal fsm data is hidden. Only public methods are available;
|
|
16
|
+
- [x] Changes in stateData can be provided as standard javascript object, DT-model or dt-object. Automatic detection is implemented;
|
|
17
|
+
- [x] Method `fsm.extractList` will return a list of requested stateData properties;
|
|
18
|
+
- [x] Method `extractList` is available as argument in transition functions.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### 4.0.1 ( 2022-11-16)
|
|
26
|
+
- [x] Walk was removed. Generates a lot of problems with objects in stateData(HTMLElement, Date, URL). StateData is using a shallow copy. Developer should take care of immutability himself;
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### 4.0.0 (2022-11-15)
|
|
32
|
+
- [x] The library become a ES module;
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### 3.0.0 (2022-10-14)
|
|
37
|
+
- [x] Dependency "@peter.naydenov/walk" was upgraded to version 3.0.0;
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### 2.2.4 ( 2022-05-27 )
|
|
42
|
+
- [x] New dependency was added - walk ("@peter.naydenov/walk");
|
|
43
|
+
- [x] "Walk" is loaded by default in fsm dependency object;
|
|
44
|
+
- [x] "Ask-for-promise" is loaded by default in fsm dependency object;
|
|
45
|
+
- [x] Deep copy for stateData on each update with "walk" library;
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### 2.2.3 ( 2021-04-02 )
|
|
50
|
+
- [x] Fix: Duplicated update callback if logic contain a chainAction;
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
### 2.2.2 ( 2021-03-26 )
|
|
55
|
+
- [x] Internal code refactoring;
|
|
56
|
+
- [ ] Bug: Duplicated update callback if logic contain a chainAction;
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### 2.2.0 (2019-01-20)
|
|
61
|
+
- [x] Fix: Cached transitions are starting before callback functions for already executed transitions;
|
|
62
|
+
- [x] New method 'ignoreCachedUpdates()'. Ignore all cached updates;
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
### 2.1.0 (2019-01-19)
|
|
67
|
+
- [x] Export fsm state as an object - externalState;
|
|
68
|
+
- [x] Import externalState;
|
|
69
|
+
- [x] Lock updates during update process execution;
|
|
70
|
+
- [x] Prevent simultaneous updates;
|
|
71
|
+
- [x] Cache new updates during update process execution;
|
|
72
|
+
- [x] Execute cached updates in a row;
|
|
73
|
+
- [ ] Error: Cached transitions are starting before callback functions for already executed transitions;
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### 2.0.0 (2018-12-01)
|
|
78
|
+
- [x] Transition function could contain asynchronous code;
|
|
79
|
+
- [x] Chain-actions in **transaction conditions** (Optional);
|
|
80
|
+
- [x] Chain-actions are possible on **positive** and *negative* transition-end;
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
### 1.0.0 (2018-11-21)
|
|
85
|
+
- [x] FSM;
|
|
86
|
+
- [x] Set FSM external dependencies;
|
|
87
|
+
- [x] Chain-actions by using `command` in transition response object;
|
|
88
|
+
- [x] Internal state flags and values with stateData;
|
|
89
|
+
|
|
90
|
+
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 Peter Naydenov
|
|
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.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
## Migration Guides
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## Migration from v.4.x.x to v.5.x.x.
|
|
5
|
+
|
|
6
|
+
### FSM Description
|
|
7
|
+
- FSM description property 'table' was renamed to `behavior`;
|
|
8
|
+
- Data fields for stateData should be in fsm machine definition. Missing keys will be ignored;
|
|
9
|
+
|
|
10
|
+
### Transition functions
|
|
11
|
+
- Transition functions have different set and arrangment of arguments;
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// ver. 4 ->
|
|
15
|
+
function transitionFunction ( task, dependencies, stateData, data ) {
|
|
16
|
+
// ...code here
|
|
17
|
+
return task.done(transitionResult);
|
|
18
|
+
}
|
|
19
|
+
// ver. 5 ->
|
|
20
|
+
// stateData is not directly available. Use the function extractList to get the data you need;
|
|
21
|
+
// look at the example below:
|
|
22
|
+
function transitionFunction ( {task, state, dependencies, extractList }, data ) {
|
|
23
|
+
// ...code here
|
|
24
|
+
const [ top, something, else ] = extractList ([ 'a', 'b', 'c' ]);
|
|
25
|
+
// get 'a' from stateData and write in variable 'top';
|
|
26
|
+
// get 'b' from stateData and write in variable 'something';
|
|
27
|
+
// get 'c' from stateData and write in variable 'else';
|
|
28
|
+
const transitionResult = {
|
|
29
|
+
success : true
|
|
30
|
+
, stateData : {
|
|
31
|
+
// ...setup stateData changes here
|
|
32
|
+
}
|
|
33
|
+
, result :
|
|
34
|
+
};
|
|
35
|
+
task.done(transitionResult);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
- Transition functions can update only defined stateData fields. Not defined data-segments or properties will be ignored;
|
|
40
|
+
```js
|
|
41
|
+
const machine = {
|
|
42
|
+
behavior : [
|
|
43
|
+
// transition condition rows here..
|
|
44
|
+
]
|
|
45
|
+
stateData : {
|
|
46
|
+
a : 1 // <- this is the only allowed field in stateData;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const lib = {
|
|
51
|
+
trans ({task}) { // transition function
|
|
52
|
+
stateData = { a : 2, b : 3, c : 4 }; // <- only 'a' is defined in machine.stateData;
|
|
53
|
+
task.done({ success : true, stateData }) // 'b' and 'c' will be ignored;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
- If you don't know what is defined in stateData, just request a extractList without any arguments;
|
|
58
|
+
```
|
|
59
|
+
function trans ({task, extractList}) {
|
|
60
|
+
const stateDataCopy = extractList(); // <- will return state fields from stateData wrapped in object
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
- Fill stateData with primitive values and objects that are JSON compatible!
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Migration from v.1 to v.2
|
|
67
|
+
Project was started with simplest posible implementation. I like the approach and want to extend it. Reasons:
|
|
68
|
+
- Some of my transition function contain asynchronous events;
|
|
69
|
+
- Describe chain of actions inside the transition condition records;
|
|
70
|
+
- Chain of action on positive and negative transition end;
|
|
71
|
+
|
|
72
|
+
So... about changes:
|
|
73
|
+
### Transition complete
|
|
74
|
+
- **Version 1**: Transition function should return **transitionResult** object.
|
|
75
|
+
- **Version 2**: Transition function receives as first param **task**. Task is askForPromise object. Transition is complete on `task.done(transitionResult)`.
|
|
76
|
+
- **Changes**: Find return statement and convert it to task.done:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
// ver. 1 ->
|
|
80
|
+
...
|
|
81
|
+
return { success : true }
|
|
82
|
+
// ver. 2 ->
|
|
83
|
+
...
|
|
84
|
+
task.done ({ success : true })
|
|
85
|
+
|
|
86
|
+
```
|
package/README.md
CHANGED
|
@@ -1,23 +1,47 @@
|
|
|
1
1
|
# FSM (@peter.naydenov/fsm)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
## What's new in version 5.x.x
|
|
7
|
+
- For fast upgrade, checkout the [Migration Guide](https://github.com/PeterNaydenov/fsm/blob/master/Migration.guide.md)
|
|
8
|
+
- List of [all changes are available in Changelog file](https://github.com/PeterNaydenov/fsm/blob/master/Changelog.md)
|
|
9
|
+
- Documentation is updated to reflect the changes in version 5.x.x;
|
|
10
|
+
|
|
11
|
+
## Description
|
|
12
|
+
Finite state machine(FSM) is an abstract machine that can be in exactly one of a finite number of **states** at any given time. The FSM can change from one state to another in response to some external inputs(**actions**). The change from state to another is called a **transition**.
|
|
13
|
+
An FSM definition includes:
|
|
14
|
+
|
|
15
|
+
|
|
4
16
|
```js
|
|
5
|
-
const
|
|
17
|
+
const fsmDefinition = {
|
|
6
18
|
init : 'none' // initial fsm state
|
|
7
|
-
,
|
|
8
|
-
// [ fromState, action , nextState, transitionFx ]
|
|
19
|
+
, behavior : [
|
|
20
|
+
// [ fromState, action , nextState, transitionFx, chaining ]
|
|
9
21
|
[ 'none' , 'activate', 'active' , 'switchON' ] // transition condition
|
|
10
22
|
, [ 'active' , 'stop' , 'none' , 'switchOFF' ] // transition condition
|
|
11
23
|
]
|
|
24
|
+
, stateData : {
|
|
25
|
+
// ... all stateData flags are here
|
|
26
|
+
}
|
|
27
|
+
}
|
|
12
28
|
}
|
|
13
29
|
```
|
|
14
|
-
- **init**: string. Initial state
|
|
15
|
-
- **
|
|
30
|
+
- **init**: string. Initial state of the FSM;
|
|
31
|
+
- **stateData**: Container for all stateData required by the FSM.
|
|
32
|
+
- **behavior**: array of transition conditions. Describe relation among fsm state, action and transition;
|
|
16
33
|
- **transitionCondition**: Array [fromState action nextState transitionFx];
|
|
17
34
|
- **fromState**: string. State as starting point for transition;
|
|
18
35
|
- **action**: string. External input signal. Transition could happen only when fromState and action are described in transitionCondition record;
|
|
19
|
-
- **nextState**: string. The FSM state if transition
|
|
36
|
+
- **nextState**: string. The next FSM state if transition become successful;
|
|
20
37
|
- **transitionFx**: string. The function name that will be executed on 'state/action' conditions. Transition should return **transitionResult** object where parameter "**success**" will represent transition success. Result of transition will be evaluated by FSM. Positive response will change actual state to 'nextState' from transitionCondition record. Negative result will keep actual state;
|
|
38
|
+
- **chaining**(optional): Array [ positive, negative ]. Optional element of `transition condition`. It's a mechanism to trigger next action based on the result of the transition. If transition result is positive, FSM will trigger action from `positive` position. If transition result is negative, FSM will trigger action from `negative` position. If only one position will use chaining, set the other as 'false'.
|
|
39
|
+
```js
|
|
40
|
+
// ... transition conditions
|
|
41
|
+
, [ 'ready', 'activate', 'active', 'switchOFF', [ false, 'generator' ] ]
|
|
42
|
+
// Chaining will trigger 'generator' action on negative transition result and will do nothing on positive result.
|
|
43
|
+
// ... transition conditions
|
|
44
|
+
```
|
|
21
45
|
|
|
22
46
|
**Transitions** are functions and they are provided to FSM as functional library - javascript object with functions.
|
|
23
47
|
```js
|
|
@@ -32,13 +56,13 @@ const transitionLibrary = {
|
|
|
32
56
|
```
|
|
33
57
|
|
|
34
58
|
It's simple and clean way to represent system behaviour but practice shows that is not enough. This implementation was extended to cover some aditional program needs like:
|
|
35
|
-
- Transition function could contain asynchronous code
|
|
36
|
-
- Chain-actions in **transaction conditions**
|
|
37
|
-
- Chain-actions are possible on **positive** and *negative* transition-end
|
|
38
|
-
- Export fsm state as an object: externalState
|
|
39
|
-
- Import externalState
|
|
40
|
-
- Prevent simultaneous updates
|
|
41
|
-
-
|
|
59
|
+
- Transition function could contain asynchronous code;
|
|
60
|
+
- Chain-actions in **transaction conditions**(Optional);
|
|
61
|
+
- Chain-actions are possible on **positive** and *negative* transition-end;
|
|
62
|
+
- Export fsm state as an object: externalState;
|
|
63
|
+
- Import externalState;
|
|
64
|
+
- Prevent simultaneous updates;
|
|
65
|
+
- Fsm-updates cache mechanism and execution in a row;
|
|
42
66
|
|
|
43
67
|
|
|
44
68
|
|
|
@@ -65,24 +89,24 @@ If your project is commonJS, use a dynamic `import` function or use version v.3.
|
|
|
65
89
|
|
|
66
90
|
|
|
67
91
|
## Fsm Description
|
|
68
|
-
Fsm description is an object that define fsm business logic. Every fsm description should contain **init** and **
|
|
92
|
+
Fsm description is an object that define fsm business logic. Every fsm description should contain **init** and **behavior** properties.:
|
|
69
93
|
```js
|
|
70
94
|
const machine = {
|
|
71
95
|
init : 'stopped'
|
|
72
|
-
,
|
|
96
|
+
, behavior: [
|
|
73
97
|
// [ state , action , nextState, functionName, chainAction(optional) ]
|
|
74
|
-
[ 'stopped', 'activate', 'active', 'fnActivate' ]
|
|
75
|
-
, [ '
|
|
98
|
+
[ 'stopped', 'activate', 'active', 'fnActivate' ] // transition condition
|
|
99
|
+
, [ 'active' , 'stop' , 'stoped', 'fnStop' ]
|
|
76
100
|
]
|
|
77
101
|
, stateData : { greeting: 'hi' }
|
|
78
|
-
/** Parameter 'stateData' is
|
|
79
|
-
*
|
|
80
|
-
* stateData
|
|
102
|
+
/** Parameter 'stateData' is not a required parameter. It's a data storage space.
|
|
103
|
+
* Storaged data is available in every transition function by using a function 'extractList'.
|
|
104
|
+
* Only a predefined state-data-names can be saved in 'stateData'
|
|
81
105
|
* /
|
|
82
106
|
}
|
|
83
107
|
```
|
|
84
108
|
|
|
85
|
-
Property '**init**' is the initial state of the system. Property '**
|
|
109
|
+
Property '**init**' is the initial state of the system. Property '**behavior**' describes how system reacts. Every row(transition condition) contains 5 elements:
|
|
86
110
|
1. Current active state;
|
|
87
111
|
2. Action;
|
|
88
112
|
3. Next state;
|
|
@@ -93,7 +117,7 @@ Property '**init**' is the initial state of the system. Property '**table**' des
|
|
|
93
117
|
[ 'stopped', 'activate', 'active', 'fnActivate' ]
|
|
94
118
|
// Read this transition condition like:
|
|
95
119
|
/**
|
|
96
|
-
* When state is 'stopped' and
|
|
120
|
+
* When state is 'stopped' and action 'activate' comes, transition 'fnActivate' will be executed. On success state will become 'active'. No chain-actions are defined.
|
|
97
121
|
*/
|
|
98
122
|
```
|
|
99
123
|
|
|
@@ -117,19 +141,20 @@ Object that will contain all transition functions:
|
|
|
117
141
|
|
|
118
142
|
## Fsm Transition Function
|
|
119
143
|
|
|
120
|
-
Fsm transition function is a function, member of transition library. Transition functions is kind of middleware. Every function receives
|
|
144
|
+
Fsm transition function is a function, member of transition library. Transition functions is kind of middleware. Every function receives this arguments:
|
|
121
145
|
```js
|
|
122
146
|
const lib = {
|
|
123
|
-
fnActivate ( task, dependencies,
|
|
147
|
+
fnActivate ( {task, state, dependencies, extractList}, data ) {
|
|
124
148
|
// function code is here...
|
|
125
149
|
task.done ( end ) // end is a transitionResult {}
|
|
126
150
|
}
|
|
127
151
|
}
|
|
128
152
|
```
|
|
129
153
|
- task - askForPromise object; [AskForPromise documentation](https://github.com/PeterNaydenov/ask-for-promise). Represents asynchronous transition execution. Finish by providing to task object, the transition result object. `task.done( transitionResult )`;
|
|
154
|
+
- state - string. Current state of the FSM;
|
|
130
155
|
- dependencies - object. Contain all external dependencies. Set fsm dependencies by fsm.setDependencies();
|
|
131
|
-
-
|
|
132
|
-
-
|
|
156
|
+
- extractList - function. Extract data from FSM stateData;
|
|
157
|
+
- data - any(Prefered: object). External data provided from fsm.update( action, **data**);
|
|
133
158
|
|
|
134
159
|
Execution of transition function will end on `task.done(end)` where **end** is an **transitionResult** object.
|
|
135
160
|
|
|
@@ -145,7 +170,6 @@ Only one of the params in this object is required:
|
|
|
145
170
|
success : true // Required. Boolean. Transition success;
|
|
146
171
|
, response : {} // Optional. Object. update answer response;
|
|
147
172
|
, stateData : {} // Optional. Object. 'stateData' if there is stateData changes;
|
|
148
|
-
, command : null // Optional. String|null|undefined. Next action if chaining is required (depricated). Use "chainActions" in table instead;
|
|
149
173
|
}
|
|
150
174
|
```
|
|
151
175
|
|
|
@@ -155,17 +179,19 @@ Only one of the params in this object is required:
|
|
|
155
179
|
|
|
156
180
|
```js
|
|
157
181
|
setDependencies : 'Insert all external dependencies'
|
|
158
|
-
,
|
|
182
|
+
, getDependencies : 'Returns all external dependencies'
|
|
159
183
|
, update : 'Trigger an action'
|
|
160
|
-
, exportState : 'Export state and stateData as a single object (externalState)'
|
|
161
184
|
, importState : 'Import externalState object.'
|
|
185
|
+
, exportState : 'Export state and stateData as a single object (externalState)'
|
|
162
186
|
, reset : 'Revert state and stateData to initial values described during initialization'
|
|
163
187
|
, ignoreCachedUpdates : 'Ignore all cached updates'
|
|
188
|
+
, getState : 'Returns actual state'
|
|
189
|
+
, extractList : 'Extract list of state segments or properties'
|
|
164
190
|
```
|
|
165
191
|
|
|
166
192
|
|
|
167
193
|
### fsm.setDependencies ()
|
|
168
|
-
Set dependencies for FSM. Dependency object will be provided to every transition function. With **dependency injection** code will stay testable.
|
|
194
|
+
Set dependencies for FSM. Dependency object will be provided to every transition function. With **dependency injection** code will stay testable. Method could be called multiple times. All dependencies will be merged in one object.
|
|
169
195
|
|
|
170
196
|
```js
|
|
171
197
|
const
|
|
@@ -179,31 +205,58 @@ Set dependencies for FSM. Dependency object will be provided to every transition
|
|
|
179
205
|
|
|
180
206
|
fsm.setDependencies ( deps )
|
|
181
207
|
```
|
|
208
|
+
- deps: object. Object with external dependencies;
|
|
182
209
|
- **Method returns**: void;
|
|
183
210
|
|
|
184
211
|
|
|
185
212
|
|
|
186
|
-
### fsm.
|
|
187
|
-
|
|
213
|
+
### fsm.getDependencies ()
|
|
214
|
+
Returns all external dependencies.
|
|
188
215
|
|
|
189
216
|
```js
|
|
190
|
-
|
|
217
|
+
const
|
|
218
|
+
moment = require ( 'moment' )
|
|
219
|
+
, fsm = new Fsm ()
|
|
220
|
+
, deps = {
|
|
221
|
+
scrollTo : window.scrollTo
|
|
222
|
+
, moment
|
|
223
|
+
}
|
|
224
|
+
;
|
|
225
|
+
|
|
226
|
+
fsm.setDependencies ( deps )
|
|
227
|
+
const allDeps = fsm.getDependencies ()
|
|
191
228
|
```
|
|
192
|
-
- **Method returns**: string. Current FSM state;
|
|
193
229
|
|
|
194
230
|
|
|
195
231
|
|
|
196
232
|
### fsm.update ()
|
|
197
233
|
Provide actions to FSM. If conditions 'state/action' exist in description table, FSM will react.
|
|
234
|
+
- If action name does not exist in behavior table, FSM will ignore the action;
|
|
235
|
+
- If action name exist in behavior table but current state is different, FSM will ignore the action;
|
|
236
|
+
- If transition function is not provided, FSM will ignore the action;
|
|
237
|
+
|
|
198
238
|
```js
|
|
199
|
-
fsm.update ( action, altData)
|
|
239
|
+
fsm.update ( action, altData )
|
|
200
240
|
.then ( r => {
|
|
201
241
|
// ...do something with the response
|
|
202
242
|
})
|
|
203
243
|
```
|
|
204
|
-
- **action**(required): string. The action.
|
|
244
|
+
- **action**(required): string. The action name.
|
|
205
245
|
- **altData**(optional): any. Additional data provided to the transition;
|
|
206
|
-
- **Method returns**: Promise
|
|
246
|
+
- **Method returns**: Promise<any>. Returned value is equal to transitionResult.response;
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
### fsm.getState ()
|
|
251
|
+
Will return current current FSM state.
|
|
252
|
+
|
|
253
|
+
```js
|
|
254
|
+
let currentState = fsm.getState ()
|
|
255
|
+
```
|
|
256
|
+
- **Method returns**: string. Current FSM state;
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
207
260
|
|
|
208
261
|
|
|
209
262
|
|
|
@@ -311,13 +364,14 @@ const
|
|
|
311
364
|
}
|
|
312
365
|
, machine = {
|
|
313
366
|
init : 'none'
|
|
314
|
-
,
|
|
367
|
+
, behavior : [
|
|
315
368
|
[ 'none' , 'start' , 'active' , 'switchON', [ false, 'generator'] ]
|
|
316
369
|
, [ 'none' , 'generator' , 'altSrc' , 'altOn' ]
|
|
317
370
|
, [ 'active' , 'stop' , 'none' , 'switchOFF' ]
|
|
318
371
|
, [ 'altSrc' , 'stop' , 'none' , 'switchOFF' ]
|
|
319
372
|
, [ 'altSrc' , 'electricity' , 'active', 'primarySource' ]
|
|
320
373
|
]
|
|
374
|
+
, stateData : {}
|
|
321
375
|
}
|
|
322
376
|
;
|
|
323
377
|
const fsm = new Fsm ( machine, lib );
|
|
@@ -332,141 +386,10 @@ fsm.update ( 'activate' )
|
|
|
332
386
|
|
|
333
387
|
|
|
334
388
|
|
|
389
|
+
## External Links
|
|
335
390
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
- Some of my transition function contain asynchronous events;
|
|
339
|
-
- Describe chain of actions inside the transition condition records;
|
|
340
|
-
- Chain of action on positive and negative transition end;
|
|
341
|
-
|
|
342
|
-
So... about changes:
|
|
343
|
-
### Transition complete
|
|
344
|
-
- **Version 1**: Transition function should return **transitionResult** object.
|
|
345
|
-
- **Version 2**: Transition function receives as first param **task**. Task is askForPromise object. Transition is complete on `task.done(transitionResult)`.
|
|
346
|
-
- **Changes**: Find return statement and convert it to task.done:
|
|
347
|
-
|
|
348
|
-
```js
|
|
349
|
-
// ver. 1 ->
|
|
350
|
-
...
|
|
351
|
-
return { success : true }
|
|
352
|
-
// ver. 2 ->
|
|
353
|
-
...
|
|
354
|
-
task.done ({ success : true })
|
|
355
|
-
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
### Transition params
|
|
361
|
-
|
|
362
|
-
```js
|
|
363
|
-
// ver. 1 ->
|
|
364
|
-
transition ( dependencies, stateData, dt )
|
|
365
|
-
|
|
366
|
-
// ver. 2 ->
|
|
367
|
-
transition ( task, dependencies, stateData, dt )
|
|
368
|
-
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
- **Change**: Open transition library and add 'task' argument to all transitioin functions.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
### Description table
|
|
376
|
-
- **Version 1**: Transition condition in description table:
|
|
377
|
-
```js
|
|
378
|
-
[ 'state', 'action', 'nextState', 'transitionFx' ]
|
|
379
|
-
```
|
|
380
|
-
All fields are string and are required.
|
|
381
|
-
|
|
382
|
-
- **Version 2**: Fields in description table record:
|
|
383
|
-
```js
|
|
384
|
-
[ 'state', 'action', 'nextState', 'transitionFx', 'chainActions' ]
|
|
385
|
-
// chainAction is array [ nextAction, nextAction ]
|
|
386
|
-
// If we need chaining only on positive/negative result of transition we can use "false"
|
|
387
|
-
// Example:
|
|
388
|
-
// We need chain transition only if transition failed:
|
|
389
|
-
// [ false, nextAction ]
|
|
390
|
-
// This chainAction will trigger nextAction only if transition failed.
|
|
391
|
-
|
|
392
|
-
```
|
|
393
|
-
ChainActions is an array with two values. First value represents next action on success transition.
|
|
394
|
-
Second on failed transition. ChainAction is optional.
|
|
395
|
-
|
|
396
|
-
- **Changes**: As ChainActions is an optional parameter, no changes needed.
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
### Chaining
|
|
401
|
-
- Version 1:
|
|
402
|
-
TransitionResult should contain property "command", that will link to next transition.
|
|
403
|
-
- Version 2:
|
|
404
|
-
TransitionResult with property 'command' still works. Chaining in description-table is more powerfull and will overwrite transitionResult's "command" property.
|
|
405
|
-
- Changes: No changes needed but is much better to describe chains in description table instead in transition functions. Keep all logic flows on one place for easy reading and manipulating.
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
## Release History
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
### 4.0.1 ( 2022-11-16)
|
|
415
|
-
- [x] Walk was removed. Generates a lot of problems with objects in stateData(HTMLElement, Date, URL). StateData is using a shallow copy. Developer should take care of immutability himself;
|
|
416
|
-
|
|
417
|
-
### 4.0.0 (2022-11-15)
|
|
418
|
-
- [x] The library become a ES module;
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
### 3.0.0 (2022-10-14)
|
|
423
|
-
- [x] Dependency "@peter.naydenov/walk" was upgraded to version 3.0.0;
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
### 2.2.4 ( 2022-05-27 )
|
|
428
|
-
- [x] New dependency was added - walk ("@peter.naydenov/walk");
|
|
429
|
-
- [x] "Walk" is loaded by default in fsm dependency object;
|
|
430
|
-
- [x] "Ask-for-promise" is loaded by default in fsm dependency object;
|
|
431
|
-
- [x] Deep copy for stateData on each update with "walk" library;
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
### 2.2.3 ( 2021-04-02 )
|
|
436
|
-
- [x] Fix: Duplicated update callback if logic contain a chainAction;
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
### 2.2.2 ( 2021-03-26 )
|
|
442
|
-
- [x] Internal code refactoring;
|
|
443
|
-
- [ ] Bug: Duplicated update callback if logic contain a chainAction;
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
### 2.2.0 (2019-01-20)
|
|
448
|
-
- [x] Fix: Cached transitions are starting before callback functions for already executed transitions;
|
|
449
|
-
- [x] New method 'ignoreCachedUpdates()'. Ignore all cached updates;
|
|
450
|
-
|
|
451
|
-
### 2.1.0 (2019-01-19)
|
|
452
|
-
- [x] Export fsm state as an object - externalState;
|
|
453
|
-
- [x] Import externalState;
|
|
454
|
-
- [x] Lock updates during update process execution;
|
|
455
|
-
- [x] Prevent simultaneous updates;
|
|
456
|
-
- [x] Cache new updates during update process execution;
|
|
457
|
-
- [x] Execute cached updates in a row;
|
|
458
|
-
- [ ] Error: Cached transitions are starting before callback functions for already executed transitions;
|
|
459
|
-
|
|
460
|
-
### 2.0.0 (2018-12-01)
|
|
461
|
-
- [x] Transition function could contain asynchronous code;
|
|
462
|
-
- [x] Chain-actions in **transaction conditions** (Optional);
|
|
463
|
-
- [x] Chain-actions are possible on **positive** and *negative* transition-end;
|
|
464
|
-
|
|
465
|
-
### 1.0.0 (2018-11-21)
|
|
466
|
-
- [x] FSM;
|
|
467
|
-
- [x] Set FSM external dependencies;
|
|
468
|
-
- [x] Chain-actions by using `command` in transition response object;
|
|
469
|
-
- [x] Internal state flags and values with stateData;
|
|
391
|
+
- [Fsm version 4.x.x - previous version](https://github.com/PeterNaydenov/fsm/tree/4.x.x)
|
|
392
|
+
- [AskForPromise - a promise library](https://github.com/PeterNaydenov/ask-for-promise)
|
|
470
393
|
|
|
471
394
|
|
|
472
395
|
|