state-machine-cat 10.1.1 → 10.1.3

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.
Files changed (36) hide show
  1. package/README.md +1 -1
  2. package/bin/smcat.mjs +5 -0
  3. package/dist/commonjs/bundle.js +64 -64
  4. package/package.json +33 -32
  5. package/src/cli/actions.mjs +9 -0
  6. package/src/cli/file-name-to-stream.mjs +5 -6
  7. package/src/cli/make-description.mjs +9 -0
  8. package/src/cli/normalize.mjs +79 -41
  9. package/src/cli/validations.mjs +27 -1
  10. package/src/index-node.mjs +15 -47
  11. package/src/index.mjs +9 -9
  12. package/src/options.mjs +19 -13
  13. package/src/parse/index.mjs +13 -0
  14. package/src/parse/parser-helpers.mjs +70 -6
  15. package/src/parse/scxml/index.mjs +40 -1
  16. package/src/parse/scxml/normalize-machine.mjs +1 -1
  17. package/src/render/dot/attributebuilder.mjs +7 -0
  18. package/src/render/dot/counter.mjs +13 -0
  19. package/src/render/dot/index.mjs +66 -28
  20. package/src/render/dot/render-dot-from-ast.js +37 -15
  21. package/src/render/dot/state-transformers.mjs +4 -2
  22. package/src/render/dot/utl.mjs +20 -0
  23. package/src/render/index-node.mjs +9 -3
  24. package/src/render/index.mjs +3 -3
  25. package/src/render/scjson/index.mjs +6 -0
  26. package/src/render/scjson/make-valid-xml-name.mjs +7 -1
  27. package/src/render/scxml/index.mjs +3 -1
  28. package/src/render/smcat/index.js +48 -14
  29. package/src/render/vector/dot-to-vector-native.mjs +1 -1
  30. package/src/render/vector/vector-native-dot-with-fallback.mjs +3 -2
  31. package/src/render/vector/vector-with-viz-js.mjs +3 -2
  32. package/src/state-machine-model.mjs +46 -4
  33. package/src/transform/desugar.mjs +67 -18
  34. package/src/transform/utl.mjs +8 -0
  35. package/src/version.mjs +2 -1
  36. package/types/state-machine-cat.d.ts +41 -14
@@ -1,3 +1,4 @@
1
+ /** @type {any} - the Handlebars delivered types don't seem to cover everythint in handlebars ...*/
1
2
  const Handlebars = require("handlebars/dist/handlebars.runtime.js");
2
3
  // eslint-disable-next-line import/no-unassigned-import
3
4
  require("./dot.template.js");
@@ -15,34 +16,55 @@ Handlebars.registerHelper("stateSection", (pStateMachine) =>
15
16
  );
16
17
 
17
18
  // TODO: duplicate from the one in state-transformers.js
19
+ /**
20
+ *
21
+ * @param {string} pString
22
+ * @returns {(pState: import("../../../types/state-machine-cat.js").IState) => Boolean}
23
+ */
18
24
  function isType(pString) {
19
25
  return (pState) => pState.type === pString;
20
26
  }
27
+ /**
28
+ *
29
+ * @param {string[]} pStringArray
30
+ * @returns {(pState: import("../../../types/state-machine-cat.js").IState) => Boolean}
31
+ */
21
32
  // TODO: duplicate from the one in state-transformers.js
22
33
  function isOneOfTypes(pStringArray) {
23
34
  return (pState) => pStringArray.includes(pState.type);
24
35
  }
25
36
 
26
37
  // TODO: duplicate from the one in index.js
