@aranzatech/diagrams-bpmn 0.1.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/dist/chunk-23B2IGK5.js +24 -0
- package/dist/chunk-23B2IGK5.js.map +1 -0
- package/dist/chunk-3AFZDIMQ.js +286 -0
- package/dist/chunk-3AFZDIMQ.js.map +1 -0
- package/dist/chunk-4OAEWYYU.js +579 -0
- package/dist/chunk-4OAEWYYU.js.map +1 -0
- package/dist/chunk-57LA2WSJ.js +476 -0
- package/dist/chunk-57LA2WSJ.js.map +1 -0
- package/dist/chunk-6TUC5QX5.js +491 -0
- package/dist/chunk-6TUC5QX5.js.map +1 -0
- package/dist/chunk-MLUJKUTG.js +86 -0
- package/dist/chunk-MLUJKUTG.js.map +1 -0
- package/dist/chunk-NXMUX67A.js +1443 -0
- package/dist/chunk-NXMUX67A.js.map +1 -0
- package/dist/edges/index.cjs +300 -0
- package/dist/edges/index.cjs.map +1 -0
- package/dist/edges/index.d.cts +17 -0
- package/dist/edges/index.d.ts +17 -0
- package/dist/edges/index.js +4 -0
- package/dist/edges/index.js.map +1 -0
- package/dist/elements/index.cjs +587 -0
- package/dist/elements/index.cjs.map +1 -0
- package/dist/elements/index.d.cts +20 -0
- package/dist/elements/index.d.ts +20 -0
- package/dist/elements/index.js +4 -0
- package/dist/elements/index.js.map +1 -0
- package/dist/index.cjs +3442 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +67 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/nodes/index.cjs +1487 -0
- package/dist/nodes/index.cjs.map +1 -0
- package/dist/nodes/index.d.cts +45 -0
- package/dist/nodes/index.d.ts +45 -0
- package/dist/nodes/index.js +4 -0
- package/dist/nodes/index.js.map +1 -0
- package/dist/simulation/index.cjs +483 -0
- package/dist/simulation/index.cjs.map +1 -0
- package/dist/simulation/index.d.cts +62 -0
- package/dist/simulation/index.d.ts +62 -0
- package/dist/simulation/index.js +3 -0
- package/dist/simulation/index.js.map +1 -0
- package/dist/types-CxzazgBX.d.cts +111 -0
- package/dist/types-CxzazgBX.d.ts +111 -0
- package/dist/xml/index.cjs +1068 -0
- package/dist/xml/index.cjs.map +1 -0
- package/dist/xml/index.d.cts +24 -0
- package/dist/xml/index.d.ts +24 -0
- package/dist/xml/index.js +4 -0
- package/dist/xml/index.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/simulation/evaluator.ts
|
|
4
|
+
function parseValue(raw) {
|
|
5
|
+
if (raw === "true") return true;
|
|
6
|
+
if (raw === "false") return false;
|
|
7
|
+
if (raw.startsWith("'") && raw.endsWith("'") || raw.startsWith('"') && raw.endsWith('"'))
|
|
8
|
+
return raw.slice(1, -1);
|
|
9
|
+
const n = Number(raw);
|
|
10
|
+
return isNaN(n) ? raw : n;
|
|
11
|
+
}
|
|
12
|
+
function evalCondition(expr, variables) {
|
|
13
|
+
const body = expr.trim().replace(/^\$\{|\}$/g, "").trim();
|
|
14
|
+
if (!body) return false;
|
|
15
|
+
if (body.startsWith("!")) {
|
|
16
|
+
const inner = body.slice(1).trim();
|
|
17
|
+
return !Boolean(variables[inner]);
|
|
18
|
+
}
|
|
19
|
+
const neq = body.match(/^(\w+)\s*!=\s*(.+)$/);
|
|
20
|
+
if (neq) return String(variables[neq[1].trim()]) !== String(parseValue(neq[2].trim()));
|
|
21
|
+
const eq = body.match(/^(\w+)\s*==\s*(.+)$/);
|
|
22
|
+
if (eq) {
|
|
23
|
+
const lhs = variables[eq[1].trim()];
|
|
24
|
+
const rhs = parseValue(eq[2].trim());
|
|
25
|
+
return lhs == rhs;
|
|
26
|
+
}
|
|
27
|
+
const gte = body.match(/^(\w+)\s*>=\s*(-?\d+\.?\d*)$/);
|
|
28
|
+
if (gte) return Number(variables[gte[1].trim()]) >= Number(gte[2]);
|
|
29
|
+
const lte = body.match(/^(\w+)\s*<=\s*(-?\d+\.?\d*)$/);
|
|
30
|
+
if (lte) return Number(variables[lte[1].trim()]) <= Number(lte[2]);
|
|
31
|
+
const gt = body.match(/^(\w+)\s*>\s*(-?\d+\.?\d*)$/);
|
|
32
|
+
if (gt) return Number(variables[gt[1].trim()]) > Number(gt[2]);
|
|
33
|
+
const lt = body.match(/^(\w+)\s*<\s*(-?\d+\.?\d*)$/);
|
|
34
|
+
if (lt) return Number(variables[lt[1].trim()]) < Number(lt[2]);
|
|
35
|
+
return Boolean(variables[body]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/simulation/index.ts
|
|
39
|
+
function seqOut(diagram, nodeId) {
|
|
40
|
+
return diagram.edges.filter((e) => e.type === "sequenceFlow" && e.source === nodeId);
|
|
41
|
+
}
|
|
42
|
+
function seqIn(diagram, nodeId) {
|
|
43
|
+
return diagram.edges.filter((e) => e.type === "sequenceFlow" && e.target === nodeId);
|
|
44
|
+
}
|
|
45
|
+
function nodeById(diagram, id) {
|
|
46
|
+
return diagram.nodes.find((n) => n.id === id);
|
|
47
|
+
}
|
|
48
|
+
function boundaryEventsOf(diagram, hostId) {
|
|
49
|
+
return diagram.nodes.filter((n) => n.type === "BoundaryEvent" && n.attachedToRef === hostId);
|
|
50
|
+
}
|
|
51
|
+
var _tokenCounter = 0;
|
|
52
|
+
function nextTokenId() {
|
|
53
|
+
return `tok_${++_tokenCounter}`;
|
|
54
|
+
}
|
|
55
|
+
var GATEWAY_TYPES = /* @__PURE__ */ new Set([
|
|
56
|
+
"ExclusiveGateway",
|
|
57
|
+
"InclusiveGateway",
|
|
58
|
+
"ParallelGateway",
|
|
59
|
+
"ComplexGateway",
|
|
60
|
+
"EventBasedGateway"
|
|
61
|
+
]);
|
|
62
|
+
var TASK_TYPES = /* @__PURE__ */ new Set([
|
|
63
|
+
"Task",
|
|
64
|
+
"UserTask",
|
|
65
|
+
"ServiceTask",
|
|
66
|
+
"ScriptTask",
|
|
67
|
+
"ManualTask",
|
|
68
|
+
"BusinessRuleTask",
|
|
69
|
+
"ReceiveTask",
|
|
70
|
+
"SendTask",
|
|
71
|
+
"CallActivity"
|
|
72
|
+
]);
|
|
73
|
+
function isAutomatic(nodeType) {
|
|
74
|
+
return nodeType === "StartEvent" || nodeType === "EndEvent" || nodeType === "IntermediateThrowEvent" || GATEWAY_TYPES.has(nodeType);
|
|
75
|
+
}
|
|
76
|
+
function isManual(nodeType) {
|
|
77
|
+
return TASK_TYPES.has(nodeType) || nodeType === "IntermediateCatchEvent" || nodeType === "BoundaryEvent";
|
|
78
|
+
}
|
|
79
|
+
function isSubProcess(nodeType) {
|
|
80
|
+
return nodeType === "SubProcess" || nodeType === "Transaction" || nodeType === "AdHocSubProcess";
|
|
81
|
+
}
|
|
82
|
+
function getScopeId(diagram, nodeId) {
|
|
83
|
+
const node = nodeById(diagram, nodeId);
|
|
84
|
+
if (!node?.parentId) return "root";
|
|
85
|
+
const parent = nodeById(diagram, node.parentId);
|
|
86
|
+
return parent && isSubProcess(parent.type) ? node.parentId : "root";
|
|
87
|
+
}
|
|
88
|
+
function withLog(state, entry) {
|
|
89
|
+
return { ...state, log: [...state.log, { ...entry, step: state.step }] };
|
|
90
|
+
}
|
|
91
|
+
function disperseToTargets(diagram, state, sourceId, consumedTokenId) {
|
|
92
|
+
const outEdges = seqOut(diagram, sourceId);
|
|
93
|
+
if (outEdges.length === 0) return state;
|
|
94
|
+
let next = {
|
|
95
|
+
...state,
|
|
96
|
+
tokens: consumedTokenId !== null ? state.tokens.filter((t) => t.id !== consumedTokenId) : state.tokens
|
|
97
|
+
};
|
|
98
|
+
for (const edge of outEdges) {
|
|
99
|
+
const target = nodeById(diagram, edge.target);
|
|
100
|
+
if (!target) continue;
|
|
101
|
+
const newToken = {
|
|
102
|
+
id: nextTokenId(),
|
|
103
|
+
elementId: edge.target,
|
|
104
|
+
scopeId: getScopeId(diagram, edge.target)
|
|
105
|
+
};
|
|
106
|
+
next = {
|
|
107
|
+
...next,
|
|
108
|
+
tokens: [...next.tokens, newToken]
|
|
109
|
+
};
|
|
110
|
+
next = withLog(next, {
|
|
111
|
+
type: "created",
|
|
112
|
+
elementId: edge.target,
|
|
113
|
+
tokenId: newToken.id,
|
|
114
|
+
message: `Token created at "${target.name ?? edge.target}".`
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return next;
|
|
118
|
+
}
|
|
119
|
+
function enterSubProcess(diagram, state, subProcNode) {
|
|
120
|
+
const childStarts = diagram.nodes.filter(
|
|
121
|
+
(n) => n.type === "StartEvent" && n.parentId === subProcNode.id
|
|
122
|
+
);
|
|
123
|
+
let next = {
|
|
124
|
+
...state,
|
|
125
|
+
enteredScopes: [...state.enteredScopes, subProcNode.id]
|
|
126
|
+
};
|
|
127
|
+
for (const startNode of childStarts) {
|
|
128
|
+
const newToken = {
|
|
129
|
+
id: nextTokenId(),
|
|
130
|
+
elementId: startNode.id,
|
|
131
|
+
scopeId: subProcNode.id
|
|
132
|
+
};
|
|
133
|
+
next = {
|
|
134
|
+
...next,
|
|
135
|
+
tokens: [...next.tokens, newToken]
|
|
136
|
+
};
|
|
137
|
+
next = withLog(next, {
|
|
138
|
+
type: "created",
|
|
139
|
+
elementId: startNode.id,
|
|
140
|
+
tokenId: newToken.id,
|
|
141
|
+
message: `SubProcess "${subProcNode.name ?? subProcNode.id}" entered \u2014 token at "${startNode.name ?? startNode.id}".`
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return next;
|
|
145
|
+
}
|
|
146
|
+
function fireAutomatic(diagram, state, token) {
|
|
147
|
+
const node = nodeById(diagram, token.elementId);
|
|
148
|
+
if (!node) return state;
|
|
149
|
+
const { type } = node;
|
|
150
|
+
const vars = state.variables;
|
|
151
|
+
if (type === "EndEvent") {
|
|
152
|
+
let next = {
|
|
153
|
+
...state,
|
|
154
|
+
tokens: state.tokens.filter((t) => t.id !== token.id)
|
|
155
|
+
};
|
|
156
|
+
next = withLog(next, {
|
|
157
|
+
type: "consumed",
|
|
158
|
+
elementId: node.id,
|
|
159
|
+
tokenId: token.id,
|
|
160
|
+
message: `Token consumed at end event "${node.name ?? node.id}".`
|
|
161
|
+
});
|
|
162
|
+
return next;
|
|
163
|
+
}
|
|
164
|
+
if (type === "StartEvent" || type === "IntermediateThrowEvent") {
|
|
165
|
+
let next = withLog(state, {
|
|
166
|
+
type: "fired",
|
|
167
|
+
elementId: node.id,
|
|
168
|
+
tokenId: token.id,
|
|
169
|
+
message: `"${node.name ?? node.id}" (${type}) fired.`
|
|
170
|
+
});
|
|
171
|
+
return disperseToTargets(diagram, next, node.id, token.id);
|
|
172
|
+
}
|
|
173
|
+
if (type === "ExclusiveGateway") {
|
|
174
|
+
const incoming = seqIn(diagram, node.id);
|
|
175
|
+
if (incoming.length >= 2) {
|
|
176
|
+
let next2 = withLog(state, {
|
|
177
|
+
type: "joined",
|
|
178
|
+
elementId: node.id,
|
|
179
|
+
tokenId: token.id,
|
|
180
|
+
message: `ExclusiveGateway "${node.name ?? node.id}" join \u2014 token passes through.`
|
|
181
|
+
});
|
|
182
|
+
return disperseToTargets(diagram, next2, node.id, token.id);
|
|
183
|
+
}
|
|
184
|
+
const outEdges = seqOut(diagram, node.id);
|
|
185
|
+
const chosen = outEdges.find(
|
|
186
|
+
(e) => e.conditionExpression && !e.isDefault && evalCondition(e.conditionExpression, vars)
|
|
187
|
+
) ?? outEdges.find((e) => e.isDefault) ?? outEdges[0];
|
|
188
|
+
if (!chosen) return state;
|
|
189
|
+
const target = nodeById(diagram, chosen.target);
|
|
190
|
+
if (!target) return state;
|
|
191
|
+
const newToken = {
|
|
192
|
+
id: nextTokenId(),
|
|
193
|
+
elementId: chosen.target,
|
|
194
|
+
scopeId: getScopeId(diagram, chosen.target)
|
|
195
|
+
};
|
|
196
|
+
let next = {
|
|
197
|
+
...state,
|
|
198
|
+
tokens: [...state.tokens.filter((t) => t.id !== token.id), newToken]
|
|
199
|
+
};
|
|
200
|
+
next = withLog(next, {
|
|
201
|
+
type: "fired",
|
|
202
|
+
elementId: node.id,
|
|
203
|
+
tokenId: token.id,
|
|
204
|
+
message: `ExclusiveGateway "${node.name ?? node.id}" split \u2192 "${target.name ?? chosen.target}".`
|
|
205
|
+
});
|
|
206
|
+
return next;
|
|
207
|
+
}
|
|
208
|
+
if (type === "InclusiveGateway") {
|
|
209
|
+
const incoming = seqIn(diagram, node.id);
|
|
210
|
+
if (incoming.length >= 2) {
|
|
211
|
+
let next2 = withLog(state, {
|
|
212
|
+
type: "joined",
|
|
213
|
+
elementId: node.id,
|
|
214
|
+
tokenId: token.id,
|
|
215
|
+
message: `InclusiveGateway "${node.name ?? node.id}" join.`
|
|
216
|
+
});
|
|
217
|
+
return disperseToTargets(diagram, next2, node.id, token.id);
|
|
218
|
+
}
|
|
219
|
+
const outEdges = seqOut(diagram, node.id);
|
|
220
|
+
const matching = outEdges.filter(
|
|
221
|
+
(e) => e.conditionExpression && !e.isDefault && evalCondition(e.conditionExpression, vars)
|
|
222
|
+
);
|
|
223
|
+
const activePaths = matching.length > 0 ? matching : outEdges.filter((e) => e.isDefault);
|
|
224
|
+
const paths = activePaths.length > 0 ? activePaths : outEdges;
|
|
225
|
+
let next = withLog(state, {
|
|
226
|
+
type: "split",
|
|
227
|
+
elementId: node.id,
|
|
228
|
+
tokenId: token.id,
|
|
229
|
+
message: `InclusiveGateway "${node.name ?? node.id}" split \u2192 ${paths.length} path(s).`
|
|
230
|
+
});
|
|
231
|
+
next = { ...next, tokens: next.tokens.filter((t) => t.id !== token.id) };
|
|
232
|
+
for (const edge of paths) {
|
|
233
|
+
const tgt = nodeById(diagram, edge.target);
|
|
234
|
+
if (!tgt) continue;
|
|
235
|
+
const newToken = {
|
|
236
|
+
id: nextTokenId(),
|
|
237
|
+
elementId: edge.target,
|
|
238
|
+
scopeId: getScopeId(diagram, edge.target)
|
|
239
|
+
};
|
|
240
|
+
next = { ...next, tokens: [...next.tokens, newToken] };
|
|
241
|
+
next = withLog(next, {
|
|
242
|
+
type: "created",
|
|
243
|
+
elementId: edge.target,
|
|
244
|
+
tokenId: newToken.id,
|
|
245
|
+
message: `Token created at "${tgt.name ?? edge.target}".`
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
return next;
|
|
249
|
+
}
|
|
250
|
+
if (type === "ParallelGateway") {
|
|
251
|
+
const incoming = seqIn(diagram, node.id);
|
|
252
|
+
if (incoming.length >= 2) {
|
|
253
|
+
const atGateway = state.tokens.filter((t) => t.elementId === node.id);
|
|
254
|
+
if (atGateway.length < incoming.length) {
|
|
255
|
+
return withLog(state, {
|
|
256
|
+
type: "blocked",
|
|
257
|
+
elementId: node.id,
|
|
258
|
+
tokenId: token.id,
|
|
259
|
+
message: `ParallelGateway "${node.name ?? node.id}" waiting for ${incoming.length - atGateway.length} more token(s).`
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
const consumeIds = new Set(atGateway.map((t) => t.id));
|
|
263
|
+
let next2 = {
|
|
264
|
+
...state,
|
|
265
|
+
tokens: state.tokens.filter((t) => !consumeIds.has(t.id))
|
|
266
|
+
};
|
|
267
|
+
next2 = withLog(next2, {
|
|
268
|
+
type: "joined",
|
|
269
|
+
elementId: node.id,
|
|
270
|
+
message: `ParallelGateway "${node.name ?? node.id}" join fired \u2014 all paths synchronized.`
|
|
271
|
+
});
|
|
272
|
+
return disperseToTargets(diagram, next2, node.id, null);
|
|
273
|
+
}
|
|
274
|
+
let next = withLog(state, {
|
|
275
|
+
type: "split",
|
|
276
|
+
elementId: node.id,
|
|
277
|
+
tokenId: token.id,
|
|
278
|
+
message: `ParallelGateway "${node.name ?? node.id}" split \u2192 ${seqOut(diagram, node.id).length} paths.`
|
|
279
|
+
});
|
|
280
|
+
return disperseToTargets(diagram, next, node.id, token.id);
|
|
281
|
+
}
|
|
282
|
+
if (type === "EventBasedGateway") {
|
|
283
|
+
let next = withLog(state, {
|
|
284
|
+
type: "split",
|
|
285
|
+
elementId: node.id,
|
|
286
|
+
tokenId: token.id,
|
|
287
|
+
message: `EventBasedGateway "${node.name ?? node.id}" waiting \u2014 ${seqOut(diagram, node.id).length} competing event(s).`
|
|
288
|
+
});
|
|
289
|
+
return disperseToTargets(diagram, next, node.id, token.id);
|
|
290
|
+
}
|
|
291
|
+
if (type === "ComplexGateway") {
|
|
292
|
+
const outEdges = seqOut(diagram, node.id);
|
|
293
|
+
const chosen = outEdges[0];
|
|
294
|
+
if (!chosen) return state;
|
|
295
|
+
const newToken = {
|
|
296
|
+
id: nextTokenId(),
|
|
297
|
+
elementId: chosen.target,
|
|
298
|
+
scopeId: getScopeId(diagram, chosen.target)
|
|
299
|
+
};
|
|
300
|
+
let next = {
|
|
301
|
+
...state,
|
|
302
|
+
tokens: [...state.tokens.filter((t) => t.id !== token.id), newToken]
|
|
303
|
+
};
|
|
304
|
+
next = withLog(next, {
|
|
305
|
+
type: "fired",
|
|
306
|
+
elementId: node.id,
|
|
307
|
+
tokenId: token.id,
|
|
308
|
+
message: `ComplexGateway "${node.name ?? node.id}" fired \u2192 "${chosen.target}".`
|
|
309
|
+
});
|
|
310
|
+
return next;
|
|
311
|
+
}
|
|
312
|
+
return state;
|
|
313
|
+
}
|
|
314
|
+
function createSimulation(diagram, initialVariables = {}) {
|
|
315
|
+
_tokenCounter = 0;
|
|
316
|
+
const startEvents = diagram.nodes.filter(
|
|
317
|
+
(n) => n.type === "StartEvent" && !n.parentId
|
|
318
|
+
);
|
|
319
|
+
const tokens = startEvents.map((n) => ({
|
|
320
|
+
id: nextTokenId(),
|
|
321
|
+
elementId: n.id,
|
|
322
|
+
scopeId: "root"
|
|
323
|
+
}));
|
|
324
|
+
const log = startEvents.map((n, i) => ({
|
|
325
|
+
step: 0,
|
|
326
|
+
type: "created",
|
|
327
|
+
elementId: n.id,
|
|
328
|
+
tokenId: tokens[i]?.id,
|
|
329
|
+
message: `Simulation started \u2014 token placed at "${n.name ?? n.id}".`
|
|
330
|
+
}));
|
|
331
|
+
return {
|
|
332
|
+
tokens,
|
|
333
|
+
step: 0,
|
|
334
|
+
status: startEvents.length > 0 ? "running" : "idle",
|
|
335
|
+
log,
|
|
336
|
+
variables: initialVariables,
|
|
337
|
+
enteredScopes: []
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function tick(diagram, state) {
|
|
341
|
+
if (state.status !== "running") return state;
|
|
342
|
+
let current = { ...state, step: state.step + 1 };
|
|
343
|
+
let changed = true;
|
|
344
|
+
let guard = 0;
|
|
345
|
+
while (changed && guard < 1e3) {
|
|
346
|
+
guard++;
|
|
347
|
+
changed = false;
|
|
348
|
+
for (const token of current.tokens) {
|
|
349
|
+
const node = nodeById(diagram, token.elementId);
|
|
350
|
+
if (!node) continue;
|
|
351
|
+
if (isSubProcess(node.type)) {
|
|
352
|
+
if (!current.enteredScopes.includes(node.id)) {
|
|
353
|
+
const childStarts = diagram.nodes.filter(
|
|
354
|
+
(n) => n.type === "StartEvent" && n.parentId === node.id
|
|
355
|
+
);
|
|
356
|
+
if (childStarts.length > 0) {
|
|
357
|
+
current = enterSubProcess(diagram, current, node);
|
|
358
|
+
changed = true;
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
const scopeTokens = current.tokens.filter((t) => t.scopeId === node.id);
|
|
363
|
+
if (scopeTokens.length === 0) {
|
|
364
|
+
let next = withLog(current, {
|
|
365
|
+
type: "fired",
|
|
366
|
+
elementId: node.id,
|
|
367
|
+
tokenId: token.id,
|
|
368
|
+
message: `SubProcess "${node.name ?? node.id}" completed.`
|
|
369
|
+
});
|
|
370
|
+
current = disperseToTargets(diagram, next, node.id, token.id);
|
|
371
|
+
changed = true;
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
if (node.type === "ParallelGateway") {
|
|
378
|
+
const incoming = seqIn(diagram, node.id);
|
|
379
|
+
const atGateway = current.tokens.filter((t) => t.elementId === node.id);
|
|
380
|
+
if (incoming.length >= 2 && atGateway.length < incoming.length) continue;
|
|
381
|
+
}
|
|
382
|
+
if (!isAutomatic(node.type)) continue;
|
|
383
|
+
const prevLen = current.tokens.length;
|
|
384
|
+
const prevIds = new Set(current.tokens.map((t) => t.id));
|
|
385
|
+
current = fireAutomatic(diagram, current, token);
|
|
386
|
+
const same = current.tokens.length === prevLen && [...prevIds].every((id) => current.tokens.some((t) => t.id === id));
|
|
387
|
+
if (!same) {
|
|
388
|
+
changed = true;
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (current.tokens.length === 0) {
|
|
394
|
+
current = { ...current, status: "completed" };
|
|
395
|
+
}
|
|
396
|
+
return current;
|
|
397
|
+
}
|
|
398
|
+
function fire(diagram, state, elementId, variables) {
|
|
399
|
+
if (state.status !== "running") return state;
|
|
400
|
+
const node = nodeById(diagram, elementId);
|
|
401
|
+
if (!node) return state;
|
|
402
|
+
const mergedVars = variables ? { ...state.variables, ...variables } : state.variables;
|
|
403
|
+
if (node.type === "BoundaryEvent") {
|
|
404
|
+
const hostId = node.attachedToRef;
|
|
405
|
+
if (!hostId) return state;
|
|
406
|
+
const hostToken = state.tokens.find((t) => t.elementId === hostId);
|
|
407
|
+
if (!hostToken) return state;
|
|
408
|
+
const isInterrupting = node.isInterrupting !== false;
|
|
409
|
+
let next2 = { ...state, variables: mergedVars, step: state.step + 1 };
|
|
410
|
+
next2 = withLog(next2, {
|
|
411
|
+
type: isInterrupting ? "interrupted" : "fired",
|
|
412
|
+
elementId,
|
|
413
|
+
tokenId: hostToken.id,
|
|
414
|
+
message: `BoundaryEvent "${node.name ?? elementId}" fired (${isInterrupting ? "interrupting" : "non-interrupting"}).`
|
|
415
|
+
});
|
|
416
|
+
if (isInterrupting) {
|
|
417
|
+
next2 = { ...next2, tokens: next2.tokens.filter((t) => t.id !== hostToken.id) };
|
|
418
|
+
}
|
|
419
|
+
next2 = disperseToTargets(diagram, next2, elementId, null);
|
|
420
|
+
return tick(diagram, { ...next2, step: next2.step - 1 });
|
|
421
|
+
}
|
|
422
|
+
const token = state.tokens.find((t) => t.elementId === elementId);
|
|
423
|
+
if (!token) return state;
|
|
424
|
+
if (node.type === "IntermediateCatchEvent") {
|
|
425
|
+
const gwEdge = seqIn(diagram, elementId).find((e) => {
|
|
426
|
+
const src = nodeById(diagram, e.source);
|
|
427
|
+
return src?.type === "EventBasedGateway";
|
|
428
|
+
});
|
|
429
|
+
if (gwEdge) {
|
|
430
|
+
const gw = nodeById(diagram, gwEdge.source);
|
|
431
|
+
if (gw) {
|
|
432
|
+
const siblingTargets = new Set(
|
|
433
|
+
seqOut(diagram, gw.id).map((e) => e.target).filter((id) => id !== elementId)
|
|
434
|
+
);
|
|
435
|
+
state = {
|
|
436
|
+
...state,
|
|
437
|
+
tokens: state.tokens.filter((t) => !siblingTargets.has(t.elementId))
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
let next = { ...state, variables: mergedVars, step: state.step + 1 };
|
|
443
|
+
next = withLog(next, {
|
|
444
|
+
type: "fired",
|
|
445
|
+
elementId,
|
|
446
|
+
tokenId: token.id,
|
|
447
|
+
message: `"${node.name ?? elementId}" (${node.type}) manually fired.`
|
|
448
|
+
});
|
|
449
|
+
next = disperseToTargets(diagram, next, elementId, token.id);
|
|
450
|
+
return tick(diagram, { ...next, step: next.step - 1 });
|
|
451
|
+
}
|
|
452
|
+
function getFireable(diagram, state) {
|
|
453
|
+
if (state.status !== "running") return [];
|
|
454
|
+
const fireable = /* @__PURE__ */ new Set();
|
|
455
|
+
for (const token of state.tokens) {
|
|
456
|
+
const node = nodeById(diagram, token.elementId);
|
|
457
|
+
if (!node) continue;
|
|
458
|
+
if (isManual(node.type)) {
|
|
459
|
+
fireable.add(node.id);
|
|
460
|
+
}
|
|
461
|
+
if (TASK_TYPES.has(node.type)) {
|
|
462
|
+
for (const be of boundaryEventsOf(diagram, node.id)) {
|
|
463
|
+
fireable.add(be.id);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return [...fireable];
|
|
468
|
+
}
|
|
469
|
+
function isCompleted(state) {
|
|
470
|
+
return state.status === "completed";
|
|
471
|
+
}
|
|
472
|
+
function setVariable(state, key, value) {
|
|
473
|
+
return { ...state, variables: { ...state.variables, [key]: value } };
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
exports.createSimulation = createSimulation;
|
|
477
|
+
exports.fire = fire;
|
|
478
|
+
exports.getFireable = getFireable;
|
|
479
|
+
exports.isCompleted = isCompleted;
|
|
480
|
+
exports.setVariable = setVariable;
|
|
481
|
+
exports.tick = tick;
|
|
482
|
+
//# sourceMappingURL=index.cjs.map
|
|
483
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/simulation/evaluator.ts","../../src/simulation/index.ts"],"names":["next"],"mappings":"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","file":"index.cjs","sourcesContent":["export type SimVariables = Record<string, string | number | boolean>;\n\nfunction parseValue(raw: string): string | number | boolean {\n if (raw === \"true\") return true;\n if (raw === \"false\") return false;\n if ((raw.startsWith(\"'\") && raw.endsWith(\"'\")) || (raw.startsWith('\"') && raw.endsWith('\"')))\n return raw.slice(1, -1);\n const n = Number(raw);\n return isNaN(n) ? raw : n;\n}\n\n/**\n * Evaluates a BPMN condition expression (${...}) against a variables map.\n * Supports: bare variable (truthy), ==, !=, >, >=, <, <=, !var\n */\nexport function evalCondition(expr: string, variables: SimVariables): boolean {\n const body = expr.trim().replace(/^\\$\\{|\\}$/g, \"\").trim();\n if (!body) return false;\n\n // Logical NOT: !varName\n if (body.startsWith(\"!\")) {\n const inner = body.slice(1).trim();\n return !Boolean(variables[inner]);\n }\n\n // != comparison\n const neq = body.match(/^(\\w+)\\s*!=\\s*(.+)$/);\n if (neq) return String(variables[neq[1].trim()]) !== String(parseValue(neq[2].trim()));\n\n // == comparison\n const eq = body.match(/^(\\w+)\\s*==\\s*(.+)$/);\n if (eq) {\n const lhs = variables[eq[1].trim()];\n const rhs = parseValue(eq[2].trim());\n // eslint-disable-next-line eqeqeq\n return lhs == rhs;\n }\n\n // >= comparison\n const gte = body.match(/^(\\w+)\\s*>=\\s*(-?\\d+\\.?\\d*)$/);\n if (gte) return Number(variables[gte[1].trim()]) >= Number(gte[2]);\n\n // <= comparison\n const lte = body.match(/^(\\w+)\\s*<=\\s*(-?\\d+\\.?\\d*)$/);\n if (lte) return Number(variables[lte[1].trim()]) <= Number(lte[2]);\n\n // > comparison\n const gt = body.match(/^(\\w+)\\s*>\\s*(-?\\d+\\.?\\d*)$/);\n if (gt) return Number(variables[gt[1].trim()]) > Number(gt[2]);\n\n // < comparison\n const lt = body.match(/^(\\w+)\\s*<\\s*(-?\\d+\\.?\\d*)$/);\n if (lt) return Number(variables[lt[1].trim()]) < Number(lt[2]);\n\n // Bare variable → truthy\n return Boolean(variables[body]);\n}\n","import { evalCondition } from \"./evaluator\";\nexport type { SimVariables } from \"./evaluator\";\n\n// ─── Public types ─────────────────────────────────────────────────────────────\n\nexport interface SimNode {\n id: string;\n type: string;\n name?: string;\n parentId?: string;\n /** BoundaryEvent only — the task/subprocess this event is attached to. */\n attachedToRef?: string;\n /** BoundaryEvent: true = interrupting (default), false = non-interrupting. */\n isInterrupting?: boolean;\n}\n\nexport interface SimEdge {\n id: string;\n type: string;\n source: string;\n target: string;\n conditionExpression?: string;\n isDefault?: boolean;\n}\n\nexport interface SimDiagram {\n nodes: SimNode[];\n edges: SimEdge[];\n}\n\nexport interface SimToken {\n id: string;\n /** The element the token currently occupies. */\n elementId: string;\n /**\n * The subprocess scope this token belongs to.\n * \"root\" for top-level tokens; the subprocess node id for child tokens.\n */\n scopeId: string;\n}\n\nexport type SimStatus = \"idle\" | \"running\" | \"completed\" | \"deadlocked\";\n\nexport type SimLogType =\n | \"created\"\n | \"fired\"\n | \"split\"\n | \"joined\"\n | \"consumed\"\n | \"blocked\"\n | \"deadlocked\"\n | \"interrupted\";\n\nexport interface SimLogEntry {\n step: number;\n type: SimLogType;\n elementId: string;\n tokenId?: string;\n message: string;\n}\n\nexport interface SimulationState {\n tokens: SimToken[];\n step: number;\n status: SimStatus;\n log: SimLogEntry[];\n /** Process-level variables used for gateway condition evaluation. */\n variables: Record<string, string | number | boolean>;\n /** IDs of subprocess nodes whose internal execution has started. */\n enteredScopes: string[];\n}\n\n// ─── Diagram query helpers ────────────────────────────────────────────────────\n\nfunction seqOut(diagram: SimDiagram, nodeId: string): SimEdge[] {\n return diagram.edges.filter((e) => e.type === \"sequenceFlow\" && e.source === nodeId);\n}\n\nfunction seqIn(diagram: SimDiagram, nodeId: string): SimEdge[] {\n return diagram.edges.filter((e) => e.type === \"sequenceFlow\" && e.target === nodeId);\n}\n\nfunction nodeById(diagram: SimDiagram, id: string): SimNode | undefined {\n return diagram.nodes.find((n) => n.id === id);\n}\n\n/** Returns boundary events attached to the given host element. */\nfunction boundaryEventsOf(diagram: SimDiagram, hostId: string): SimNode[] {\n return diagram.nodes.filter((n) => n.type === \"BoundaryEvent\" && n.attachedToRef === hostId);\n}\n\nlet _tokenCounter = 0;\nfunction nextTokenId(): string {\n return `tok_${++_tokenCounter}`;\n}\n\n// ─── Element classification ───────────────────────────────────────────────────\n\nconst GATEWAY_TYPES = new Set([\n \"ExclusiveGateway\",\n \"InclusiveGateway\",\n \"ParallelGateway\",\n \"ComplexGateway\",\n \"EventBasedGateway\",\n]);\n\nconst TASK_TYPES = new Set([\n \"Task\",\n \"UserTask\",\n \"ServiceTask\",\n \"ScriptTask\",\n \"ManualTask\",\n \"BusinessRuleTask\",\n \"ReceiveTask\",\n \"SendTask\",\n \"CallActivity\",\n]);\n\nfunction isAutomatic(nodeType: string): boolean {\n return (\n nodeType === \"StartEvent\" ||\n nodeType === \"EndEvent\" ||\n nodeType === \"IntermediateThrowEvent\" ||\n GATEWAY_TYPES.has(nodeType)\n );\n}\n\nfunction isManual(nodeType: string): boolean {\n return (\n TASK_TYPES.has(nodeType) ||\n nodeType === \"IntermediateCatchEvent\" ||\n nodeType === \"BoundaryEvent\"\n );\n}\n\nfunction isSubProcess(nodeType: string): boolean {\n return (\n nodeType === \"SubProcess\" ||\n nodeType === \"Transaction\" ||\n nodeType === \"AdHocSubProcess\"\n );\n}\n\n// ─── Scope resolution ─────────────────────────────────────────────────────────\n\n/**\n * Determines the scope of a node by checking whether its parent is a SubProcess.\n * Returns \"root\" for top-level nodes or children of Pools/Lanes.\n */\nfunction getScopeId(diagram: SimDiagram, nodeId: string): string {\n const node = nodeById(diagram, nodeId);\n if (!node?.parentId) return \"root\";\n const parent = nodeById(diagram, node.parentId);\n return parent && isSubProcess(parent.type) ? node.parentId : \"root\";\n}\n\n// ─── Core token helpers ───────────────────────────────────────────────────────\n\nfunction withLog(\n state: SimulationState,\n entry: Omit<SimLogEntry, \"step\">,\n): SimulationState {\n return { ...state, log: [...state.log, { ...entry, step: state.step }] };\n}\n\n/**\n * Removes the consumed token and creates new tokens at each outgoing\n * sequence-flow target of sourceId. Each new token inherits the scope\n * determined by the target node's position in the diagram.\n */\nfunction disperseToTargets(\n diagram: SimDiagram,\n state: SimulationState,\n sourceId: string,\n consumedTokenId: string | null,\n): SimulationState {\n const outEdges = seqOut(diagram, sourceId);\n if (outEdges.length === 0) return state;\n\n let next: SimulationState = {\n ...state,\n tokens:\n consumedTokenId !== null\n ? state.tokens.filter((t) => t.id !== consumedTokenId)\n : state.tokens,\n };\n\n for (const edge of outEdges) {\n const target = nodeById(diagram, edge.target);\n if (!target) continue;\n\n const newToken: SimToken = {\n id: nextTokenId(),\n elementId: edge.target,\n scopeId: getScopeId(diagram, edge.target),\n };\n next = {\n ...next,\n tokens: [...next.tokens, newToken],\n };\n next = withLog(next, {\n type: \"created\",\n elementId: edge.target,\n tokenId: newToken.id,\n message: `Token created at \"${target.name ?? edge.target}\".`,\n });\n }\n\n return next;\n}\n\n// ─── SubProcess scope management ─────────────────────────────────────────────\n\nfunction enterSubProcess(\n diagram: SimDiagram,\n state: SimulationState,\n subProcNode: SimNode,\n): SimulationState {\n const childStarts = diagram.nodes.filter(\n (n) => n.type === \"StartEvent\" && n.parentId === subProcNode.id,\n );\n\n let next: SimulationState = {\n ...state,\n enteredScopes: [...state.enteredScopes, subProcNode.id],\n };\n\n for (const startNode of childStarts) {\n const newToken: SimToken = {\n id: nextTokenId(),\n elementId: startNode.id,\n scopeId: subProcNode.id,\n };\n next = {\n ...next,\n tokens: [...next.tokens, newToken],\n };\n next = withLog(next, {\n type: \"created\",\n elementId: startNode.id,\n tokenId: newToken.id,\n message: `SubProcess \"${subProcNode.name ?? subProcNode.id}\" entered — token at \"${startNode.name ?? startNode.id}\".`,\n });\n }\n\n return next;\n}\n\n// ─── Automatic element execution ──────────────────────────────────────────────\n\nfunction fireAutomatic(\n diagram: SimDiagram,\n state: SimulationState,\n token: SimToken,\n): SimulationState {\n const node = nodeById(diagram, token.elementId);\n if (!node) return state;\n const { type } = node;\n const vars = state.variables;\n\n // EndEvent ─────────────────────────────────────────────────────────────────\n if (type === \"EndEvent\") {\n let next: SimulationState = {\n ...state,\n tokens: state.tokens.filter((t) => t.id !== token.id),\n };\n next = withLog(next, {\n type: \"consumed\",\n elementId: node.id,\n tokenId: token.id,\n message: `Token consumed at end event \"${node.name ?? node.id}\".`,\n });\n return next;\n }\n\n // StartEvent / IntermediateThrowEvent ──────────────────────────────────────\n if (type === \"StartEvent\" || type === \"IntermediateThrowEvent\") {\n let next = withLog(state, {\n type: \"fired\",\n elementId: node.id,\n tokenId: token.id,\n message: `\"${node.name ?? node.id}\" (${type}) fired.`,\n });\n return disperseToTargets(diagram, next, node.id, token.id);\n }\n\n // ExclusiveGateway ─────────────────────────────────────────────────────────\n if (type === \"ExclusiveGateway\") {\n const incoming = seqIn(diagram, node.id);\n if (incoming.length >= 2) {\n // XOR join: pass through immediately\n let next = withLog(state, {\n type: \"joined\",\n elementId: node.id,\n tokenId: token.id,\n message: `ExclusiveGateway \"${node.name ?? node.id}\" join — token passes through.`,\n });\n return disperseToTargets(diagram, next, node.id, token.id);\n }\n\n const outEdges = seqOut(diagram, node.id);\n // Evaluate conditions; fall back to default, then first\n const chosen =\n outEdges.find(\n (e) => e.conditionExpression && !e.isDefault && evalCondition(e.conditionExpression, vars),\n ) ??\n outEdges.find((e) => e.isDefault) ??\n outEdges[0];\n\n if (!chosen) return state;\n const target = nodeById(diagram, chosen.target);\n if (!target) return state;\n\n const newToken: SimToken = {\n id: nextTokenId(),\n elementId: chosen.target,\n scopeId: getScopeId(diagram, chosen.target),\n };\n let next: SimulationState = {\n ...state,\n tokens: [...state.tokens.filter((t) => t.id !== token.id), newToken],\n };\n next = withLog(next, {\n type: \"fired\",\n elementId: node.id,\n tokenId: token.id,\n message: `ExclusiveGateway \"${node.name ?? node.id}\" split → \"${target.name ?? chosen.target}\".`,\n });\n return next;\n }\n\n // InclusiveGateway ─────────────────────────────────────────────────────────\n if (type === \"InclusiveGateway\") {\n const incoming = seqIn(diagram, node.id);\n if (incoming.length >= 2) {\n // OR join: pass through (simplified — full semantics require tracking active paths)\n let next = withLog(state, {\n type: \"joined\",\n elementId: node.id,\n tokenId: token.id,\n message: `InclusiveGateway \"${node.name ?? node.id}\" join.`,\n });\n return disperseToTargets(diagram, next, node.id, token.id);\n }\n\n const outEdges = seqOut(diagram, node.id);\n // Take all paths whose condition is true; if none match → take default\n const matching = outEdges.filter(\n (e) => e.conditionExpression && !e.isDefault && evalCondition(e.conditionExpression, vars),\n );\n const activePaths = matching.length > 0 ? matching : outEdges.filter((e) => e.isDefault);\n const paths = activePaths.length > 0 ? activePaths : outEdges; // all if no conditions defined\n\n let next = withLog(state, {\n type: \"split\",\n elementId: node.id,\n tokenId: token.id,\n message: `InclusiveGateway \"${node.name ?? node.id}\" split → ${paths.length} path(s).`,\n });\n\n next = { ...next, tokens: next.tokens.filter((t) => t.id !== token.id) };\n for (const edge of paths) {\n const tgt = nodeById(diagram, edge.target);\n if (!tgt) continue;\n const newToken: SimToken = {\n id: nextTokenId(),\n elementId: edge.target,\n scopeId: getScopeId(diagram, edge.target),\n };\n next = { ...next, tokens: [...next.tokens, newToken] };\n next = withLog(next, {\n type: \"created\",\n elementId: edge.target,\n tokenId: newToken.id,\n message: `Token created at \"${tgt.name ?? edge.target}\".`,\n });\n }\n return next;\n }\n\n // ParallelGateway ──────────────────────────────────────────────────────────\n if (type === \"ParallelGateway\") {\n const incoming = seqIn(diagram, node.id);\n if (incoming.length >= 2) {\n const atGateway = state.tokens.filter((t) => t.elementId === node.id);\n if (atGateway.length < incoming.length) {\n return withLog(state, {\n type: \"blocked\",\n elementId: node.id,\n tokenId: token.id,\n message: `ParallelGateway \"${node.name ?? node.id}\" waiting for ${incoming.length - atGateway.length} more token(s).`,\n });\n }\n const consumeIds = new Set(atGateway.map((t) => t.id));\n let next: SimulationState = {\n ...state,\n tokens: state.tokens.filter((t) => !consumeIds.has(t.id)),\n };\n next = withLog(next, {\n type: \"joined\",\n elementId: node.id,\n message: `ParallelGateway \"${node.name ?? node.id}\" join fired — all paths synchronized.`,\n });\n return disperseToTargets(diagram, next, node.id, null);\n }\n // AND split\n let next = withLog(state, {\n type: \"split\",\n elementId: node.id,\n tokenId: token.id,\n message: `ParallelGateway \"${node.name ?? node.id}\" split → ${seqOut(diagram, node.id).length} paths.`,\n });\n return disperseToTargets(diagram, next, node.id, token.id);\n }\n\n // EventBasedGateway ────────────────────────────────────────────────────────\n // Disperses to ALL outgoing catch events; first one fired wins (race).\n if (type === \"EventBasedGateway\") {\n let next = withLog(state, {\n type: \"split\",\n elementId: node.id,\n tokenId: token.id,\n message: `EventBasedGateway \"${node.name ?? node.id}\" waiting — ${seqOut(diagram, node.id).length} competing event(s).`,\n });\n return disperseToTargets(diagram, next, node.id, token.id);\n }\n\n // ComplexGateway (simplified: first path) ─────────────────────────────────\n if (type === \"ComplexGateway\") {\n const outEdges = seqOut(diagram, node.id);\n const chosen = outEdges[0];\n if (!chosen) return state;\n const newToken: SimToken = {\n id: nextTokenId(),\n elementId: chosen.target,\n scopeId: getScopeId(diagram, chosen.target),\n };\n let next: SimulationState = {\n ...state,\n tokens: [...state.tokens.filter((t) => t.id !== token.id), newToken],\n };\n next = withLog(next, {\n type: \"fired\",\n elementId: node.id,\n tokenId: token.id,\n message: `ComplexGateway \"${node.name ?? node.id}\" fired → \"${chosen.target}\".`,\n });\n return next;\n }\n\n return state;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\nexport function createSimulation(\n diagram: SimDiagram,\n initialVariables: Record<string, string | number | boolean> = {},\n): SimulationState {\n _tokenCounter = 0;\n\n const startEvents = diagram.nodes.filter(\n (n) => n.type === \"StartEvent\" && !n.parentId,\n );\n\n const tokens: SimToken[] = startEvents.map((n) => ({\n id: nextTokenId(),\n elementId: n.id,\n scopeId: \"root\",\n }));\n\n const log: SimLogEntry[] = startEvents.map((n, i) => ({\n step: 0,\n type: \"created\" as SimLogType,\n elementId: n.id,\n tokenId: tokens[i]?.id,\n message: `Simulation started — token placed at \"${n.name ?? n.id}\".`,\n }));\n\n return {\n tokens,\n step: 0,\n status: startEvents.length > 0 ? \"running\" : \"idle\",\n log,\n variables: initialVariables,\n enteredScopes: [],\n };\n}\n\nexport function tick(diagram: SimDiagram, state: SimulationState): SimulationState {\n if (state.status !== \"running\") return state;\n\n let current: SimulationState = { ...state, step: state.step + 1 };\n let changed = true;\n let guard = 0;\n\n while (changed && guard < 1000) {\n guard++;\n changed = false;\n\n for (const token of current.tokens) {\n const node = nodeById(diagram, token.elementId);\n if (!node) continue;\n\n // ── SubProcess enter / wait / complete ─────────────────────────────────\n if (isSubProcess(node.type)) {\n if (!current.enteredScopes.includes(node.id)) {\n // Enter: spawn child tokens at internal start events\n const childStarts = diagram.nodes.filter(\n (n) => n.type === \"StartEvent\" && n.parentId === node.id,\n );\n if (childStarts.length > 0) {\n current = enterSubProcess(diagram, current, node);\n changed = true;\n break;\n }\n // No internal structure → treat as manual task (don't advance)\n } else {\n // Check if scope completed\n const scopeTokens = current.tokens.filter((t) => t.scopeId === node.id);\n if (scopeTokens.length === 0) {\n let next = withLog(current, {\n type: \"fired\",\n elementId: node.id,\n tokenId: token.id,\n message: `SubProcess \"${node.name ?? node.id}\" completed.`,\n });\n current = disperseToTargets(diagram, next, node.id, token.id);\n changed = true;\n break;\n }\n }\n continue;\n }\n\n // ── ParallelGateway join: only fire when all tokens are present ─────────\n if (node.type === \"ParallelGateway\") {\n const incoming = seqIn(diagram, node.id);\n const atGateway = current.tokens.filter((t) => t.elementId === node.id);\n if (incoming.length >= 2 && atGateway.length < incoming.length) continue;\n }\n\n if (!isAutomatic(node.type)) continue;\n\n const prevLen = current.tokens.length;\n const prevIds = new Set(current.tokens.map((t) => t.id));\n current = fireAutomatic(diagram, current, token);\n\n const same =\n current.tokens.length === prevLen &&\n [...prevIds].every((id) => current.tokens.some((t) => t.id === id));\n\n if (!same) {\n changed = true;\n break;\n }\n }\n }\n\n // Determine final status\n if (current.tokens.length === 0) {\n current = { ...current, status: \"completed\" };\n }\n\n return current;\n}\n\nexport function fire(\n diagram: SimDiagram,\n state: SimulationState,\n elementId: string,\n variables?: Record<string, string | number | boolean>,\n): SimulationState {\n if (state.status !== \"running\") return state;\n\n const node = nodeById(diagram, elementId);\n if (!node) return state;\n\n const mergedVars = variables ? { ...state.variables, ...variables } : state.variables;\n\n // ── BoundaryEvent: fired from the host task context, no token at the event ─\n if (node.type === \"BoundaryEvent\") {\n const hostId = node.attachedToRef;\n if (!hostId) return state;\n\n // The boundary event is activated relative to a token at the host task\n const hostToken = state.tokens.find((t) => t.elementId === hostId);\n if (!hostToken) return state;\n\n const isInterrupting = node.isInterrupting !== false;\n\n let next: SimulationState = { ...state, variables: mergedVars, step: state.step + 1 };\n next = withLog(next, {\n type: isInterrupting ? \"interrupted\" : \"fired\",\n elementId,\n tokenId: hostToken.id,\n message: `BoundaryEvent \"${node.name ?? elementId}\" fired (${isInterrupting ? \"interrupting\" : \"non-interrupting\"}).`,\n });\n\n if (isInterrupting) {\n // Remove the host task token (interrupts the task)\n next = { ...next, tokens: next.tokens.filter((t) => t.id !== hostToken.id) };\n }\n // Non-interrupting: host token stays; a new parallel token follows the boundary path\n\n next = disperseToTargets(diagram, next, elementId, null);\n return tick(diagram, { ...next, step: next.step - 1 });\n }\n\n const token = state.tokens.find((t) => t.elementId === elementId);\n if (!token) return state;\n\n // ── IntermediateCatchEvent following an EventBasedGateway: cancel race ────\n if (node.type === \"IntermediateCatchEvent\") {\n const gwEdge = seqIn(diagram, elementId).find((e) => {\n const src = nodeById(diagram, e.source);\n return src?.type === \"EventBasedGateway\";\n });\n if (gwEdge) {\n // Cancel all sibling catch events in the race\n const gw = nodeById(diagram, gwEdge.source);\n if (gw) {\n const siblingTargets = new Set(\n seqOut(diagram, gw.id)\n .map((e) => e.target)\n .filter((id) => id !== elementId),\n );\n state = {\n ...state,\n tokens: state.tokens.filter((t) => !siblingTargets.has(t.elementId)),\n };\n }\n }\n }\n\n let next: SimulationState = { ...state, variables: mergedVars, step: state.step + 1 };\n next = withLog(next, {\n type: \"fired\",\n elementId,\n tokenId: token.id,\n message: `\"${node.name ?? elementId}\" (${node.type}) manually fired.`,\n });\n next = disperseToTargets(diagram, next, elementId, token.id);\n return tick(diagram, { ...next, step: next.step - 1 });\n}\n\nexport function getFireable(diagram: SimDiagram, state: SimulationState): string[] {\n if (state.status !== \"running\") return [];\n\n const fireable = new Set<string>();\n\n for (const token of state.tokens) {\n const node = nodeById(diagram, token.elementId);\n if (!node) continue;\n\n if (isManual(node.type)) {\n fireable.add(node.id);\n }\n\n // Expose boundary events attached to tasks that have tokens\n if (TASK_TYPES.has(node.type)) {\n for (const be of boundaryEventsOf(diagram, node.id)) {\n fireable.add(be.id);\n }\n }\n }\n\n return [...fireable];\n}\n\nexport function isCompleted(state: SimulationState): boolean {\n return state.status === \"completed\";\n}\n\n/** Set or update a process variable without advancing the simulation. */\nexport function setVariable(\n state: SimulationState,\n key: string,\n value: string | number | boolean,\n): SimulationState {\n return { ...state, variables: { ...state.variables, [key]: value } };\n}\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
type SimVariables = Record<string, string | number | boolean>;
|
|
2
|
+
|
|
3
|
+
interface SimNode {
|
|
4
|
+
id: string;
|
|
5
|
+
type: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
parentId?: string;
|
|
8
|
+
/** BoundaryEvent only — the task/subprocess this event is attached to. */
|
|
9
|
+
attachedToRef?: string;
|
|
10
|
+
/** BoundaryEvent: true = interrupting (default), false = non-interrupting. */
|
|
11
|
+
isInterrupting?: boolean;
|
|
12
|
+
}
|
|
13
|
+
interface SimEdge {
|
|
14
|
+
id: string;
|
|
15
|
+
type: string;
|
|
16
|
+
source: string;
|
|
17
|
+
target: string;
|
|
18
|
+
conditionExpression?: string;
|
|
19
|
+
isDefault?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface SimDiagram {
|
|
22
|
+
nodes: SimNode[];
|
|
23
|
+
edges: SimEdge[];
|
|
24
|
+
}
|
|
25
|
+
interface SimToken {
|
|
26
|
+
id: string;
|
|
27
|
+
/** The element the token currently occupies. */
|
|
28
|
+
elementId: string;
|
|
29
|
+
/**
|
|
30
|
+
* The subprocess scope this token belongs to.
|
|
31
|
+
* "root" for top-level tokens; the subprocess node id for child tokens.
|
|
32
|
+
*/
|
|
33
|
+
scopeId: string;
|
|
34
|
+
}
|
|
35
|
+
type SimStatus = "idle" | "running" | "completed" | "deadlocked";
|
|
36
|
+
type SimLogType = "created" | "fired" | "split" | "joined" | "consumed" | "blocked" | "deadlocked" | "interrupted";
|
|
37
|
+
interface SimLogEntry {
|
|
38
|
+
step: number;
|
|
39
|
+
type: SimLogType;
|
|
40
|
+
elementId: string;
|
|
41
|
+
tokenId?: string;
|
|
42
|
+
message: string;
|
|
43
|
+
}
|
|
44
|
+
interface SimulationState {
|
|
45
|
+
tokens: SimToken[];
|
|
46
|
+
step: number;
|
|
47
|
+
status: SimStatus;
|
|
48
|
+
log: SimLogEntry[];
|
|
49
|
+
/** Process-level variables used for gateway condition evaluation. */
|
|
50
|
+
variables: Record<string, string | number | boolean>;
|
|
51
|
+
/** IDs of subprocess nodes whose internal execution has started. */
|
|
52
|
+
enteredScopes: string[];
|
|
53
|
+
}
|
|
54
|
+
declare function createSimulation(diagram: SimDiagram, initialVariables?: Record<string, string | number | boolean>): SimulationState;
|
|
55
|
+
declare function tick(diagram: SimDiagram, state: SimulationState): SimulationState;
|
|
56
|
+
declare function fire(diagram: SimDiagram, state: SimulationState, elementId: string, variables?: Record<string, string | number | boolean>): SimulationState;
|
|
57
|
+
declare function getFireable(diagram: SimDiagram, state: SimulationState): string[];
|
|
58
|
+
declare function isCompleted(state: SimulationState): boolean;
|
|
59
|
+
/** Set or update a process variable without advancing the simulation. */
|
|
60
|
+
declare function setVariable(state: SimulationState, key: string, value: string | number | boolean): SimulationState;
|
|
61
|
+
|
|
62
|
+
export { type SimDiagram, type SimEdge, type SimLogEntry, type SimLogType, type SimNode, type SimStatus, type SimToken, type SimVariables, type SimulationState, createSimulation, fire, getFireable, isCompleted, setVariable, tick };
|