@peter.naydenov/fsm-hub 2.1.5 → 2.1.6
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/{Chaingelog.md → Changelog.md} +8 -0
- package/package.json +2 -2
- package/src/methods/_callback.js +20 -4
- package/test/01-basics.js +137 -1
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
## Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
### 2.1.6 ( 2026-07-22)
|
|
5
|
+
- [x] Fix: `_callback.js` crashed when a callback rule fired with a `null` response (or a transformer returning `null`). Guarded the `.answer` access so the placeholder-clear no-ops and the callback still runs.
|
|
6
|
+
- [x] Fix: `MISSING_FSM` debugger call logged the whole subscribers array instead of the missing name. Now passes the specific missing entry.
|
|
7
|
+
- [x] Tests: 3 regression cases added (1 for the `MISSING_FSM` data, 2 for the null-response crashes). 14 → 17 passing;
|
|
8
|
+
- [x] Dev dependencies updates. @peter.naydenov/fsm - v.5.2.7;
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
4
12
|
### 2.1.5 ( 2026-07-21)
|
|
5
13
|
- [x] Dependency update. ask-for-promise@3.2.0;
|
|
6
14
|
- [x] Dev dependency update. @peter.naydenov/fsm - v.5.2.6;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/fsm-hub",
|
|
3
3
|
"description": "FSM orchestration and state-managment tool",
|
|
4
|
-
"version": "2.1.
|
|
4
|
+
"version": "2.1.6",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Peter Naydenov",
|
|
7
7
|
"main": "./dist/fsm-hub.umd.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"ask-for-promise": "^3.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@peter.naydenov/fsm": "5.2.
|
|
29
|
+
"@peter.naydenov/fsm": "5.2.7",
|
|
30
30
|
"@rollup/plugin-commonjs": "^29.0.3",
|
|
31
31
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
32
32
|
"@rollup/plugin-terser": "^1.0.0",
|
package/src/methods/_callback.js
CHANGED
|
@@ -17,10 +17,18 @@ return function _callback ( task, fsmName, state, response ) {
|
|
|
17
17
|
return
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
if ( fsmSubscriber ) { // Execute fsm rules
|
|
20
|
+
if ( fsmSubscriber ) { // Execute fsm rules
|
|
21
21
|
fsmSubscriber.forEach ( subscriberName => {
|
|
22
22
|
if ( !hub.fsm[ subscriberName ] ) {
|
|
23
|
-
|
|
23
|
+
// Log the missing subscriber's name, not the
|
|
24
|
+
// whole subscribers array. The debugger formats
|
|
25
|
+
// the warning as `Warning: Fsm "%s" is not
|
|
26
|
+
// registered to the hub.` and the array makes
|
|
27
|
+
// the message look like
|
|
28
|
+
// `... to the hub. [ 'two' ]`
|
|
29
|
+
// instead of the intended
|
|
30
|
+
// `... to the hub. two`
|
|
31
|
+
hub._debugger ( msg.MISSING_FSM, subscriberName )
|
|
24
32
|
return
|
|
25
33
|
}
|
|
26
34
|
const
|
|
@@ -57,8 +65,16 @@ return function _callback ( task, fsmName, state, response ) {
|
|
|
57
65
|
if ( typeof transformFn == 'function' ) data = transformFn (state, response )
|
|
58
66
|
else data = response
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
// `data` can be null/undefined if the response is
|
|
69
|
+
// null and no transformer is set, or if the
|
|
70
|
+
// transformer itself returns null. Guard the
|
|
71
|
+
// `.answer` access so we don't blow up — the
|
|
72
|
+
// placeholder-clear below is a no-op when
|
|
73
|
+
// `data` is falsy, and `fn(data)` will still
|
|
74
|
+
// receive whatever value the user/transformer
|
|
75
|
+
// produced (null included).
|
|
76
|
+
if ( data && data.answer && data.answer.hasOwnProperty ( '___internalFlag') ) data.answer = undefined
|
|
77
|
+
|
|
62
78
|
if ( typeof fn == 'function' ) fn(data)
|
|
63
79
|
else hub._debugger ( msg.MISSING_FN, cbName )
|
|
64
80
|
|
package/test/01-basics.js
CHANGED
|
@@ -529,7 +529,7 @@ it ( 'Callback-function with data argument', done => {
|
|
|
529
529
|
|
|
530
530
|
|
|
531
531
|
it ( 'Test a Debugger', () => {
|
|
532
|
-
const
|
|
532
|
+
const
|
|
533
533
|
machine = {
|
|
534
534
|
reactivity : [
|
|
535
535
|
[ 'one', 'active', 'two', 'activate' ]
|
|
@@ -543,6 +543,142 @@ it ( 'Callback-function with data argument', done => {
|
|
|
543
543
|
|
|
544
544
|
|
|
545
545
|
|
|
546
|
+
|
|
547
|
+
// =====================================================================
|
|
548
|
+
// BUG REGRESSIONS
|
|
549
|
+
// =====================================================================
|
|
550
|
+
|
|
551
|
+
// -----------------------------------------------------------------
|
|
552
|
+
// BUG A — _callback.js passed `fsmSubscriber` (the whole array of
|
|
553
|
+
// subscriber names) as the data arg to MISSING_FSM, instead of
|
|
554
|
+
// `subscriberName` (the specific missing one). The warning message
|
|
555
|
+
// therefore looked like
|
|
556
|
+
// `Warning: Fsm "%s" is not registered to the hub. [ 'two' ]`
|
|
557
|
+
// instead of the intended
|
|
558
|
+
// `Warning: Fsm "%s" is not registered to the hub. two`.
|
|
559
|
+
// The existing test "Not registered fsm subscriber" only checks the
|
|
560
|
+
// `str` half of the call, so the wrong data was never noticed.
|
|
561
|
+
// -----------------------------------------------------------------
|
|
562
|
+
it ( 'BUG A — MISSING_FSM is logged with the missing name, not the array', done => {
|
|
563
|
+
const
|
|
564
|
+
mini = {
|
|
565
|
+
init : 'none'
|
|
566
|
+
, behavior : [
|
|
567
|
+
[ 'none', 'activate', 'active', 'switchOn' ]
|
|
568
|
+
]
|
|
569
|
+
}
|
|
570
|
+
, lib = {
|
|
571
|
+
switchOn ({ task }, data) {
|
|
572
|
+
task.done ({ success : true, response : data })
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
, one = new Fsm ( mini, lib )
|
|
576
|
+
;
|
|
577
|
+
const hub = new FsmHub ({
|
|
578
|
+
reactivity : [
|
|
579
|
+
[ 'one', 'active', 'two', 'activate' ]
|
|
580
|
+
]
|
|
581
|
+
});
|
|
582
|
+
const calls = [];
|
|
583
|
+
hub._debugger = ( str, data ) => calls.push ({ str, data });
|
|
584
|
+
hub.addFsm ({ one }); // 'two' is intentionally NOT registered
|
|
585
|
+
|
|
586
|
+
one.update ( 'activate', 'try' );
|
|
587
|
+
|
|
588
|
+
setTimeout ( () => {
|
|
589
|
+
const missing = calls.find ( c => c.str === MISSING_FSM )
|
|
590
|
+
expect ( missing, 'MISSING_FSM was not logged' ).to.exist
|
|
591
|
+
// The data should be the missing name 'two' (a string),
|
|
592
|
+
// NOT the whole subscribers array.
|
|
593
|
+
expect ( missing.data ).to.equal ( 'two' )
|
|
594
|
+
done ()
|
|
595
|
+
}, 50 )
|
|
596
|
+
}) // it BUG A
|
|
597
|
+
|
|
598
|
+
// -----------------------------------------------------------------
|
|
599
|
+
// BUG B — _callback.js crashed with
|
|
600
|
+
// `TypeError: Cannot read properties of null (reading 'answer')`
|
|
601
|
+
// when a callback rule (length 3 in `reactivity`) was triggered
|
|
602
|
+
// and the FSM's response was `null` (and no transformer was
|
|
603
|
+
// configured, or the transformer itself returned `null`).
|
|
604
|
+
//
|
|
605
|
+
// The existing test "Callback-function with data argument" always
|
|
606
|
+
// passes a non-null `response`, so this path was never exercised.
|
|
607
|
+
// -----------------------------------------------------------------
|
|
608
|
+
it ( 'BUG B — callback rule with null response does not crash', done => {
|
|
609
|
+
const
|
|
610
|
+
mini = {
|
|
611
|
+
init : 'none'
|
|
612
|
+
, behavior : [
|
|
613
|
+
[ 'none', 'activate', 'active', 'switchOn' ]
|
|
614
|
+
]
|
|
615
|
+
}
|
|
616
|
+
// Transition returns response: null. No transformer.
|
|
617
|
+
, lib = {
|
|
618
|
+
switchOn ({ task }) {
|
|
619
|
+
task.done ({ success : true, response : null })
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
, one = new Fsm ( mini, lib )
|
|
623
|
+
;
|
|
624
|
+
const hub = new FsmHub ({
|
|
625
|
+
reactivity : [
|
|
626
|
+
// length-3 rule = callback, no fsm subscriber
|
|
627
|
+
[ 'one', 'active', 'showme' ]
|
|
628
|
+
]
|
|
629
|
+
});
|
|
630
|
+
function showme ( data ) {
|
|
631
|
+
// The crash happened BEFORE this was called.
|
|
632
|
+
// We just want to assert: the callback fires
|
|
633
|
+
// and `data` is what the response was (null).
|
|
634
|
+
expect ( data ).to.equal ( null )
|
|
635
|
+
done ()
|
|
636
|
+
} // showme func.
|
|
637
|
+
hub.addFsm ({ one });
|
|
638
|
+
hub.addFunctions ({ showme });
|
|
639
|
+
|
|
640
|
+
one.update ( 'activate' );
|
|
641
|
+
}) // it BUG B — null response
|
|
642
|
+
|
|
643
|
+
it ( 'BUG B — callback rule with a transformer that returns null does not crash', done => {
|
|
644
|
+
const
|
|
645
|
+
mini = {
|
|
646
|
+
init : 'none'
|
|
647
|
+
, behavior : [
|
|
648
|
+
[ 'none', 'activate', 'active', 'switchOn' ]
|
|
649
|
+
]
|
|
650
|
+
}
|
|
651
|
+
, lib = {
|
|
652
|
+
switchOn ({ task }, data) {
|
|
653
|
+
task.done ({ success : true, response : data })
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
, one = new Fsm ( mini, lib )
|
|
657
|
+
;
|
|
658
|
+
const hub = new FsmHub ({
|
|
659
|
+
reactivity : [
|
|
660
|
+
[ 'one', 'active', 'showme' ]
|
|
661
|
+
]
|
|
662
|
+
, transformers : {
|
|
663
|
+
'one/showme' : 'nullTransformer'
|
|
664
|
+
}
|
|
665
|
+
}, {
|
|
666
|
+
// A transformer that returns null. This used to
|
|
667
|
+
// crash in _callback.js's `data.answer` check.
|
|
668
|
+
nullTransformer () { return null }
|
|
669
|
+
});
|
|
670
|
+
function showme ( data ) {
|
|
671
|
+
expect ( data ).to.equal ( null )
|
|
672
|
+
done ()
|
|
673
|
+
} // showme func.
|
|
674
|
+
hub.addFsm ({ one });
|
|
675
|
+
hub.addFunctions ({ showme });
|
|
676
|
+
|
|
677
|
+
one.update ( 'activate', 'try' );
|
|
678
|
+
}) // it BUG B — null transformer
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
546
682
|
|
|
547
683
|
}) // describe
|
|
548
684
|
|