jssm 5.43.2 → 5.45.2
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/dist/es6/jssm.d.ts +5 -1
- package/dist/es6/jssm.js +99 -14
- package/dist/es6/jssm_types.d.ts +25 -1
- package/dist/es6/jssm_util.d.ts +3 -1
- package/dist/es6/jssm_util.js +3 -1
- package/dist/es6/version.js +1 -1
- package/dist/jssm.es5.cjs.js +1 -1
- package/dist/jssm.es5.iife.js +1 -1
- package/jssm.d.ts +5 -1
- package/jssm_types.d.ts +25 -1
- package/jssm_util.d.ts +3 -1
- package/package.json +8 -7
- package/src/ts/jssm.ts +145 -22
- package/src/ts/jssm_types.ts +40 -1
- package/src/ts/jssm_util.ts +18 -1
- package/src/ts/tests/hooks.spec.ts +184 -3
- package/src/ts/version.ts +1 -1
package/dist/es6/jssm.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
declare type StateType = string;
|
|
2
2
|
import { JssmGenericState, JssmGenericConfig, JssmTransition, JssmTransitionList, // JssmTransitionRule,
|
|
3
|
-
JssmMachineInternalState, JssmParseTree, JssmStateDeclaration, JssmArrow, JssmArrowDirection, JssmArrowKind, JssmLayout, FslDirection, FslTheme } from './jssm_types';
|
|
3
|
+
JssmMachineInternalState, JssmParseTree, JssmStateDeclaration, JssmArrow, JssmArrowDirection, JssmArrowKind, JssmLayout, FslDirection, FslTheme, HookDescription } from './jssm_types';
|
|
4
4
|
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key } from './jssm_util';
|
|
5
5
|
import { version } from './version';
|
|
6
6
|
declare function arrow_direction(arrow: JssmArrow): JssmArrowDirection;
|
|
@@ -37,6 +37,9 @@ declare class Machine<mDT> {
|
|
|
37
37
|
_arrange_end_declaration: Array<Array<StateType>>;
|
|
38
38
|
_theme: FslTheme;
|
|
39
39
|
_flow: FslDirection;
|
|
40
|
+
_has_hooks: boolean;
|
|
41
|
+
_hooks: Map<string, Function>;
|
|
42
|
+
_named_hooks: Map<string, Function>;
|
|
40
43
|
constructor({ start_states, complete, transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, state_declaration, fsl_version, dot_preamble, arrange_declaration, arrange_start_declaration, arrange_end_declaration, theme, flow, graph_layout }: JssmGenericConfig<mDT>);
|
|
41
44
|
_new_state(state_config: JssmGenericState): StateType;
|
|
42
45
|
state(): StateType;
|
|
@@ -86,6 +89,7 @@ declare class Machine<mDT> {
|
|
|
86
89
|
is_complete(): boolean;
|
|
87
90
|
state_is_complete(whichState: StateType): boolean;
|
|
88
91
|
has_completes(): boolean;
|
|
92
|
+
set_hook(HookDesc: HookDescription): void;
|
|
89
93
|
action(name: StateType, newData?: mDT): boolean;
|
|
90
94
|
transition(newState: StateType, newData?: mDT): boolean;
|
|
91
95
|
force_transition(newState: StateType, newData?: mDT): boolean;
|
package/dist/es6/jssm.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// whargarbl lots of these return arrays could/should be sets
|
|
2
2
|
import { reduce as reduce_to_639 } from 'reduce-to-639-1';
|
|
3
|
-
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, array_box_if_string } from './jssm_util';
|
|
3
|
+
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, array_box_if_string, hook_name, named_hook_name } from './jssm_util';
|
|
4
4
|
import { parse } from './jssm-dot'; // TODO FIXME WHARGARBL this could be post-typed
|
|
5
|
-
import { version } from './version'; // replaced from package.js in build
|
|
5
|
+
import { version } from './version'; // replaced from package.js in build
|
|
6
6
|
/* eslint-disable complexity */
|
|
7
7
|
function arrow_direction(arrow) {
|
|
8
8
|
switch (String(arrow)) {
|
|
@@ -345,6 +345,9 @@ class Machine {
|
|
|
345
345
|
this._theme = theme;
|
|
346
346
|
this._flow = flow;
|
|
347
347
|
this._graph_layout = graph_layout;
|
|
348
|
+
this._has_hooks = false;
|
|
349
|
+
this._hooks = new Map();
|
|
350
|
+
this._named_hooks = new Map();
|
|
348
351
|
if (state_declaration) {
|
|
349
352
|
state_declaration.map((state_decl) => {
|
|
350
353
|
if (this._state_declarations.has(state_decl.state)) { // no repeats
|
|
@@ -401,7 +404,7 @@ class Machine {
|
|
|
401
404
|
// set up the action mapping, so that actions can be looked up by origin
|
|
402
405
|
if (tr.action) {
|
|
403
406
|
// forward mapping first by action name
|
|
404
|
-
let actionMap = this._actions.get(tr.action);
|
|
407
|
+
let actionMap = this._actions.get(tr.action);
|
|
405
408
|
if (!(actionMap)) {
|
|
406
409
|
actionMap = new Map();
|
|
407
410
|
this._actions.set(tr.action, actionMap);
|
|
@@ -413,7 +416,7 @@ class Machine {
|
|
|
413
416
|
actionMap.set(tr.from, thisEdgeId);
|
|
414
417
|
}
|
|
415
418
|
// reverse mapping first by state origin name
|
|
416
|
-
let rActionMap = this._reverse_actions.get(tr.from);
|
|
419
|
+
let rActionMap = this._reverse_actions.get(tr.from);
|
|
417
420
|
if (!(rActionMap)) {
|
|
418
421
|
rActionMap = new Map();
|
|
419
422
|
this._reverse_actions.set(tr.from, rActionMap);
|
|
@@ -694,14 +697,59 @@ class Machine {
|
|
|
694
697
|
has_completes() {
|
|
695
698
|
return this.states().some((x) => this.state_is_complete(x));
|
|
696
699
|
}
|
|
700
|
+
// basic toolable hook call. convenience wrappers will follow, like
|
|
701
|
+
// hook(from, to, handler) and exit_hook(from, handler) and etc
|
|
702
|
+
set_hook(HookDesc) {
|
|
703
|
+
switch (HookDesc.kind) {
|
|
704
|
+
case 'hook':
|
|
705
|
+
this._hooks.set(hook_name(HookDesc.from, HookDesc.to), HookDesc.handler);
|
|
706
|
+
this._has_hooks = true;
|
|
707
|
+
break;
|
|
708
|
+
case 'named':
|
|
709
|
+
this._named_hooks.set(named_hook_name(HookDesc.from, HookDesc.to, HookDesc.action), HookDesc.handler);
|
|
710
|
+
this._has_hooks = true;
|
|
711
|
+
break;
|
|
712
|
+
// case 'entry':
|
|
713
|
+
// console.log('TODO: Should add entry hook here');
|
|
714
|
+
// throw 'TODO: Should add entry hook here';
|
|
715
|
+
// case 'exit':
|
|
716
|
+
// console.log('TODO: Should add exit hook here');
|
|
717
|
+
// throw 'TODO: Should add exit hook here';
|
|
718
|
+
default:
|
|
719
|
+
console.log(`Unknown hook type ${HookDesc.kind}, should be impossible`);
|
|
720
|
+
throw new RangeError(`Unknown hook type ${HookDesc.kind}, should be impossible`);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
// remove_hook(HookDesc: HookDescription) {
|
|
724
|
+
// throw 'TODO: Should remove hook here';
|
|
725
|
+
// }
|
|
697
726
|
action(name, newData) {
|
|
698
727
|
// todo whargarbl implement hooks
|
|
699
728
|
// todo whargarbl implement data stuff
|
|
700
729
|
// todo major incomplete whargarbl comeback
|
|
701
730
|
if (this.valid_action(name, newData)) {
|
|
702
731
|
const edge = this.current_action_edge_for(name);
|
|
703
|
-
this.
|
|
704
|
-
|
|
732
|
+
if (this._has_hooks) {
|
|
733
|
+
let hook_permits = undefined;
|
|
734
|
+
const nhn = named_hook_name(this._state, edge.to, name), maybe_hook = this._named_hooks.get(nhn);
|
|
735
|
+
if (maybe_hook === undefined) {
|
|
736
|
+
hook_permits = true;
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
hook_permits = maybe_hook({ from: this._state, to: edge.to, action: name });
|
|
740
|
+
}
|
|
741
|
+
if (hook_permits !== false) {
|
|
742
|
+
this._state = edge.to;
|
|
743
|
+
return true;
|
|
744
|
+
}
|
|
745
|
+
else {
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
else {
|
|
750
|
+
this._state = edge.to;
|
|
751
|
+
return true;
|
|
752
|
+
}
|
|
705
753
|
}
|
|
706
754
|
else {
|
|
707
755
|
return false;
|
|
@@ -712,8 +760,27 @@ class Machine {
|
|
|
712
760
|
// todo whargarbl implement data stuff
|
|
713
761
|
// todo major incomplete whargarbl comeback
|
|
714
762
|
if (this.valid_transition(newState, newData)) {
|
|
715
|
-
this.
|
|
716
|
-
|
|
763
|
+
if (this._has_hooks) {
|
|
764
|
+
let hook_permits = undefined;
|
|
765
|
+
const hn = hook_name(this._state, newState), maybe_hook = this._hooks.get(hn);
|
|
766
|
+
if (maybe_hook === undefined) {
|
|
767
|
+
hook_permits = true;
|
|
768
|
+
}
|
|
769
|
+
else {
|
|
770
|
+
hook_permits = maybe_hook({ from: this._state, to: newState });
|
|
771
|
+
}
|
|
772
|
+
if (hook_permits !== false) {
|
|
773
|
+
this._state = newState;
|
|
774
|
+
return true;
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
return false;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
this._state = newState;
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
717
784
|
}
|
|
718
785
|
else {
|
|
719
786
|
return false;
|
|
@@ -725,8 +792,27 @@ class Machine {
|
|
|
725
792
|
// todo whargarbl implement data stuff
|
|
726
793
|
// todo major incomplete whargarbl comeback
|
|
727
794
|
if (this.valid_force_transition(newState, newData)) {
|
|
728
|
-
this.
|
|
729
|
-
|
|
795
|
+
if (this._has_hooks) {
|
|
796
|
+
let hook_permits = undefined;
|
|
797
|
+
const hn = hook_name(this._state, newState), maybe_hook = this._hooks.get(hn);
|
|
798
|
+
if (maybe_hook === undefined) {
|
|
799
|
+
hook_permits = true;
|
|
800
|
+
}
|
|
801
|
+
else {
|
|
802
|
+
hook_permits = maybe_hook({ from: this._state, to: newState, forced: true });
|
|
803
|
+
}
|
|
804
|
+
if (hook_permits !== false) {
|
|
805
|
+
this._state = newState;
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
return false;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
else {
|
|
813
|
+
this._state = newState;
|
|
814
|
+
return true;
|
|
815
|
+
}
|
|
730
816
|
}
|
|
731
817
|
else {
|
|
732
818
|
return false;
|
|
@@ -734,7 +820,9 @@ class Machine {
|
|
|
734
820
|
}
|
|
735
821
|
current_action_for(action) {
|
|
736
822
|
const action_base = this._actions.get(action);
|
|
737
|
-
return action_base
|
|
823
|
+
return action_base
|
|
824
|
+
? action_base.get(this.state())
|
|
825
|
+
: undefined;
|
|
738
826
|
}
|
|
739
827
|
current_action_edge_for(action) {
|
|
740
828
|
const idx = this.current_action_for(action);
|
|
@@ -744,13 +832,11 @@ class Machine {
|
|
|
744
832
|
return this._edges[idx];
|
|
745
833
|
}
|
|
746
834
|
valid_action(action, _newData) {
|
|
747
|
-
// todo whargarbl implement hooks
|
|
748
835
|
// todo whargarbl implement data stuff
|
|
749
836
|
// todo major incomplete whargarbl comeback
|
|
750
837
|
return this.current_action_for(action) !== undefined;
|
|
751
838
|
}
|
|
752
839
|
valid_transition(newState, _newData) {
|
|
753
|
-
// todo whargarbl implement hooks
|
|
754
840
|
// todo whargarbl implement data stuff
|
|
755
841
|
// todo major incomplete whargarbl comeback
|
|
756
842
|
const transition_for = this.lookup_transition_for(this.state(), newState);
|
|
@@ -763,7 +849,6 @@ class Machine {
|
|
|
763
849
|
return true;
|
|
764
850
|
}
|
|
765
851
|
valid_force_transition(newState, _newData) {
|
|
766
|
-
// todo whargarbl implement hooks
|
|
767
852
|
// todo whargarbl implement data stuff
|
|
768
853
|
// todo major incomplete whargarbl comeback
|
|
769
854
|
return (this.lookup_transition_for(this.state(), newState) !== undefined);
|
package/dist/es6/jssm_types.d.ts
CHANGED
|
@@ -148,4 +148,28 @@ declare type JssmCompileSeStart<DataType> = {
|
|
|
148
148
|
};
|
|
149
149
|
declare type JssmParseTree = Array<JssmCompileSeStart<StateType>>;
|
|
150
150
|
declare type JssmParseFunctionType = (string: any) => JssmParseTree;
|
|
151
|
-
|
|
151
|
+
declare type BasicHookDescription = {
|
|
152
|
+
kind: 'hook';
|
|
153
|
+
from: string;
|
|
154
|
+
to: string;
|
|
155
|
+
handler: Function;
|
|
156
|
+
};
|
|
157
|
+
declare type HookDescriptionWithAction = {
|
|
158
|
+
kind: 'named';
|
|
159
|
+
from: string;
|
|
160
|
+
to: string;
|
|
161
|
+
action: string;
|
|
162
|
+
handler: Function;
|
|
163
|
+
};
|
|
164
|
+
declare type EntryHook = {
|
|
165
|
+
kind: 'entry';
|
|
166
|
+
to: string;
|
|
167
|
+
handler: Function;
|
|
168
|
+
};
|
|
169
|
+
declare type ExitHook = {
|
|
170
|
+
kind: 'exit';
|
|
171
|
+
from: string;
|
|
172
|
+
handler: Function;
|
|
173
|
+
};
|
|
174
|
+
declare type HookDescription = BasicHookDescription | HookDescriptionWithAction | EntryHook | ExitHook;
|
|
175
|
+
export { JssmColor, JssmTransition, JssmTransitions, JssmTransitionList, JssmTransitionRule, JssmArrow, JssmArrowKind, JssmArrowDirection, JssmGenericConfig, JssmGenericState, JssmGenericMachine, JssmParseTree, JssmCompileSe, JssmCompileSeStart, JssmCompileRule, JssmPermitted, JssmPermittedOpt, JssmResult, JssmStateDeclaration, JssmStateDeclarationRule, JssmLayout, JssmParseFunctionType, JssmMachineInternalState, FslDirection, FslTheme, HookDescription };
|
package/dist/es6/jssm_util.d.ts
CHANGED
|
@@ -5,4 +5,6 @@ declare const seq: Function;
|
|
|
5
5
|
declare const histograph: Function;
|
|
6
6
|
declare const weighted_sample_select: Function;
|
|
7
7
|
declare const weighted_histo_key: Function;
|
|
8
|
-
|
|
8
|
+
declare const hook_name: (from: string, to: string) => string;
|
|
9
|
+
declare const named_hook_name: (from: string, to: string, action: string) => string;
|
|
10
|
+
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, hook_name, named_hook_name };
|
package/dist/es6/jssm_util.js
CHANGED
|
@@ -31,4 +31,6 @@ const weighted_histo_key = (n, opts, prob_prop, extract) => // TODO FIXME no any
|
|
|
31
31
|
histograph(weighted_sample_select(n, opts, prob_prop)
|
|
32
32
|
.map((s) => s[extract] // TODO FIXME eslint-disable-line flowtype/no-weak-types
|
|
33
33
|
));
|
|
34
|
-
|
|
34
|
+
const hook_name = (from, to) => JSON.stringify([from, to]);
|
|
35
|
+
const named_hook_name = (from, to, action) => JSON.stringify([from, to, action]);
|
|
36
|
+
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, hook_name, named_hook_name };
|
package/dist/es6/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const version = "5.
|
|
1
|
+
const version = "5.45.2";
|
|
2
2
|
export { version };
|