state-machine-cat 10.1.8 → 10.1.10

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.
@@ -1,252 +0,0 @@
1
- /* eslint-disable security/detect-object-injection */
2
- import fastxml from "fast-xml-parser";
3
- import he from "he";
4
- import castArray from "lodash/castArray.js";
5
- import utl from "../../transform/utl.mjs";
6
- import parserHelpers from "../parser-helpers.mjs";
7
- import { normalizeMachine } from "./normalize-machine.mjs";
8
-
9
- const formatLabel = utl.formatLabel;
10
-
11
- function extractActions(pState, pActionType) {
12
- return castArray(pState[pActionType]).map((pAction) => ({
13
- type: pActionType === "onexit" ? "exit" : "entry",
14
- body: he.decode(pAction).trim(),
15
- }));
16
- }
17
-
18
- function extractActionsFromInvokes(pInvokeTriggers) {
19
- return castArray(pInvokeTriggers).map((pInvokeTrigger) => {
20
- const lId = he.decode(pInvokeTrigger.id || "").trim();
21
-
22
- return {
23
- type: "activity",
24
- body: lId || he.decode(pInvokeTrigger || "").trim(),
25
- };
26
- });
27
- }
28
-
29
- /**
30
- * @param {import("./scxml").INormalizedSCXMLState} pState
31
- * @returns {{type: string; body: string;}[]}
32
- */
33
-
34
- /**
35
- * @param {import("./scxml").INormalizedSCXMLState} pState
36
- * @returns {any[]}
37
- */
38
- function deriveActions(pState) {
39
- let lReturnValue = [];
40
-
41
- if (pState.onentry) {
42
- lReturnValue = lReturnValue.concat(extractActions(pState, "onentry"));
43
- }
44
- if (pState.invoke) {
45
- lReturnValue = lReturnValue.concat(
46
- extractActionsFromInvokes(pState.invoke)
47
- );
48
- }
49
- if (pState.onexit) {
50
- lReturnValue = lReturnValue.concat(extractActions(pState, "onexit"));
51
- }
52
- return lReturnValue;
53
- }
54
-
55
- /**
56
- * @param {import("../../..").StateType} pType
57
- * param {import("./scxml").ISCXMLHistoryState} pState
58
- * @param {any} pState
59
- * @returns {import("../../..").StateType}
60
- */
61
- function deriveStateType(pType, pState) {
62
- return pType === "history" && pState.type === "deep" ? "deephistory" : pType;
63
- }
64
-
65
- /**
66
- * @param {import("../../../types/state-machine-cat").StateType} pType
67
- * returns {(pState: import("./scxml").INormalizedSCXMLState) => import("../../..").IState}
68
- * @returns {(any) => import("../../..").IState}
69
- */
70
- function mapState(pType) {
71
- return (pState) => {
72
- /** @type {import("../../../types/state-machine-cat").IState} */
73
- const lReturnValue = {
74
- name: pState.id,
75
- type: deriveStateType(pType, pState),
76
- };
77
-
78
- if (parserHelpers.getStateType(pState.id) !== lReturnValue.type) {
79
- lReturnValue.typeExplicitlySet = true;
80
- }
81
- if (pState.onentry || pState.onexit || pState.invoke) {
82
- lReturnValue.actions = deriveActions(pState);
83
- }
84
- if (
85
- Object.keys(pState).some((pKey) =>
86
- ["initial", "state", "history", "parallel", "final"].includes(pKey)
87
- )
88
- ) {
89
- // recursion, so ...
90
- // eslint-disable-next-line no-use-before-define
91
- lReturnValue.statemachine = mapMachine(pState);
92
- }
93
- return lReturnValue;
94
- };
95
- }
96
-
97
- /**
98
- * @param {import("./scxml").ISCXMLTransition} pTransition
99
- * @returns {{event?: string; cond?: string; action?: string; type?: string;}}
100
- */
101
- function extractTransitionAttributesFromObject(pTransition) {
102
- const lReturnValue = {};
103
-
104
- if (pTransition.event) {
105
- // SCXML uses spaces to distinguish multiple events
106
- // the smcat ast uses linebreaks
107
- lReturnValue.event = pTransition.event.split(/\s+/).join("\n");
108
- }
109
- if (pTransition.cond) {
110
- lReturnValue.cond = pTransition.cond;
111
- }
112
- if (pTransition["#text"]) {
113
- lReturnValue.action = he.decode(pTransition["#text"]).trim();
114
- }
115
-
116
- if (pTransition.type) {
117
- lReturnValue.type = pTransition.type;
118
- }
119
-
120
- return lReturnValue;
121
- }
122
-
123
- /**
124
- *
125
- * @param {import("./scxml").ISCXMLTransition} pTransition
126
- * @returns {{action?: string; label?: string;event?: string; cond?: string; type?: string}}
127
- */
128
- function extractTransitionAttributes(pTransition) {
129
- const lReturnValue = {};
130
-
131
- if (typeof pTransition === "string") {
132
- lReturnValue.action = he.decode(pTransition).trim();
133
- } else {
134
- Object.assign(
135
- lReturnValue,
136
- extractTransitionAttributesFromObject(pTransition)
137
- );
138
- }
139
-
140
- const lLabel = formatLabel(
141
- lReturnValue.event,
142
- lReturnValue.cond,
143
- lReturnValue.action
144
- );
145
-
146
- if (lLabel) {
147
- lReturnValue.label = lLabel;
148
- }
149
-
150
- return lReturnValue;
151
- }
152
-
153
- /**
154
- * @param {import("./scxml").INormalizedSCXMLState} pState
155
- */
156
- function reduceTransition(pState) {
157
- /**
158
- * @param {import("./scxml").ISCXMLTransition[]} pAllTransitions
159
- * @param {import("./scxml").ISCXMLTransition} pTransition
160
- * @returns {import("../../..").ITransition}
161
- */
162
- return (pAllTransitions, pTransition) => {
163
- // in SCXML spaces denote references to multiple states
164
- // => split into multiple transitions
165
- const lTargets = (pTransition?.target ?? pState.id).split(/\s+/);
166
- const lTransitionAttributes = extractTransitionAttributes(pTransition);
167
-
168
- return pAllTransitions.concat(
169
- lTargets.map((pTarget) => ({
170
- from: pState.id,
171
- // a 'target-less transition' is typically
172
- // a self-transition
173
- to: pTarget,
174
- ...lTransitionAttributes,
175
- }))
176
- );
177
- };
178
- }
179
-
180
- /**
181
- * @param {import("./scxml").INormalizedSCXMLState[]} pStates
182
- * @returns {import("../../../types/state-machine-cat").ITransition[]}
183
- */
184
- function extractTransitions(pStates) {
185
- return pStates
186
- .filter((pState) =>
187
- Object.prototype.hasOwnProperty.call(pState, "transition")
188
- )
189
- .reduce(
190
- (pAllTransitions, pThisState) =>
191
- pAllTransitions.concat(
192
- castArray(pThisState.transition).reduce(
193
- reduceTransition(pThisState),
194
- []
195
- )
196
- ),
197
- []
198
- );
199
- }
200
-
201
- /**
202
- * @param {any} pSCXMLStateMachine
203
- * @returns {import("../../..").IStateMachine}
204
- */
205
- function mapMachine(pSCXMLStateMachine) {
206
- const lNormalizedMachine = normalizeMachine(pSCXMLStateMachine);
207
- const lReturnValue = {
208
- states: lNormalizedMachine.initial
209
- .map(mapState("initial"))
210
- .concat(lNormalizedMachine.state.map(mapState("regular")))
211
- .concat(lNormalizedMachine.parallel.map(mapState("parallel")))
212
- .concat(lNormalizedMachine.history.map(mapState("history")))
213
- .concat(lNormalizedMachine.final.map(mapState("final"))),
214
- };
215
-
216
- const lTransitions = extractTransitions(lNormalizedMachine.initial)
217
- .concat(extractTransitions(lNormalizedMachine.state))
218
- .concat(extractTransitions(lNormalizedMachine.parallel));
219
-
220
- if (lTransitions.length > 0) {
221
- lReturnValue.transitions = lTransitions;
222
- }
223
- return lReturnValue;
224
- }
225
-
226
- /**
227
- * Parses SCXML into a state machine AST.
228
- *
229
- * @param {string} pSCXMLString The SCXML to parse
230
- * @returns {import("../../../types/state-machine-cat").IStateMachine} state machine AST
231
- */
232
- export function parse(pSCXMLString) {
233
- const lTrimmedSCXMLString = pSCXMLString.trim();
234
-
235
- if (fastxml.validate(lTrimmedSCXMLString) === true) {
236
- /** @type {import("./scxml").ISCXMLAsJSON} */
237
- const lXMLAsJSON = fastxml.parse(lTrimmedSCXMLString, {
238
- attributeNamePrefix: "",
239
- ignoreAttributes: false,
240
- tagValueProcessor: (pTagValue) => he.decode(pTagValue),
241
- stopNodes: ["onentry", "onexit", "transition"],
242
- });
243
-
244
- return mapMachine(
245
- lXMLAsJSON?.scxml ?? {
246
- xmlns: "http://www.w3.org/2005/07/scxml",
247
- version: "1.0",
248
- }
249
- );
250
- }
251
- throw new Error("That doesn't look like valid xml ...\n");
252
- }