bpmn-elements 17.2.2 → 18.0.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.
Files changed (155) hide show
  1. package/README.md +3 -1
  2. package/dist/Api.js +83 -0
  3. package/dist/Context.js +228 -22
  4. package/dist/Environment.js +111 -31
  5. package/dist/EventBroker.js +57 -1
  6. package/dist/Expressions.js +3 -4
  7. package/dist/MessageFormatter.js +29 -16
  8. package/dist/Timers.js +13 -9
  9. package/dist/Tracker.js +1 -0
  10. package/dist/activity/Activity.js +458 -254
  11. package/dist/activity/ActivityExecution.js +113 -40
  12. package/dist/activity/Dummy.js +6 -1
  13. package/dist/activity/Escalation.js +36 -24
  14. package/dist/activity/ExecutionScope.js +1 -1
  15. package/dist/activity/Message.js +36 -24
  16. package/dist/activity/Signal.js +36 -24
  17. package/dist/activity/outbound-evaluator.js +1 -1
  18. package/dist/condition.js +12 -6
  19. package/dist/constants.js +21 -0
  20. package/dist/definition/Definition.js +182 -64
  21. package/dist/definition/DefinitionExecution.js +195 -82
  22. package/dist/error/BpmnError.js +12 -1
  23. package/dist/error/Errors.js +50 -9
  24. package/dist/eventDefinitions/CancelEventDefinition.js +29 -11
  25. package/dist/eventDefinitions/CompensateEventDefinition.js +51 -31
  26. package/dist/eventDefinitions/ConditionalEventDefinition.js +21 -9
  27. package/dist/eventDefinitions/ErrorEventDefinition.js +46 -30
  28. package/dist/eventDefinitions/EscalationEventDefinition.js +44 -27
  29. package/dist/eventDefinitions/EventDefinitionExecution.js +30 -23
  30. package/dist/eventDefinitions/LinkEventDefinition.js +45 -120
  31. package/dist/eventDefinitions/MessageEventDefinition.js +44 -29
  32. package/dist/eventDefinitions/SignalEventDefinition.js +46 -31
  33. package/dist/eventDefinitions/TerminateEventDefinition.js +10 -1
  34. package/dist/eventDefinitions/TimerEventDefinition.js +57 -37
  35. package/dist/eventDefinitions/index.js +20 -21
  36. package/dist/events/BoundaryEvent.js +52 -40
  37. package/dist/events/EndEvent.js +22 -8
  38. package/dist/events/IntermediateCatchEvent.js +26 -8
  39. package/dist/events/IntermediateThrowEvent.js +24 -9
  40. package/dist/events/StartEvent.js +30 -14
  41. package/dist/events/index.js +10 -11
  42. package/dist/flows/Association.js +50 -7
  43. package/dist/flows/MessageFlow.js +49 -10
  44. package/dist/flows/SequenceFlow.js +93 -22
  45. package/dist/flows/index.js +6 -7
  46. package/dist/gateways/EventBasedGateway.js +29 -15
  47. package/dist/gateways/ExclusiveGateway.js +20 -5
  48. package/dist/gateways/InclusiveGateway.js +21 -5
  49. package/dist/gateways/ParallelGateway.js +253 -15
  50. package/dist/gateways/index.js +8 -9
  51. package/dist/getPropertyValue.js +2 -2
  52. package/dist/index.js +42 -43
  53. package/dist/io/BpmnIO.js +15 -1
  54. package/dist/io/EnvironmentDataObject.js +29 -1
  55. package/dist/io/EnvironmentDataStore.js +24 -1
  56. package/dist/io/EnvironmentDataStoreReference.js +24 -1
  57. package/dist/io/InputOutputSpecification.js +21 -11
  58. package/dist/io/Properties.js +28 -17
  59. package/dist/messageHelper.js +41 -4
  60. package/dist/process/Lane.js +15 -4
  61. package/dist/process/Process.js +174 -76
  62. package/dist/process/ProcessExecution.js +362 -177
  63. package/dist/shared.js +2 -0
  64. package/dist/tasks/CallActivity.js +19 -4
  65. package/dist/tasks/LoopCharacteristics.js +94 -9
  66. package/dist/tasks/ReceiveTask.js +36 -21
  67. package/dist/tasks/ScriptTask.js +22 -6
  68. package/dist/tasks/ServiceImplementation.js +7 -4
  69. package/dist/tasks/ServiceTask.js +19 -4
  70. package/dist/tasks/SignalTask.js +19 -4
  71. package/dist/tasks/StandardLoopCharacteristics.js +8 -4
  72. package/dist/tasks/SubProcess.js +44 -29
  73. package/dist/tasks/Task.js +19 -4
  74. package/dist/tasks/Transaction.js +8 -4
  75. package/dist/tasks/index.js +16 -18
  76. package/package.json +31 -13
  77. package/src/Api.js +70 -0
  78. package/src/Context.js +200 -19
  79. package/src/Environment.js +99 -30
  80. package/src/EventBroker.js +46 -1
  81. package/src/Expressions.js +2 -3
  82. package/src/MessageFormatter.js +24 -16
  83. package/src/Timers.js +12 -9
  84. package/src/Tracker.js +1 -0
  85. package/src/activity/Activity.js +388 -231
  86. package/src/activity/ActivityExecution.js +93 -42
  87. package/src/activity/Dummy.js +6 -1
  88. package/src/activity/Escalation.js +25 -18
  89. package/src/activity/ExecutionScope.js +1 -1
  90. package/src/activity/Message.js +25 -18
  91. package/src/activity/Signal.js +25 -18
  92. package/src/activity/outbound-evaluator.js +1 -1
  93. package/src/condition.js +11 -5
  94. package/src/constants.js +15 -0
  95. package/src/definition/Definition.js +157 -62
  96. package/src/definition/DefinitionExecution.js +161 -83
  97. package/src/error/BpmnError.js +11 -1
  98. package/src/error/Errors.js +44 -5
  99. package/src/eventDefinitions/CancelEventDefinition.js +27 -13
  100. package/src/eventDefinitions/CompensateEventDefinition.js +48 -32
  101. package/src/eventDefinitions/ConditionalEventDefinition.js +20 -10
  102. package/src/eventDefinitions/ErrorEventDefinition.js +44 -33
  103. package/src/eventDefinitions/EscalationEventDefinition.js +39 -26
  104. package/src/eventDefinitions/EventDefinitionExecution.js +30 -24
  105. package/src/eventDefinitions/LinkEventDefinition.js +34 -120
  106. package/src/eventDefinitions/MessageEventDefinition.js +42 -31
  107. package/src/eventDefinitions/SignalEventDefinition.js +43 -32
  108. package/src/eventDefinitions/TerminateEventDefinition.js +9 -1
  109. package/src/eventDefinitions/TimerEventDefinition.js +53 -35
  110. package/src/eventDefinitions/index.js +10 -23
  111. package/src/events/BoundaryEvent.js +50 -39
  112. package/src/events/EndEvent.js +19 -7
  113. package/src/events/IntermediateCatchEvent.js +24 -8
  114. package/src/events/IntermediateThrowEvent.js +24 -8
  115. package/src/events/StartEvent.js +25 -14
  116. package/src/events/index.js +5 -18
  117. package/src/flows/Association.js +43 -9
  118. package/src/flows/MessageFlow.js +41 -10
  119. package/src/flows/SequenceFlow.js +82 -19
  120. package/src/flows/index.js +3 -4
  121. package/src/gateways/EventBasedGateway.js +27 -15
  122. package/src/gateways/ExclusiveGateway.js +16 -3
  123. package/src/gateways/InclusiveGateway.js +16 -3
  124. package/src/gateways/ParallelGateway.js +301 -10
  125. package/src/gateways/index.js +4 -4
  126. package/src/getPropertyValue.js +2 -2
  127. package/src/index.js +19 -19
  128. package/src/io/BpmnIO.js +13 -1
  129. package/src/io/EnvironmentDataObject.js +26 -1
  130. package/src/io/EnvironmentDataStore.js +22 -1
  131. package/src/io/EnvironmentDataStoreReference.js +22 -1
  132. package/src/io/InputOutputSpecification.js +17 -8
  133. package/src/io/Properties.js +23 -13
  134. package/src/messageHelper.js +36 -4
  135. package/src/process/Lane.js +14 -4
  136. package/src/process/Process.js +154 -72
  137. package/src/process/ProcessExecution.js +326 -175
  138. package/src/shared.js +1 -0
  139. package/src/tasks/CallActivity.js +16 -2
  140. package/src/tasks/LoopCharacteristics.js +77 -11
  141. package/src/tasks/ReceiveTask.js +33 -22
  142. package/src/tasks/ScriptTask.js +17 -3
  143. package/src/tasks/ServiceImplementation.js +6 -3
  144. package/src/tasks/ServiceTask.js +16 -2
  145. package/src/tasks/SignalTask.js +16 -2
  146. package/src/tasks/StandardLoopCharacteristics.js +7 -3
  147. package/src/tasks/SubProcess.js +37 -23
  148. package/src/tasks/Task.js +16 -2
  149. package/src/tasks/Transaction.js +7 -3
  150. package/src/tasks/index.js +8 -9
  151. package/types/bundle-errors.d.ts +1 -0
  152. package/types/bundle.d.ts +97 -0
  153. package/types/index.d.ts +2614 -84
  154. package/types/interfaces.d.ts +636 -0
  155. package/types/types.d.ts +0 -765