27
- function splitStates(pAST) {
28
- pAST.initialStates = pAST.states.filter(isType("initial"));
29
- pAST.regularStates = pAST.states.filter(
38
+ function splitStates(pStateMachine) {
39
+ pStateMachine.initialStates = pStateMachine.states.filter(isType("initial"));
40
+ pStateMachine.regularStates = pStateMachine.states.filter(
30
41
  (pState) => isType("regular")(pState) && !pState.statemachine
31
42
  );
32
- pAST.historyStates = pAST.states.filter(isType("history"));
33
- pAST.deepHistoryStates = pAST.states.filter(isType("deephistory"));
34
- pAST.choiceStates = pAST.states.filter(isType("choice"));
35
- pAST.forkjoinStates = pAST.states.filter(
43
+ pStateMachine.historyStates = pStateMachine.states.filter(isType("history"));
44
+ pStateMachine.deepHistoryStates = pStateMachine.states.filter(
45
+ isType("deephistory")
46
+ );
47
+ pStateMachine.choiceStates = pStateMachine.states.filter(isType("choice"));
48
+ pStateMachine.forkjoinStates = pStateMachine.states.filter(
36
49
  isOneOfTypes(["fork", "join", "forkjoin"])
37
50
  );
38
- pAST.junctionStates = pAST.states.filter(isType("junction"));
39
- pAST.terminateStates = pAST.states.filter(isType("terminate"));
40
- pAST.finalStates = pAST.states.filter(isType("final"));
41
- pAST.compositeStates = pAST.states.filter((pState) => pState.statemachine);
51
+ pStateMachine.junctionStates = pStateMachine.states.filter(
52
+ isType("junction")
53
+ );
54
+ pStateMachine.terminateStates = pStateMachine.states.filter(
55
+ isType("terminate")
56
+ );
57
+ pStateMachine.finalStates = pStateMachine.states.filter(isType("final"));
58
+ pStateMachine.compositeStates = pStateMachine.states.filter(
59
+ (pState) => pState.statemachine
60
+ );
42
61
 
43
- return pAST;
62
+ return pStateMachine;
44
63
  }
45
-
46
- module.exports = function renderDotFromAST(pAST) {
47
- return Handlebars.templates["dot.template.hbs"](pAST);
64
+ /**
65
+ * @param {import("../../../types/state-machine-cat.js").IStateMachine} pStateMachine
66
+ * @returns {string}
67
+ */
68
+ module.exports = function renderDotFromAST(pStateMachine) {
69
+ return Handlebars.templates["dot.template.hbs"](pStateMachine);
48
70
  };
@@ -1,3 +1,4 @@
1
+ import cloneDeep from "lodash/cloneDeep.js";
1
2
  import utl from "./utl.mjs";
2
3
 
3
4
  function isType(pString) {
@@ -8,8 +9,9 @@ function isOneOfTypes(pStringArray) {
8
9
  }
9
10
 
10
11
  function setLabel(pState) {
11
- pState.label = pState.label || pState.name;
12
- return pState;
12
+ const lState = cloneDeep(pState);
13
+ lState.label = pState.label || pState.name;
14
+ return lState;
13
15
  }
14
16
 
15
17
  function nameNote(pState) {
@@ -1,3 +1,9 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @param {string} pString
5
+ * @returns {string}
6
+ */
1
7
  function escapeString(pString) {
2
8
  return pString
3
9
  .replace(/\\/g, "\\\\")
@@ -6,6 +12,10 @@ function escapeString(pString) {
6
12
  .concat("\\l");
7
13
  }
8
14
 
15
+ /**
16
+ * @param {string} pString
17
+ * @returns {string}
18
+ */
9
19
  function escapeLabelString(pString) {
10
20
  return pString
11
21
  .replace(/\\/g, "\\\\")
@@ -14,12 +24,22 @@ function escapeLabelString(pString) {
14
24
  .concat(" \\l");
15
25
  }
16
26
 
27
+ /**
28
+ * @param {string} pDirection
29
+ * @returns {boolean}
30
+ */
17
31
  function isVertical(pDirection) {
18
32
  const lDirection = pDirection || "top-down";
19
33
 
20
34
  return lDirection === "top-down" || lDirection === "bottom-top";
21
35
  }
22
36
 
37
+ /**
38
+ *
39
+ * @param {import("../../state-machine-model.mjs").default} pStateMachineModel
40
+ * @param {import("../../../types/state-machine-cat").ITransition} pTransition
41
+ * @returns {boolean}
42
+ */
23
43
  function isCompositeSelf(pStateMachineModel, pTransition) {
24
44
  return (
25
45
  pTransition.from === pTransition.to &&
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  /* eslint-disable security/detect-object-injection */
2
3
  import has from "lodash/has.js";
3
4
  import smcat from "./smcat/index.js";
@@ -7,8 +8,13 @@ import oldVector from "./vector/vector-with-viz-js.mjs";
7
8
  import scjson from "./scjson/index.mjs";
8
9
  import scxml from "./scxml/index.mjs";
9
10
 
11
+ /**
12
+ *
13
+ * @param {import("../../types/state-machine-cat.js").OutputType} pOutputType
14
+ * @returns {import("../../types/state-machine-cat.js").RenderFunctionType}
15
+ */
10
16
  export default function getRenderFunction(pOutputType) {
11
- const lOutputtype2Renderfunction = {
17
+ const lOutputType2RenderFunction = {
12
18
  smcat,
13
19
  dot,
14
20
  svg: vector,
@@ -24,7 +30,7 @@ export default function getRenderFunction(pOutputType) {
24
30
  scxml,
25
31
  };
26
32
 
27
- return has(lOutputtype2Renderfunction, pOutputType)
28
- ? lOutputtype2Renderfunction[pOutputType]
33
+ return has(lOutputType2RenderFunction, pOutputType)
34
+ ? lOutputType2RenderFunction[pOutputType]
29
35
  : (pX) => pX;
30
36
  }
@@ -7,7 +7,7 @@ import scjson from "./scjson/index.mjs";
7
7
  import scxml from "./scxml/index.mjs";
8
8
 
9
9
  export default function getRenderFunction(pOutputType) {
10
- const lOutputtype2Renderfunction = {
10
+ const lOutputType2RenderFunction = {
11
11
  smcat,
12
12
  dot,
13
13
  svg,
@@ -16,7 +16,7 @@ export default function getRenderFunction(pOutputType) {
16
16
  scxml,
17
17
  };
18
18
 
19
- return has(lOutputtype2Renderfunction, pOutputType)
20
- ? lOutputtype2Renderfunction[pOutputType]
19
+ return has(lOutputType2RenderFunction, pOutputType)
20
+ ? lOutputType2RenderFunction[pOutputType]
21
21
  : (pX) => pX;
22
22
  }
@@ -137,6 +137,12 @@ function findInitialStateName(pStateMachine, pInitialPseudoStateName) {
137
137
  return lReturnValue;
138
138
  }
139
139
 
140
+ /**
141
+ * @param {import("../../../types/state-machine-cat").IStateMachine} pStateMachine
142
+ * @param {import("../../../types/state-machine-cat").IRenderOptions?} _pOptions
143
+ * @param {import("../../../types/state-machine-cat").ITransition[]?} pTransitions
144
+ * @returns {any}
145
+ */
140
146
  export default function render(pStateMachine, _pOptions, pTransitions) {
141
147
  const lInitialPseudoStateName = findInitialPseudoStateName(pStateMachine);
142
148
  const lInitialStateName = findInitialStateName(
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  /*
2
3
  * In the XML spec we read: https://www.w3.org/TR/xml/#NT-Name:
3
4
  *
@@ -18,6 +19,11 @@ const NAME_CHAR_FORBIDDEN_RE =
18
19
  const START_NAME_CHAR_FORBIDDEN_EXTRA_RE =
19
20
  /[-|.|0-9|\u00B7|\u0300-\u036F|\u203F-\u2040]/g;
20
21
 
22
+ /**
23
+ *
24
+ * @param {string} pCandidateNameTail
25
+ * @returns {string}
26
+ */
21
27
  function makeValidNameChars(pCandidateNameTail) {
22
28
  return pCandidateNameTail.replace(NAME_CHAR_FORBIDDEN_RE, "_");
23
29
  }
@@ -25,7 +31,7 @@ function makeValidNameChars(pCandidateNameTail) {
25
31
  /**
26
32
  * if it's an invalid NameStartChar but a valid NameChar smack a '_' in front of it
27
33
  * if it's an invalid NameChar as well - run it through the makeValidNameChars replacer
28
- * @param {char} pCandidateChar - start char
34
+ * @param {string} pCandidateChar - start char
29
35
  * @returns {string} valid start string
30
36
  */
31
37
  function makeValidNameStartChar(pCandidateChar) {
@@ -1,6 +1,8 @@
1
+ // @ts-check
1
2
  import ast2scjson from "../scjson/index.mjs";
2
3
  import renderFomSCJSON from "./render-from-scjson.js";
3
4
 
5
+ /** @type {import("../../../types/state-machine-cat.js").StringRenderFunctionType} */
4
6
  export default function renderSCXML(pStateMachine) {
5
- return renderFomSCJSON(ast2scjson(pStateMachine));
7
+ return renderFomSCJSON(ast2scjson(pStateMachine, null));
6
8
  }
@@ -1,13 +1,25 @@
1
+ // @ts-check
2
+ /** @type {any} - the type definitions for Handlebars don't match what we're actually using - hence this override*/
1
3
  const Handlebars = require("handlebars/dist/handlebars.runtime.js");
2
4
  const cloneDeep = require("lodash/cloneDeep.js");
3
5
 
4
6
  // eslint-disable-next-line import/no-unassigned-import
5
7
  require("./smcat.template.js");
6
8
 
9
+ /**
10
+ * @typedef {{hasExtendedAttributes?: boolean} & import("../../../types/state-machine-cat.js").IState} IExtendedState
11
+ * @typedef {{actions: string;} & Omit<IExtendedState, "actions">} IFlattenedActionsState
12
+ */
13
+
7
14
  const NAME_QUOTABLE = /;|,|{| |\[/;
8
15
  const ACTIONS_QUOTABLE = /;|,|{/;
9
16
  const LABEL_QUOTABLE = /;|{/;
10
17
 
18
+ /**
19
+ * @param {RegExp} pRegExp
20
+ * @param {string} pString
21
+ * @returns {string}
22
+ */
11
23
  function quoteIfNecessary(pRegExp, pString) {
12
24
  return pRegExp.test(pString) ? `"${pString}"` : pString;
13
25
  }
@@ -17,20 +29,31 @@ Handlebars.registerPartial(
17
29
  Handlebars.templates["smcat.template.hbs"]
18
30
  );
19
31
 
32
+ /**
33
+ * @param {string} pString
34
+ * @returns {string}
35
+ */
20
36
  function formatActionType(pString) {
21
37
  return pString === "activity" ? "" : `${pString}/ `;
22
38
  }
23
39
 
40
+ /**
41
+ * @param {IExtendedState} pState
42
+ * @returns {IFlattenedActionsState}
43
+ */
24
44
  function flattenActions(pState) {
25
- const lReturnValue = { ...pState };
26
-
27
- lReturnValue.actions = (pState.actions || [])
28
- .map((pAction) => `${formatActionType(pAction.type)}${pAction.body}`)
29
- .join("\n ");
30
-
31
- return lReturnValue;
45
+ return {
46
+ ...pState,
47
+ actions: (pState.actions || [])
48
+ .map((pAction) => `${formatActionType(pAction.type)}${pAction.body}`)
49
+ .join("\n "),
50
+ };
32
51
  }
33
52
 
53
+ /**
54
+ * @param {IExtendedState} pState
55
+ * @returns {IExtendedState}
56
+ */
34
57
  /* eslint complexity:0 */
35
58
  function flagExtendedStateAttributes(pState) {
36
59
  if (
@@ -40,19 +63,27 @@ function flagExtendedStateAttributes(pState) {
40
63
  Object.prototype.hasOwnProperty.call(pState, "active") ||
41
64
  Object.prototype.hasOwnProperty.call(pState, "class")
42
65
  ) {
66
+ // note & fixme: mutating a parameter here
43
67
  pState.hasExtendedAttributes = true;
44
68
  }
45
69
  return pState;
46
70
  }
47
71
 
48
- function transformStates(pStates, pDirection) {
72
+ /**
73
+ * @param {import("../../../types/state-machine-cat.js").IState[]} pStates
74
+ * @returns {IFlattenedActionsState[]}
75
+ */
76
+ function transformStates(pStates) {
49
77
  pStates
50
78
  .map(flagExtendedStateAttributes)
51
79
  .filter((pState) => pState.statemachine)
52
80
  .forEach((pState) => {
81
+ // @ts-expect-error because of the filter above the statemachine is
82
+ // sure to exist, although TS currently doesn't detect this.
83
+ // also fixme: mutating a parameter here
53
84
  pState.statemachine.states = transformStates(
54
- pState.statemachine.states,
55
- pDirection
85
+ // @ts-expect-error - see above
86
+ pState.statemachine.states
56
87
  );
57
88
  });
58
89
 
@@ -86,10 +117,13 @@ Handlebars.registerHelper("quotifyActions", (pItem) =>
86
117
  quoteIfNecessary(ACTIONS_QUOTABLE, pItem)
87
118
  );
88
119
 
89
- module.exports = function renderSmcat(pAST) {
120
+ /** @type {import("../../../types/state-machine-cat.js").StringRenderFunctionType} */
121
+ module.exports = function renderSmcat(pStateMachine) {
90
122
  return Handlebars.templates["smcat.template.hbs"]({
91
- ...pAST,
92
- states: transformStates(cloneDeep(pAST.states)),
93
- transitions: transformTransitions(cloneDeep(pAST.transitions || [])),
123
+ ...pStateMachine,
124
+ states: transformStates(cloneDeep(pStateMachine.states)),
125
+ transitions: transformTransitions(
126
+ cloneDeep(pStateMachine.transitions || [])
127
+ ),
94
128
  });
95
129
  };
@@ -11,7 +11,7 @@ const DEFAULT_OPTIONS = {
11
11
  * the result
12
12
  *
13
13
  * @param {string} pDot The dot program as a string
14
- * @param {object} pOptions
14
+ * @param {{exec: string, format: import("../../../types/state-machine-cat").OutputType}} pOptions
15
15
  * exec: the path to the executable to run. Default: 'dot'
16
16
  * @return {string} the dot program converted into an svg
17
17
  * @throws {Error} when something ontowards has happened (executable not found, erroneous dot program)
@@ -10,8 +10,9 @@ const DEFAULT_INDENT = 2;
10
10
  const DOGMATIC_CONSOLE_WIDTH = 78;
11
11
  const VIZ_JS_UNSUPPORTED_OUTPUT_FORMATS = ["pdf", "png"];
12
12
 
13
- export default (pAST, pOptions) => {
14
- const lDotProgram = ast2dot(pAST, pOptions);
13
+ /** @type {import("../../../types/state-machine-cat.js").StringRenderFunctionType} */
14
+ export default (pStateMachine, pOptions) => {
15
+ const lDotProgram = ast2dot(pStateMachine, pOptions);
15
16
  const lDotOptions = {
16
17
  engine: options.getOptionValue(pOptions, "engine"),
17
18
  format: options.getOptionValue(pOptions, "outputType"),
@@ -8,8 +8,9 @@ const OUTPUT_TYPE2FORMAT = {
8
8
  oldeps: "eps",
9
9
  };
10
10
 
11
- export default (pAST, pOptions) =>
12
- viz(ast2dot(pAST, pOptions), {
11
+ /** @type {import("../../../types/state-machine-cat.js").StringRenderFunctionType} */
12
+ export default (pStateMachine, pOptions) =>
13
+ viz(ast2dot(pStateMachine, pOptions), {
13
14
  engine: options.getOptionValue(pOptions, "engine"),
14
15
  format:
15
16
  OUTPUT_TYPE2FORMAT[options.getOptionValue(pOptions, "outputType")] ||
@@ -1,3 +1,9 @@
1
+ // @ts-check
2
+ /**
3
+ * @param {import("../types/state-machine-cat").IState[]} pStates
4
+ * @param {boolean} pHasParent
5
+ * @returns {any} // IFlattenedState - a state, but flattened (statemachine is a boolean, the new attr hasParent as well)
6
+ */
1
7
  function flattenStates(pStates, pHasParent = false) {
2
8
  let lReturnValue = [];
3
9
 
@@ -6,6 +12,8 @@ function flattenStates(pStates, pHasParent = false) {
6
12
  .forEach((pState) => {
7
13
  if (Object.prototype.hasOwnProperty.call(pState.statemachine, "states")) {
8
14
  lReturnValue = lReturnValue.concat(
15
+ // @ts-expect-error TS doesn't detect that after the call in the filter
16
+ // the .statemachine is guaranteed to exist
9
17
  flattenStates(pState.statemachine.states, true)
10
18
  );
11
19
  }
@@ -21,10 +29,17 @@ function flattenStates(pStates, pHasParent = false) {
21
29
  );
22
30
  }
23
31
 
32
+ /**
33
+ * @param {import("../types/state-machine-cat").IStateMachine} pStateMachine
34
+ * @returns {import("../types/state-machine-cat").ITransition[]}
35
+ */
24
36
  function flattenTransitions(pStateMachine) {
37
+ /** @type {import("../types/state-machine-cat").ITransition[]} */
25
38
  let lTransitions = [];
26
39
 
27
40
  if (Object.prototype.hasOwnProperty.call(pStateMachine, "transitions")) {
41
+ // @ts-expect-error TS doesn't detect that after the call in the if the
42
+ // .transitions is guaranteed to exist
28
43
  lTransitions = pStateMachine.transitions;
29
44
  }
30
45
  if (Object.prototype.hasOwnProperty.call(pStateMachine, "states")) {
@@ -32,6 +47,8 @@ function flattenTransitions(pStateMachine) {
32
47
  .filter((pState) => Boolean(pState.statemachine))
33
48
  .forEach((pState) => {
34
49
  lTransitions = lTransitions.concat(
50
+ // @ts-expect-error TS doesn't detect that after the call in the filter
51
+ // the .statemachine is guaranteed to exist
35
52
  flattenTransitions(pState.statemachine)
36
53
  );
37
54
  });
@@ -40,25 +57,42 @@ function flattenTransitions(pStateMachine) {
40
57
  }
41
58
 
42
59
  export default class StateMachineModel {
43
- constructor(pAST) {
44
- this._flattenedStates = flattenStates(pAST.states || []);
45
- this._flattenedTransitions = flattenTransitions(pAST);
60
+ /**
61
+ * @param {import("../types/state-machine-cat").IStateMachine} pStateMachine
62
+ */
63
+ constructor(pStateMachine) {
64
+ this._flattenedStates = flattenStates(pStateMachine.states || []);
65
+ this._flattenedTransitions = flattenTransitions(pStateMachine);
46
66
  }
47
-
67
+ /**
68
+ * @returns {import("../types/state-machine-cat").ITransition[]}
69
+ */
48
70
  get flattenedTransitions() {
49
71
  return this._flattenedTransitions;
50
72
  }
51
73
 
74
+ /**
75
+ * @param {string} pName
76
+ * @returns {any} // IFlattenedState
77
+ */
52
78
  findStateByName(pName) {
53
79
  return this._flattenedStates.find((pState) => pState.name === pName);
54
80
  }
55
81
 
82
+ /**
83
+ * @param {import("../types/state-machine-cat").StateType[]} pTypes
84
+ * @returns {any} // IFlattenedState
85
+ */
56
86
  findStatesByTypes(pTypes) {
57
87
  return this._flattenedStates.filter((pState) =>
58
88
  pTypes.includes(pState.type)
59
89
  );
60
90
  }
61
91
 
92
+ /**
93
+ * @param {string} pStateName
94
+ * @returns {import("../types/state-machine-cat").ITransition[]}
95
+ */
62
96
  findExternalSelfTransitions(pStateName) {
63
97
  return this._flattenedTransitions.filter(
64
98
  (pTransition) =>
@@ -68,12 +102,20 @@ export default class StateMachineModel {
68
102
  );
69
103
  }
70
104
 
105
+ /**
106
+ * @param {string} pFromStateName
107
+ * @returns {import("../types/state-machine-cat").ITransition[]}
108
+ */
71
109
  findTransitionsByFrom(pFromStateName) {
72
110
  return this._flattenedTransitions.filter(
73
111
  (pTransition) => pTransition.from === pFromStateName
74
112
  );
75
113
  }
76
114
 
115
+ /**
116
+ * @param {string} pToStateName
117
+ * @returns {import("../types/state-machine-cat").ITransition[]}
118
+ */
77
119
  findTransitionsByTo(pToStateName) {
78
120
  return this._flattenedTransitions.filter(
79
121
  (pTransition) => pTransition.to === pToStateName
@@ -1,14 +1,31 @@
1
+ // @ts-check
1
2
  /* eslint-disable security/detect-object-injection */
2
3
  import cloneDeep from "lodash/cloneDeep.js";
3
4
  import reject from "lodash/reject.js";
4
5
  import StateMachineModel from "../state-machine-model.mjs";
5
6
  import utl from "./utl.mjs";
6
7
 
8
+ /**
9
+ * @typedef {{[stateName: string]: import("../../types/state-machine-cat.js").ITransition[]}} ITransitionMap
10
+ */
11
+
12
+ /**
13
+ * @param {string|undefined} pIncomingThing
14
+ * @param {string} pOutgoingThing
15
+ * @param {string} pJoinChar
16
+ * @returns {string}
17
+ */
7
18
  function fuseTransitionAttribute(pIncomingThing, pOutgoingThing, pJoinChar) {
8
19
  return pIncomingThing
9
20
  ? `${pIncomingThing}${pJoinChar}${pOutgoingThing}`
10
21
  : pOutgoingThing;
11
22
  }
23
+
24
+ /**
25
+ * @param {import("../../types/state-machine-cat.js").ITransition} pIncomingTransition
26
+ * @param {import("../../types/state-machine-cat.js").ITransition} pOutgoingTransition
27
+ * @returns {import("../../types/state-machine-cat.js").ITransition}
28
+ */
12
29
  function fuseIncomingToOutgoing(pIncomingTransition, pOutgoingTransition) {
13
30
  // in:
14
31
  // a => ]: event [condition]/ action;
@@ -19,6 +36,7 @@ function fuseIncomingToOutgoing(pIncomingTransition, pOutgoingTransition) {
19
36
  //
20
37
  // events and conditions are illegal on transitions outgoing
21
38
  // from forks, so we ignore them
39
+ /** @type {import("../../types/state-machine-cat.js").ITransition} */
22
40
  const lReturnValue = {
23
41
  ...pIncomingTransition,
24
42
  ...pOutgoingTransition,
@@ -44,27 +62,50 @@ function fuseIncomingToOutgoing(pIncomingTransition, pOutgoingTransition) {
44
62
  return lReturnValue;
45
63
  }
46
64
 
65
+ /**
66
+ * @param {import("../../types/state-machine-cat.js").ITransition[]} pTransitions
67
+ * @param {string[]} pPseudoStateNames
68
+ * @param {ITransitionMap} pOutgoingTransitionMap
69
+ * @returns {import("../../types/state-machine-cat.js").ITransition[]}
70
+ */
47
71
  function fuseTransitions(
48
72
  pTransitions,
49
73
  pPseudoStateNames,
50
74
  pOutgoingTransitionMap
51
75
  ) {
52
- return pTransitions.reduce((pAll, pTransition) => {
53
- pPseudoStateNames.forEach((pStateName, pIndex) => {
54
- if (pStateName === pTransition.to && pOutgoingTransitionMap[pStateName]) {
55
- pAll = pAll.concat(
56
- pOutgoingTransitionMap[pStateName].map((pOutgoingTransition) =>
57
- fuseIncomingToOutgoing(pTransition, pOutgoingTransition)
58
- )
59
- );
60
- } else {
61
- pAll = pIndex === 0 ? pAll.concat(pTransition) : pAll;
62
- }
63
- });
64
- return pAll;
65
- }, []);
76
+ return pTransitions.reduce(
77
+ /**
78
+ * @param {import("../../types/state-machine-cat.js").ITransition[]} pAll
79
+ * @param {import("../../types/state-machine-cat.js").ITransition} pTransition
80
+ * @returns {import("../../types/state-machine-cat.js").ITransition[]}
81
+ */
82
+ (pAll, pTransition) => {
83
+ pPseudoStateNames.forEach((pStateName, pIndex) => {
84
+ if (
85
+ pStateName === pTransition.to &&
86
+ pOutgoingTransitionMap[pStateName]
87
+ ) {
88
+ pAll = pAll.concat(
89
+ pOutgoingTransitionMap[pStateName].map((pOutgoingTransition) =>
90
+ fuseIncomingToOutgoing(pTransition, pOutgoingTransition)
91
+ )
92
+ );
93
+ } else {
94
+ pAll = pIndex === 0 ? pAll.concat(pTransition) : pAll;
95
+ }
96
+ });
97
+ return pAll;
98
+ },
99
+ []
100
+ );
66
101
  }
67
102
 
103
+ /**
104
+ * @param {import("../../types/state-machine-cat.js").IStateMachine} pMachine
105
+ * @param {string[]} pPseudoStateNames
106
+ * @param {ITransitionMap} pOutgoingTransitionMap
107
+ * @returns {import("../../types/state-machine-cat.js").IStateMachine}
108
+ */
68
109
  function deSugarPseudoStates(
69
110
  pMachine,
70
111
  pPseudoStateNames,
@@ -96,6 +137,11 @@ function deSugarPseudoStates(
96
137
  return lMachine;
97
138
  }
98
139
 
140
+ /**
141
+ * @param {import("../../types/state-machine-cat.js").IStateMachine} pMachine
142
+ * @param {string[]} pStateNames
143
+ * @returns {import("../../types/state-machine-cat.js").IStateMachine}
144
+ */
99
145
  function removeStatesCascading(pMachine, pStateNames) {
100
146
  const lMachine = cloneDeep(pMachine);
101
147
 
@@ -142,19 +188,22 @@ function removeStatesCascading(pMachine, pStateNames) {
142
188
  * b => d;
143
189
  * ```
144
190
  *
145
- * @param {IStateMachine} pMachine The state machine still containing forks
146
- * @param {StateType[]} pDesugarableStates array of de-sugarable states
147
- * @returns {IStateMachine} the transformed state machine
191
+ * @param {import("../../types/state-machine-cat.js").IStateMachine} pMachine The state machine still containing forks
192
+ * @param {import("../../types/state-machine-cat.js").StateType[]} pDesugarableStates array of de-sugarable states
193
+ * @returns {import("../../types/state-machine-cat.js").IStateMachine} the transformed state machine
148
194
  */
149
195
  export default (
150
196
  pMachine,
151
197
  pDesugarableStates = ["fork", "junction", "choice"]
152
198
  ) => {
153
199
  const lModel = new StateMachineModel(pMachine);
200
+
201
+ /** @type {string[]} */
154
202
  const lPseudoStateNames = lModel
155
203
  .findStatesByTypes(pDesugarableStates)
156
- .map((pState) => pState.name);
204
+ .map(({ name }) => name);
157
205
 
206
+ /** @type {ITransitionMap} */
158
207
  const lOutgoingTransitionMap = lPseudoStateNames.reduce(
159
208
  (pAll, pStateName) => {
160
209
  pAll[pStateName] = lModel.findTransitionsByFrom(pStateName);
@@ -1,3 +1,11 @@
1
+ // @ts-check
2
+ /**
3
+ *
4
+ * @param {string|undefined} pEvent
5
+ * @param {string|undefined} pCond
6
+ * @param {string|undefined} pActions
7
+ * @returns {string}
8
+ */
1
9
  function formatLabel(pEvent, pCond, pActions) {
2
10
  let lReturnValue = "";
3
11
 
package/src/version.mjs CHANGED
@@ -1 +1,2 @@
1
- export const version = "10.1.1";
1
+ // generated by tools/get-version.mjs - edits will be overwritten
2
+ export const version = "10.1.3";