package/src/Context.js CHANGED
@@ -1,25 +1,41 @@
1
- import BpmnIO from './io/BpmnIO.js';
2
- import Environment from './Environment.js';
1
+ import { BpmnIO } from './io/BpmnIO.js';
2
+ import { Environment } from './Environment.js';
3
3
  import { getUniqueId } from './shared.js';
4
+ import { K_ACTIVATED } from './constants.js';
4
5
 
5
- const kOwner = Symbol.for('owner');
6
- const kActivated = Symbol.for('activated');
6
+ const K_OWNER = Symbol.for('owner');
7
7
 
8
- export default function Context(definitionContext, environment) {
8
+ /**
9
+ * Build a runtime Context from a parsed BPMN definition.
10
+ * @param {import('moddle-context-serializer').SerializableContext} definitionContext
11
+ * @param {import('#types').Environment} [environment] Existing environment to clone; a fresh one is created when omitted
12
+ */
13
+ export function Context(definitionContext, environment) {
9
14
  environment = environment ? environment.clone() : new Environment();
10
15
  return new ContextInstance(definitionContext, environment);
11
16
  }
12
17
 
13
- function ContextInstance(definitionContext, environment, owner) {
18
+ /**
19
+ * Per-execution registry that lazily upserts activities, flows, and processes from the parsed BPMN definition.
20
+ * @param {import('moddle-context-serializer').SerializableContext} definitionContext
21
+ * @param {import('#types').Environment} environment
22
+ * @param {import('#types').Process | import('#types').Activity} [owner] Process or sub-process activity that owns this context
23
+ * @param {Map<string, any>} [peersCache] Shared converging parallel gateway peer cache; created at the root and propagated to every clone
24
+ */
25
+ export function ContextInstance(definitionContext, environment, owner, peersCache) {
14
26
  const { id = 'Def', name, type = 'context' } = definitionContext;
15
- const sid = getUniqueId(id);
16
27
  this.id = id;
17
28
  this.name = name;
18
29
  this.type = type;
19
- this.sid = sid;
30
+ /** Unique instance id */
31
+ this.sid = getUniqueId(id);
20
32
  this.definitionContext = definitionContext;
21
33
  this.environment = environment;
34
+ /** Discovered parallel gateway peers, keyed by gateway id, shared with all clones. Runtime-only, not serialized. */
35
+ this.peersCache = peersCache || new Map();
36
+ /** @type {import('#types').IExtensionsMapper} */
22
37
  this.extensionsMapper = new ExtensionsMapper(this);
38
+ /** @private */
23
39
  this.refs = new Map([
24
40
  ['activityRefs', new Map()],
25
41
  ['sequenceFlowRefs', new Map()],
@@ -29,15 +45,21 @@ function ContextInstance(definitionContext, environment, owner) {
29
45
  ['dataObjectRefs', new Map()],
30
46
  ['dataStoreRefs', new Map()],
31
47
  ]);
32
- this[kOwner] = owner;
48
+ this[K_OWNER] = owner;
33
49
  }
34
50
 
35
51
  Object.defineProperty(ContextInstance.prototype, 'owner', {
52
+ /** @returns {import('#types').Process | import('#types').Activity | undefined} Process or sub-process activity that owns this context */
36
53
  get() {
37
- return this[kOwner];
54
+ return this[K_OWNER];
38
55
  },
39
56
  });
40
57
 
58
+ /**
59
+ * Get or create the activity instance for the given id.
60
+ * @param {string} activityId
61
+ * @returns {import('./activity/Activity.js').Activity | null}
62
+ */
41
63
  ContextInstance.prototype.getActivityById = function getActivityById(activityId) {
42
64
  const activityInstance = this.refs.get('activityRefs').get(activityId);
43
65
  if (activityInstance) return activityInstance;
@@ -46,6 +68,11 @@ ContextInstance.prototype.getActivityById = function getActivityById(activityId)
46
68
  return this.upsertActivity(activity);
47
69
  };
48
70
 
71
+ /**
72
+ * Return the cached activity instance, instantiating it the first time it is referenced.
73
+ * @param {import('moddle-context-serializer').SerializableElement} activityDef
74
+ * @returns {import('./activity/Activity.js').Activity}
75
+ */
49
76
  ContextInstance.prototype.upsertActivity = function upsertActivity(activityDef) {
50
77
  let activityInstance = this.refs.get('activityRefs').get(activityDef.id);
51
78
  if (activityInstance) return activityInstance;
@@ -56,6 +83,11 @@ ContextInstance.prototype.upsertActivity = function upsertActivity(activityDef)
56
83
  return activityInstance;
57
84
  };
58
85
 
86
+ /**
87
+ * Get or create the sequence flow instance for the given id.
88
+ * @param {string} sequenceFlowId
89
+ * @returns {import('./flows/SequenceFlow.js').SequenceFlow | null}
90
+ */
59
91
  ContextInstance.prototype.getSequenceFlowById = function getSequenceFlowById(sequenceFlowId) {
60
92
  const flowInstance = this.refs.get('sequenceFlowRefs').get(sequenceFlowId);
61
93
  if (flowInstance) return flowInstance;
@@ -65,30 +97,55 @@ ContextInstance.prototype.getSequenceFlowById = function getSequenceFlowById(seq
65
97
  return this.upsertSequenceFlow(flowDef);
66
98
  };
67
99
 
100
+ /**
101
+ * @param {string} activityId
102
+ */
68
103
  ContextInstance.prototype.getInboundSequenceFlows = function getInboundSequenceFlows(activityId) {
69
104
  return (this.definitionContext.getInboundSequenceFlows(activityId) || []).map((flow) => this.upsertSequenceFlow(flow));
70
105
  };
71
106
 
107
+ /**
108
+ * @param {string} activityId
109
+ */
72
110
  ContextInstance.prototype.getOutboundSequenceFlows = function getOutboundSequenceFlows(activityId) {
73
111
  return (this.definitionContext.getOutboundSequenceFlows(activityId) || []).map((flow) => this.upsertSequenceFlow(flow));
74
112
  };
75
113
 
114
+ /**
115
+ * @param {string} activityId
116
+ */
76
117
  ContextInstance.prototype.getInboundAssociations = function getInboundAssociations(activityId) {
77
118
  return (this.definitionContext.getInboundAssociations(activityId) || []).map((association) => this.upsertAssociation(association));
78
119
  };
79
120
 
121
+ /**
122
+ * @param {string} activityId
123
+ */
80
124
  ContextInstance.prototype.getOutboundAssociations = function getOutboundAssociations(activityId) {
81
125
  return (this.definitionContext.getOutboundAssociations(activityId) || []).map((association) => this.upsertAssociation(association));
82
126
  };
83
127
 
128
+ /**
129
+ * Get every activity in the definition, optionally narrowed to a parent scope.
130
+ * @param {string} [scopeId] Process or sub-process id
131
+ */
84
132
  ContextInstance.prototype.getActivities = function getActivities(scopeId) {
85
133
  return (this.definitionContext.getActivities(scopeId) || []).map((activityDef) => this.upsertActivity(activityDef));
86
134
  };
87
135
 
136
+ /**
137
+ * Get every sequence flow in the definition, optionally narrowed to a parent scope.
138
+ * @param {string} [scopeId] Process or sub-process id
139
+ */
88
140
  ContextInstance.prototype.getSequenceFlows = function getSequenceFlows(scopeId) {
89
141
  return (this.definitionContext.getSequenceFlows(scopeId) || []).map((flow) => this.upsertSequenceFlow(flow));
90
142
  };
91
143
 
144
+ /**
145
+ * Return the cached sequence flow, instantiating it the first time it is referenced.
146
+ * @param {import('moddle-context-serializer').SerializableElement} flowDefinition
147
+ * @returns {import('./flows/SequenceFlow.js').SequenceFlow}
148
+ */
92
149
  ContextInstance.prototype.upsertSequenceFlow = function upsertSequenceFlow(flowDefinition) {
93
150
  const sequenceFlowRefs = this.refs.get('sequenceFlowRefs');
94
151
  let flowInstance = sequenceFlowRefs.get(flowDefinition.id);
@@ -100,10 +157,18 @@ ContextInstance.prototype.upsertSequenceFlow = function upsertSequenceFlow(flowD
100
157
  return flowInstance;
101
158
  };
102
159
 
160
+ /**
161
+ * Get association flows
162
+ * @param {string} [scopeId] Process or sub-process id
163
+ */
103
164
  ContextInstance.prototype.getAssociations = function getAssociations(scopeId) {
104
165
  return (this.definitionContext.getAssociations(scopeId) || []).map((association) => this.upsertAssociation(association));
105
166
  };
106
167
 
168
+ /**
169
+ * @param {import('moddle-context-serializer').SerializableElement} associationDefinition
170
+ * @returns {import('./flows/Association.js').Association}
171
+ */
107
172
  ContextInstance.prototype.upsertAssociation = function upsertAssociation(associationDefinition) {
108
173
  const associationRefs = this.refs.get('associationRefs');
109
174
  let instance = associationRefs.get(associationDefinition.id);
@@ -116,10 +181,38 @@ ContextInstance.prototype.upsertAssociation = function upsertAssociation(associa
116
181
  return instance;
117
182
  };
118
183
 
184
+ /**
185
+ * Create a new context that shares the parsed definition but optionally swaps environment and owner.
186
+ * @param {import('#types').Environment} [newEnvironment]
187
+ * @param {import('#types').Process | import('#types').Activity} [newOwner]
188
+ */
119
189
  ContextInstance.prototype.clone = function clone(newEnvironment, newOwner) {
120
- return new ContextInstance(this.definitionContext, newEnvironment || this.environment, newOwner);
190
+ return new ContextInstance(this.definitionContext, newEnvironment || this.environment, newOwner, this.peersCache);
121
191
  };
122
192
 
193
+ /**
194
+ * Cached converging parallel gateway peers discovered by an earlier shake.
195
+ * @param {string} gatewayId
196
+ * @returns {Array<[string, string[]]> | undefined}
197
+ */
198
+ ContextInstance.prototype.getShakenPeers = function getShakenPeers(gatewayId) {
199
+ return this.peersCache.get(gatewayId);
200
+ };
201
+
202
+ /**
203
+ * Store converging parallel gateway peers so subsequent runs can skip the graph shake.
204
+ * @param {string} gatewayId
205
+ * @param {Array<[string, string[]]>} peers
206
+ */
207
+ ContextInstance.prototype.setShakenPeers = function setShakenPeers(gatewayId, peers) {
208
+ this.peersCache.set(gatewayId, peers);
209
+ };
210
+
211
+ /**
212
+ * Get or create the process instance for the given id. Each process gets its own cloned environment.
213
+ * @param {string} processId
214
+ * @returns {import('#types').Process | null}
215
+ */
123
216
  ContextInstance.prototype.getProcessById = function getProcessById(processId) {
124
217
  const processRefs = this.refs.get('processRefs');
125
218
  let bp = processRefs.get(processId);
@@ -131,30 +224,48 @@ ContextInstance.prototype.getProcessById = function getProcessById(processId) {
131
224
  const bpContext = this.clone(this.environment.clone());
132
225
  bp = new processDefinition.Behaviour(processDefinition, bpContext);
133
226
  processRefs.set(processId, bp);
134
- bpContext[kOwner] = bp;
227
+ bpContext[K_OWNER] = bp;
135
228
 
136
229
  return bp;
137
230
  };
138
231
 
232
+ /**
233
+ * Build a fresh, uncached process instance for the given id. Used by call activities.
234
+ * @param {string} processId
235
+ * @returns {import('#types').Process | null}
236
+ */
139
237
  ContextInstance.prototype.getNewProcessById = function getNewProcessById(processId) {
140
238
  if (!this.getProcessById(processId)) return null;
141
239
  const bpDef = this.definitionContext.getProcessById(processId);
142
240
 
143
241
  const bpContext = this.clone(this.environment.clone());
144
242
  const bp = new bpDef.Behaviour(bpDef, bpContext);
145
- bpContext[kOwner] = bp;
243
+ bpContext[K_OWNER] = bp;
146
244
 
147
245
  return bp;
148
246
  };
149
247
 
248
+ /**
249
+ * Get every process in the definition.
250
+ * @returns {import('#types').Process[]}
251
+ */
150
252
  ContextInstance.prototype.getProcesses = function getProcesses() {
151
253
  return this.definitionContext.getProcesses().map(({ id: processId }) => this.getProcessById(processId));
152
254
  };
153
255
 
256
+ /**
257
+ * Get processes flagged executable in the definition.
258
+ * @returns {import('#types').Process[]}
259
+ */
154
260
  ContextInstance.prototype.getExecutableProcesses = function getExecutableProcesses() {
155
261
  return this.definitionContext.getExecutableProcesses().map(({ id: processId }) => this.getProcessById(processId));
156
262
  };
157
263
 
264
+ /**
265
+ * Get message flows that originate from the given process id.
266
+ * @param {string} sourceId Source process id
267
+ * @returns {import('./flows/MessageFlow.js').MessageFlow[]}
268
+ */
158
269
  ContextInstance.prototype.getMessageFlows = function getMessageFlows(sourceId) {
159
270
  const messageFlowRefs = this.refs.get('messageFlows');
160
271
 
@@ -176,6 +287,11 @@ ContextInstance.prototype.getMessageFlows = function getMessageFlows(sourceId) {
176
287
  return result;
177
288
  };
178
289
 
290
+ /**
291
+ * Get or create a data object instance for the given reference id.
292
+ * @param {string} referenceId
293
+ * @return {import('#types').IIOData | undefined}
294
+ */
179
295
  ContextInstance.prototype.getDataObjectById = function getDataObjectById(referenceId) {
180
296
  const dataObjectRefs = this.refs.get('dataObjectRefs');
181
297
  let dataObject;
@@ -190,6 +306,11 @@ ContextInstance.prototype.getDataObjectById = function getDataObjectById(referen
190
306
  return dataObject;
191
307
  };
192
308
 
309
+ /**
310
+ * Get or create a data store instance for the given reference id.
311
+ * @param {string} referenceId
312
+ * @return {import('#types').IIOData | undefined}
313
+ */
193
314
  ContextInstance.prototype.getDataStoreById = function getDataStoreById(referenceId) {
194
315
  const dataStoreRefs = this.refs.get('dataStoreRefs');
195
316
  let dataStore;
@@ -205,6 +326,11 @@ ContextInstance.prototype.getDataStoreById = function getDataStoreById(reference
205
326
  return dataStore;
206
327
  };
207
328
 
329
+ /**
330
+ * Get start activities, optionally filtered by referenced event definition or restricted to a parent scope.
331
+ * @param {import('#types').startActivityFilterOptions} [filterOptions]
332
+ * @param {string} [scopeId] Process or sub-process id
333
+ */
208
334
  ContextInstance.prototype.getStartActivities = function getStartActivities(filterOptions, scopeId) {
209
335
  const referenceId = filterOptions?.referenceId;
210
336
  const referenceType = filterOptions?.referenceType || 'unknown';
@@ -227,6 +353,56 @@ ContextInstance.prototype.getStartActivities = function getStartActivities(filte
227
353
  return result;
228
354
  };
229
355
 
356
+ /**
357
+ * Inspect an activity def for link event definitions.
358
+ * @param {import('moddle-context-serializer').Activity} activityDef
359
+ * @returns {{ linkBehaviour?: Function, linkNames?: string[] }}
360
+ */
361
+ ContextInstance.prototype.getLinkEventDefinitionInfo = function getLinkEventDefinitionInfo(activityDef) {
362
+ const eds = activityDef.behaviour?.eventDefinitions;
363
+ if (!eds) return {};
364
+ let linkBehaviour;
365
+ const names = new Set();
366
+ for (const ed of eds) {
367
+ if (linkBehaviour ? ed.Behaviour === linkBehaviour : ed.type?.endsWith('LinkEventDefinition')) {
368
+ if (!linkBehaviour) linkBehaviour = ed.Behaviour;
369
+ if (ed.behaviour?.name) names.add(ed.behaviour.name);
370
+ }
371
+ }
372
+ if (!linkBehaviour || !names.size) return {};
373
+ return { linkBehaviour, linkNames: [...names] };
374
+ };
375
+
376
+ /**
377
+ * Get activities whose event definitions include the given Behaviour with a matching name.
378
+ * @param {Function} Behaviour Behaviour constructor to match against `ed.Behaviour`
379
+ * @param {string[] | Iterable<string>} names
380
+ * @param {string} [scopeId] Process or sub-process id
381
+ */
382
+ ContextInstance.prototype.getActivitiesByEventDefinitionBehaviour = function getActivitiesByEventDefinitionBehaviour(
383
+ Behaviour,
384
+ names,
385
+ scopeId
386
+ ) {
387
+ const wanted = new Set(names);
388
+ if (!Behaviour || !wanted.size) return [];
389
+ const result = [];
390
+ const rawDefs = this.definitionContext.getActivities(scopeId) || [];
391
+ for (const rawDef of rawDefs) {
392
+ const eds = rawDef.behaviour?.eventDefinitions;
393
+ if (!eds) continue;
394
+ if (!eds.some((ed) => ed.Behaviour === Behaviour && wanted.has(ed.behaviour?.name))) continue;
395
+ result.push(this.upsertActivity(rawDef));
396
+ }
397
+ return result;
398
+ };
399
+
400
+ /**
401
+ * Resolve user-registered extensions and the built-in BpmnIO extension for an activity.
402
+ * Returns undefined when the activity has no extensions to attach.
403
+ * @param {import('#types').ElementBase} activity
404
+ * @returns {import('#types').IExtension | undefined}
405
+ */
230
406
  ContextInstance.prototype.loadExtensions = function loadExtensions(activity) {
231
407
  const io = new BpmnIO(activity, this);
232
408
  const extensions = this.extensionsMapper.get(activity);
@@ -235,8 +411,12 @@ ContextInstance.prototype.loadExtensions = function loadExtensions(activity) {
235
411
  return extensions;
236
412
  };
237
413
 
414
+ /**
415
+ * Resolve the parent process or sub-process activity that owns the given activity.
416
+ * @param {string} activityId
417
+ */
238
418
  ContextInstance.prototype.getActivityParentById = function getActivityParentById(activityId) {
239
- const owner = this[kOwner];
419
+ const owner = this[K_OWNER];
240
420
  if (owner) return owner;
241
421
  const activity = this.getActivityById(activityId);
242
422
  const parentId = activity.parent.id;
@@ -251,6 +431,7 @@ ExtensionsMapper.prototype.get = function get(activity) {
251
431
  return new Extensions(activity, this.context, this._getExtensions());
252
432
  };
253
433
 
434
+ /** @internal */
254
435
  ExtensionsMapper.prototype._getExtensions = function getExtensions() {
255
436
  let extensions;
256
437
  if (!(extensions = this.context.environment.extensions)) return [];
@@ -263,7 +444,7 @@ function Extensions(activity, context, extensions) {
263
444
  const extension = Extension(activity, context);
264
445
  if (extension) result.push(extension);
265
446
  }
266
- this[kActivated] = false;
447
+ this[K_ACTIVATED] = false;
267
448
  }
268
449
 
269
450
  Object.defineProperty(Extensions.prototype, 'count', {
@@ -273,13 +454,13 @@ Object.defineProperty(Extensions.prototype, 'count', {
273
454
  });
274
455
 
275
456
  Extensions.prototype.activate = function activate(message) {
276
- if (this[kActivated]) return;
277
- this[kActivated] = true;
457
+ if (this[K_ACTIVATED]) return;
458
+ this[K_ACTIVATED] = true;
278
459
  for (const extension of this.extensions) extension.activate(message);
279
460
  };
280
461
 
281
462
  Extensions.prototype.deactivate = function deactivate(message) {
282
- if (!this[kActivated]) return;
283
- this[kActivated] = false;
463
+ if (!this[K_ACTIVATED]) return;
464
+ this[K_ACTIVATED] = false;
284
465
  for (const extension of this.extensions) extension.deactivate(message);
285
466
  };
@@ -1,69 +1,96 @@
1
- import Expressions from './Expressions.js';
1
+ import { Expressions } from './Expressions.js';
2
2
  import { Scripts } from './Scripts.js';
3
3
  import { Timers } from './Timers.js';
4
4
 
5
- const kServices = Symbol.for('services');
6
- const kVariables = Symbol.for('variables');
5
+ const K_SERVICES = Symbol.for('services');
6
+ const K_VARIABLES = Symbol.for('variables');
7
7
 
8
8
  const defaultOptions = new Set(['expressions', 'extensions', 'Logger', 'output', 'scripts', 'services', 'settings', 'timers', 'variables']);
9
9
 
10
- export default function Environment(options = {}) {
10
+ /**
11
+ * Holds global execution config: variables, injected services, timers, scripts engine,
12
+ * expressions, Logger factory, and settings such as `batchSize`. Cloned and merged per Definition.
13
+ * @param {import('#types').EnvironmentOptions} [options]
14
+ */
15
+ export function Environment(options = {}) {
11
16
  this.options = validateOptions(options);
12
17
 
18
+ /** @type {import('#types').IExpressions} */
13
19
  this.expressions = options.expressions || Expressions();
14
20
  this.extensions = options.extensions;
15
21
  this.output = options.output || {};
22
+ /** @type {import('#types').IScripts} */
16
23
  this.scripts = options.scripts || new Scripts();
24
+ /** @type {import('#types').ITimers} */
17
25
  this.timers = options.timers || new Timers();
26
+ /** @type {import('#types').EnvironmentSettings} */
18
27
  this.settings = { ...options.settings };
28
+ /** @type {import('#types').LoggerFactory} */
19
29
  this.Logger = options.Logger || DummyLogger;
20
- this[kServices] = options.services || {};
21
- this[kVariables] = options.variables || {};
30
+ this[K_SERVICES] = options.services || {};
31
+ this[K_VARIABLES] = options.variables || {};
22
32
  }
23
33
 
24
- Object.defineProperties(Environment.prototype, {
25
- variables: {
26
- get() {
27
- return this[kVariables];
28
- },
34
+ Object.defineProperty(Environment.prototype, 'variables', {
35
+ /** @returns {Record<string, any>} */
36
+ get() {
37
+ return this[K_VARIABLES];
29
38
  },
30
- services: {
31
- get() {
32
- return this[kServices];
33
- },
34
- set(value) {
35
- const services = this[kServices];
36
- for (const name in services) {
37
- if (!(name in value)) delete services[name];
38
- }
39
- Object.assign(services, value);
40
- },
39
+ });
40
+
41
+ Object.defineProperty(Environment.prototype, 'services', {
42
+ /** @returns {Record<string, CallableFunction>} */
43
+ get() {
44
+ return this[K_SERVICES];
45
+ },
46
+ set(value) {
47
+ const services = this[K_SERVICES];
48
+ for (const name in services) {
49
+ if (!(name in value)) delete services[name];
50
+ }
51
+ Object.assign(services, value);
41
52
  },
42
53
  });
43
54
 
55
+ /**
56
+ * Snapshot environment state for recover.
57
+ * @returns {import('#types').EnvironmentState}
58
+ */
44
59
  Environment.prototype.getState = function getState() {
45
60
  return {
46
61
  settings: { ...this.settings },
47
- variables: { ...this[kVariables] },
62
+ variables: { ...this[K_VARIABLES] },
48
63
  output: { ...this.output },
49
64
  };
50
65
  };
51
66
 
67
+ /**
68
+ * Restore environment state captured by getState. Merges into the existing settings,
69
+ * variables, and output rather than replacing them.
70
+ * @param {import('#types').EnvironmentState} [state]
71
+ * @returns {this}
72
+ */
52
73
  Environment.prototype.recover = function recover(state) {
53
74
  if (!state) return this;
54
75
 
55
76
  if (state.settings) Object.assign(this.settings, state.settings);
56
- if (state.variables) Object.assign(this[kVariables], state.variables);
77
+ if (state.variables) Object.assign(this[K_VARIABLES], state.variables);
57
78
  if (state.output) Object.assign(this.output, state.output);
58
79
 
59
80
  return this;
60
81
  };
61
82
 
83
+ /**
84
+ * Clone the environment, optionally overriding options. Services are merged when
85
+ * `overrideOptions.services` is supplied.
86
+ * @param {import('#types').EnvironmentOptions} [overrideOptions]
87
+ * @returns {Environment}
88
+ */
62
89
  Environment.prototype.clone = function clone(overrideOptions) {
63
- const services = this[kServices];
90
+ const services = this[K_SERVICES];
64
91
  const newOptions = {
65
92
  settings: { ...this.settings },
66
- variables: { ...this[kVariables] },
93
+ variables: { ...this[K_VARIABLES] },
67
94
  Logger: this.Logger,
68
95
  extensions: this.extensions,
69
96
  scripts: this.scripts,
@@ -79,36 +106,66 @@ Environment.prototype.clone = function clone(overrideOptions) {
79
106
  return new this.constructor(newOptions);
80
107
  };
81
108
 
109
+ /**
110
+ * Merge variables into the environment. Non-objects are ignored.
111
+ * @param {Record<string, any>} newVars
112
+ */
82
113
  Environment.prototype.assignVariables = function assignVariables(newVars) {
83
114
  if (!newVars || typeof newVars !== 'object') return;
84
115
 
85
- this[kVariables] = {
116
+ this[K_VARIABLES] = {
86
117
  ...this.variables,
87
118
  ...newVars,
88
119
  };
89
120
  };
90
121
 
122
+ /**
123
+ * Merge settings into the environment. Non-objects are ignored.
124
+ * @param {import('#types').EnvironmentSettings} newSettings
125
+ * @returns {this}
126
+ */
91
127
  Environment.prototype.assignSettings = function assignSettings(newSettings) {
92
- if (!newSettings || typeof newSettings !== 'object') return;
128
+ if (!newSettings || typeof newSettings !== 'object') return this;
93
129
 
94
130
  this.settings = {
95
131
  ...this.settings,
96
132
  ...newSettings,
97
133
  };
134
+
135
+ return this;
98
136
  };
99
137
 
138
+ /**
139
+ * Resolve a registered script by language and identifier.
140
+ * @param {string} language
141
+ * @param {{ id: string, [x: string]: any }} identifier
142
+ */
100
143
  Environment.prototype.getScript = function getScript(...args) {
101
144
  return this.scripts.getScript(...args);
102
145
  };
103
146
 
147
+ /**
148
+ * Register a script for an activity, delegating to the configured scripts engine.
149
+ * @param {any} activity
150
+ */
104
151
  Environment.prototype.registerScript = function registerScript(...args) {
105
152
  return this.scripts.register(...args);
106
153
  };
107
154
 
155
+ /**
156
+ * Lookup a registered service by name.
157
+ * @param {string} serviceName
158
+ */
108
159
  Environment.prototype.getServiceByName = function getServiceByName(serviceName) {
109
- return this[kServices][serviceName];
160
+ return this[K_SERVICES][serviceName];
110
161
  };
111
162
 
163
+ /**
164
+ * Resolve an expression with the environment as scope, optionally extended by an element message.
165
+ * @param {string} expression
166
+ * @param {import('#types').ElementBrokerMessage} [message] Element message merged onto the resolution scope
167
+ * @param {any} [expressionFnContext]
168
+ */
112
169
  Environment.prototype.resolveExpression = function resolveExpression(expression, message, expressionFnContext) {
113
170
  const from = {
114
171
  environment: this,
@@ -118,10 +175,19 @@ Environment.prototype.resolveExpression = function resolveExpression(expression,
118
175
  return this.expressions.resolveExpression(expression, from, expressionFnContext);
119
176
  };
120
177
 
178
+ /**
179
+ * Register a service callable by name.
180
+ * @param {string} name service function name
181
+ * @param {CallableFunction} fn service function
182
+ */
121
183
  Environment.prototype.addService = function addService(name, fn) {
122
- this[kServices][name] = fn;
184
+ this[K_SERVICES][name] = fn;
123
185
  };
124
186
 
187
+ /**
188
+ * @param {import('#types').EnvironmentOptions} input
189
+ * @returns {import('#types').EnvironmentOptions} validated options
190
+ */
125
191
  function validateOptions(input) {
126
192
  const options = {};
127
193
  for (const key in input) {
@@ -151,6 +217,9 @@ function validateOptions(input) {
151
217
  return options;
152
218
  }
153
219
 
220
+ /**
221
+ * @returns {import('#types').ILogger}
222
+ */
154
223
  function DummyLogger() {
155
224
  return {
156
225
  debug,