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
@@ -1,22 +1,38 @@
1
- import Activity from '../activity/Activity.js';
2
- import EventDefinitionExecution from '../eventDefinitions/EventDefinitionExecution.js';
1
+ import { Activity } from '../activity/Activity.js';
2
+ import { EventDefinitionExecution } from '../eventDefinitions/EventDefinitionExecution.js';
3
3
  import { cloneContent } from '../messageHelper.js';
4
+ import { K_EXECUTION } from '../constants.js';
4
5
 
5
- const kExecution = Symbol.for('execution');
6
-
7
- export default function IntermediateCatchEvent(activityDef, context) {
8
- return new Activity(IntermediateCatchEventBehaviour, activityDef, context);
6
+ /**
7
+ * Intermediate catch event
8
+ * @param {import('moddle-context-serializer').Activity} activityDef
9
+ * @param {import('#types').ContextInstance} context
10
+ */
11
+ export function IntermediateCatchEvent(activityDef, context) {
12
+ return new Activity(
13
+ IntermediateCatchEventBehaviour,
14
+ { ...activityDef, isCatching: true, ...context.getLinkEventDefinitionInfo(activityDef) },
15
+ context
16
+ );
9
17
  }
10
18
 
19
+ /**
20
+ * Intermediate catch event behaviour
21
+ * @param {import('#types').Activity} activity
22
+ */
11
23
  export function IntermediateCatchEventBehaviour(activity) {
12
24
  this.id = activity.id;
13
25
  this.type = activity.type;
14
26
  this.broker = activity.broker;
15
- this[kExecution] = activity.eventDefinitions && new EventDefinitionExecution(activity, activity.eventDefinitions);
27
+ this[K_EXECUTION] = activity.eventDefinitions && new EventDefinitionExecution(activity, activity.eventDefinitions);
16
28
  }
17
29
 
30
+ /**
31
+ * @param {import('#types').ElementBrokerMessage} executeMessage
32
+ * @returns {void}
33
+ */
18
34
  IntermediateCatchEventBehaviour.prototype.execute = function execute(executeMessage) {
19
- const execution = this[kExecution];
35
+ const execution = this[K_EXECUTION];
20
36
  if (execution) {
21
37
  return execution.execute(executeMessage);
22
38
  }
@@ -1,22 +1,38 @@
1
- import Activity from '../activity/Activity.js';
2
- import EventDefinitionExecution from '../eventDefinitions/EventDefinitionExecution.js';
1
+ import { Activity } from '../activity/Activity.js';
2
+ import { EventDefinitionExecution } from '../eventDefinitions/EventDefinitionExecution.js';
3
3
  import { cloneContent } from '../messageHelper.js';
4
+ import { K_EXECUTION } from '../constants.js';
4
5
 
5
- const kExecution = Symbol.for('execution');
6
-
7
- export default function IntermediateThrowEvent(activityDef, context) {
8
- return new Activity(IntermediateThrowEventBehaviour, { ...activityDef, isThrowing: true }, context);
6
+ /**
7
+ * Intermediate throw event
8
+ * @param {import('moddle-context-serializer').Activity} activityDef
9
+ * @param {import('#types').ContextInstance} context
10
+ */
11
+ export function IntermediateThrowEvent(activityDef, context) {
12
+ return new Activity(
13
+ IntermediateThrowEventBehaviour,
14
+ { ...activityDef, isThrowing: true, ...context.getLinkEventDefinitionInfo(activityDef) },
15
+ context
16
+ );
9
17
  }
10
18
 
19
+ /**
20
+ * Intermediate throw event behaviour
21
+ * @param {import('#types').Activity} activity
22
+ */
11
23
  export function IntermediateThrowEventBehaviour(activity) {
12
24
  this.id = activity.id;
13
25
  this.type = activity.type;
14
26
  this.broker = activity.broker;
15
- this[kExecution] = activity.eventDefinitions && new EventDefinitionExecution(activity, activity.eventDefinitions);
27
+ this[K_EXECUTION] = activity.eventDefinitions && new EventDefinitionExecution(activity, activity.eventDefinitions);
16
28
  }
17
29
 
30
+ /**
31
+ * @param {import('#types').ElementBrokerMessage} executeMessage
32
+ * @returns {void}
33
+ */
18
34
  IntermediateThrowEventBehaviour.prototype.execute = function execute(executeMessage) {
19
- const execution = this[kExecution];
35
+ const execution = this[K_EXECUTION];
20
36
  if (execution) {
21
37
  return execution.execute(executeMessage);
22
38
  }
@@ -1,30 +1,41 @@
1
- import Activity from '../activity/Activity.js';
2
- import EventDefinitionExecution from '../eventDefinitions/EventDefinitionExecution.js';
1
+ import { Activity } from '../activity/Activity.js';
2
+ import { EventDefinitionExecution } from '../eventDefinitions/EventDefinitionExecution.js';
3
3
  import { cloneContent } from '../messageHelper.js';
4
+ import { K_EXECUTE_MESSAGE, K_EXECUTION } from '../constants.js';
4
5
 
5
- const kExecuteMessage = Symbol.for('executeMessage');
6
- const kExecution = Symbol.for('execution');
7
-
8
- export default function StartEvent(activityDef, context) {
9
- return new Activity(StartEventBehaviour, activityDef, context);
6
+ /**
7
+ * Start event
8
+ * @param {import('moddle-context-serializer').Activity} activityDef
9
+ * @param {import('#types').ContextInstance} context
10
+ */
11
+ export function StartEvent(activityDef, context) {
12
+ return new Activity(StartEventBehaviour, { ...activityDef, isStartEvent: true }, context);
10
13
  }
11
14
 
15
+ /**
16
+ * Start event behaviour
17
+ * @param {import('#types').Activity} activity
18
+ */
12
19
  export function StartEventBehaviour(activity) {
13
20
  this.id = activity.id;
14
21
  this.type = activity.type;
15
22
  this.activity = activity;
16
23
  this.broker = activity.broker;
17
- this[kExecution] = activity.eventDefinitions && new EventDefinitionExecution(activity, activity.eventDefinitions);
24
+ this[K_EXECUTION] = activity.eventDefinitions && new EventDefinitionExecution(activity, activity.eventDefinitions);
18
25
  }
19
26
 
20
27
  Object.defineProperty(StartEventBehaviour.prototype, 'executionId', {
21
28
  get() {
22
- return this[kExecuteMessage]?.content.executionId;
29
+ return this[K_EXECUTE_MESSAGE]?.content.executionId;
23
30
  },
24
31
  });
25
32
 
33
+ /**
34
+ * @param {import('#types').ElementBrokerMessage} executeMessage
35
+ * @returns {void}
36
+ */
26
37
  StartEventBehaviour.prototype.execute = function execute(executeMessage) {
27
- const execution = this[kExecution];
38
+ const execution = this[K_EXECUTION];
28
39
  if (execution) {
29
40
  return execution.execute(executeMessage);
30
41
  }
@@ -36,7 +47,7 @@ StartEventBehaviour.prototype.execute = function execute(executeMessage) {
36
47
  }
37
48
 
38
49
  const executionId = content.executionId;
39
- this[kExecuteMessage] = executeMessage;
50
+ this[K_EXECUTE_MESSAGE] = executeMessage;
40
51
  broker.subscribeTmp('api', `activity.#.${executionId}`, (...args) => this._onApiMessage(...args), {
41
52
  noAck: true,
42
53
  consumerTag: `_api-${executionId}`,
@@ -56,7 +67,7 @@ StartEventBehaviour.prototype._onApiMessage = function onApiMessage(routingKey,
56
67
  return this._stop();
57
68
  case 'signal': {
58
69
  this._stop();
59
- const content = this[kExecuteMessage].content;
70
+ const content = this[K_EXECUTE_MESSAGE].content;
60
71
  return this.broker.publish(
61
72
  'execution',
62
73
  'execute.completed',
@@ -69,7 +80,7 @@ StartEventBehaviour.prototype._onApiMessage = function onApiMessage(routingKey,
69
80
  }
70
81
  case 'discard': {
71
82
  this._stop();
72
- const content = this[kExecuteMessage].content;
83
+ const content = this[K_EXECUTE_MESSAGE].content;
73
84
  return this.broker.publish('execution', 'execute.discard', cloneContent(content), { correlationId });
74
85
  }
75
86
  }
@@ -85,7 +96,7 @@ StartEventBehaviour.prototype._onDelegatedApiMessage = function onDelegatedApiMe
85
96
  if (signalId !== this.id && signalExecutionId !== this.executionId) return;
86
97
 
87
98
  const { type, correlationId } = message.properties;
88
- const executeContent = this[kExecuteMessage].content;
99
+ const executeContent = this[K_EXECUTE_MESSAGE].content;
89
100
  this.broker.publish(
90
101
  'event',
91
102
  'activity.consumed',
@@ -1,18 +1,5 @@
1
- import BoundaryEvent, { BoundaryEventBehaviour } from './BoundaryEvent.js';
2
- import EndEvent, { EndEventBehaviour } from './EndEvent.js';
3
- import IntermediateCatchEvent, { IntermediateCatchEventBehaviour } from './IntermediateCatchEvent.js';
4
- import IntermediateThrowEvent, { IntermediateThrowEventBehaviour } from './IntermediateThrowEvent.js';
5
- import StartEvent, { StartEventBehaviour } from './StartEvent.js';
6
-
7
- export {
8
- BoundaryEvent,
9
- BoundaryEventBehaviour,
10
- EndEvent,
11
- EndEventBehaviour,
12
- IntermediateCatchEvent,
13
- IntermediateCatchEventBehaviour,
14
- IntermediateThrowEvent,
15
- IntermediateThrowEventBehaviour,
16
- StartEvent,
17
- StartEventBehaviour,
18
- };
1
+ export { BoundaryEvent, BoundaryEventBehaviour } from './BoundaryEvent.js';
2
+ export { EndEvent, EndEventBehaviour } from './EndEvent.js';
3
+ export { IntermediateCatchEvent, IntermediateCatchEventBehaviour } from './IntermediateCatchEvent.js';
4
+ export { IntermediateThrowEvent, IntermediateThrowEventBehaviour } from './IntermediateThrowEvent.js';
5
+ export { StartEvent, StartEventBehaviour } from './StartEvent.js';
@@ -2,16 +2,22 @@ import { cloneParent } from '../messageHelper.js';
2
2
  import { EventBroker } from '../EventBroker.js';
3
3
  import { Api } from '../Api.js';
4
4
  import { getUniqueId } from '../shared.js';
5
-
6
- const kCounters = Symbol.for('counters');
7
-
8
- export default function Association(associationDef, { environment }) {
5
+ import { K_COUNTERS } from '../constants.js';
6
+
7
+ /**
8
+ * Association connecting a source and target activity. Used to drive compensation —
9
+ * activities marked `isForCompensation` subscribe to inbound association events.
10
+ * @param {import('moddle-context-serializer').Association} associationDef
11
+ * @param {import('#types').ContextInstance} context
12
+ */
13
+ export function Association(associationDef, { environment }) {
9
14
  const { id, type = 'association', name, parent, targetId, sourceId, behaviour = {} } = associationDef;
10
15
 
11
16
  this.id = id;
12
17
  this.type = type;
13
18
  this.name = name;
14
19
  this.parent = cloneParent(parent);
20
+ /** @type {Record<string, any>} */
15
21
  this.behaviour = behaviour;
16
22
  this.sourceId = sourceId;
17
23
  this.targetId = targetId;
@@ -19,7 +25,7 @@ export default function Association(associationDef, { environment }) {
19
25
  this.environment = environment;
20
26
  const logger = (this.logger = environment.Logger(type.toLowerCase()));
21
27
 
22
- this[kCounters] = {
28
+ this[K_COUNTERS] = {
23
29
  take: 0,
24
30
  discard: 0,
25
31
  };
@@ -34,29 +40,43 @@ export default function Association(associationDef, { environment }) {
34
40
  }
35
41
 
36
42
  Object.defineProperty(Association.prototype, 'counters', {
43
+ /** @returns {{ take: number, discard: number }} */
37
44
  get() {
38
- return { ...this[kCounters] };
45
+ return { ...this[K_COUNTERS] };
39
46
  },
40
47
  });
41
48
 
49
+ /**
50
+ * Take the association and publish association.take.
51
+ * @param {Record<string, any>} [content]
52
+ */
42
53
  Association.prototype.take = function take(content) {
43
54
  this.logger.debug(`<${this.id}> take target <${this.targetId}>`);
44
- ++this[kCounters].take;
55
+ ++this[K_COUNTERS].take;
45
56
 
46
57
  this._publishEvent('take', content);
47
58
 
48
59
  return true;
49
60
  };
50
61
 
62
+ /**
63
+ * Discard the association and publish association.discard.
64
+ * @param {Record<string, any>} [content]
65
+ */
51
66
  Association.prototype.discard = function discard(content) {
52
67
  this.logger.debug(`<${this.id}> discard target <${this.targetId}>`);
53
- ++this[kCounters].discard;
68
+ ++this[K_COUNTERS].discard;
54
69
 
55
70
  this._publishEvent('discard', content);
56
71
 
57
72
  return true;
58
73
  };
59
74
 
75
+ /**
76
+ * Snapshot association state. Returns undefined when broker has no state and
77
+ * `disableTrackState` is set.
78
+ * @returns {import('#types').AssociationState | undefined}
79
+ */
60
80
  Association.prototype.getState = function getState() {
61
81
  const brokerState = this.broker.getState(true);
62
82
  if (!brokerState && this.environment.settings.disableTrackState) return;
@@ -69,19 +89,32 @@ Association.prototype.getState = function getState() {
69
89
  };
70
90
  };
71
91
 
92
+ /**
93
+ * Restore association state captured by getState.
94
+ * @param {import('#types').AssociationState} state
95
+ */
72
96
  Association.prototype.recover = function recover(state) {
73
- Object.assign(this[kCounters], state.counters);
97
+ Object.assign(this[K_COUNTERS], state.counters);
74
98
  this.broker.recover(state.broker);
75
99
  };
76
100
 
101
+ /**
102
+ * Resolve an association-scoped Api wrapper.
103
+ * @param {import('#types').ElementBrokerMessage} [message]
104
+ * @returns {import('#types').IApi<this>}
105
+ */
77
106
  Association.prototype.getApi = function getApi(message) {
78
107
  return new Api('association', this.broker, message || { content: this._createMessageContent() });
79
108
  };
80
109
 
110
+ /**
111
+ * Stop the association's broker.
112
+ */
81
113
  Association.prototype.stop = function stop() {
82
114
  this.broker.stop();
83
115
  };
84
116
 
117
+ /** @internal */
85
118
  Association.prototype._publishEvent = function publishEvent(action, content) {
86
119
  const eventContent = this._createMessageContent({
87
120
  action,
@@ -92,6 +125,7 @@ Association.prototype._publishEvent = function publishEvent(action, content) {
92
125
  this.broker.publish('event', `association.${action}`, eventContent, { type: action });
93
126
  };
94
127
 
128
+ /** @internal */
95
129
  Association.prototype._createMessageContent = function createMessageContent(override) {
96
130
  return {
97
131
  ...override,
@@ -2,11 +2,18 @@ import { brokerSafeId } from '../shared.js';
2
2
  import { cloneParent } from '../messageHelper.js';
3
3
  import { MessageFlowBroker } from '../EventBroker.js';
4
4
  import { Api } from '../Api.js';
5
+ import { K_COUNTERS } from '../constants.js';
5
6
 
6
- const kCounters = Symbol.for('counters');
7
- const kSourceElement = Symbol.for('sourceElement');
7
+ const K_SOURCE_ELEMENT = Symbol.for('sourceElement');
8
8
 
9
- export default function MessageFlow(flowDef, context) {
9
+ /**
10
+ * Message flow connecting a source activity (or process) to a target. Subscribes to the
11
+ * source's `end` event and publishes `message.outbound` whenever the source completes,
12
+ * carrying any message payload through to the target.
13
+ * @param {import('moddle-context-serializer').MessageFlow} flowDef
14
+ * @param {import('#types').ContextInstance} context
15
+ */
16
+ export function MessageFlow(flowDef, context) {
10
17
  const { id, type = 'messageflow', name, target, source, behaviour, parent } = flowDef;
11
18
 
12
19
  this.id = id;
@@ -15,11 +22,12 @@ export default function MessageFlow(flowDef, context) {
15
22
  this.parent = cloneParent(parent);
16
23
  this.source = source;
17
24
  this.target = target;
25
+ /** @type {Record<string, any>} */
18
26
  this.behaviour = behaviour;
19
27
  this.environment = context.environment;
20
28
  this.context = context;
21
29
 
22
- this[kCounters] = {
30
+ this[K_COUNTERS] = {
23
31
  messages: 0,
24
32
  };
25
33
 
@@ -30,16 +38,22 @@ export default function MessageFlow(flowDef, context) {
30
38
  this.emit = emit;
31
39
  this.waitFor = waitFor;
32
40
 
33
- this[kSourceElement] = context.getActivityById(source.id) || context.getProcessById(source.processId);
41
+ this[K_SOURCE_ELEMENT] = context.getActivityById(source.id) || context.getProcessById(source.processId);
34
42
  this.logger = context.environment.Logger(type.toLowerCase());
35
43
  }
36
44
 
37
45
  Object.defineProperty(MessageFlow.prototype, 'counters', {
46
+ /** @returns {{ messages: number }} */
38
47
  get() {
39
- return { ...this[kCounters] };
48
+ return { ...this[K_COUNTERS] };
40
49
  },
41
50
  });
42
51
 
52
+ /**
53
+ * Snapshot message-flow state. Returns undefined when broker has no state and
54
+ * `disableTrackState` is set.
55
+ * @returns {import('#types').MessageFlowState | undefined}
56
+ */
43
57
  MessageFlow.prototype.getState = function getState() {
44
58
  const brokerState = this.broker.getState(true);
45
59
  if (!brokerState && this.environment.settings.disableTrackState) return;
@@ -52,31 +66,47 @@ MessageFlow.prototype.getState = function getState() {
52
66
  };
53
67
  };
54
68
 
69
+ /**
70
+ * Restore message-flow state captured by getState.
71
+ * @param {import('#types').MessageFlowState} state
72
+ */
55
73
  MessageFlow.prototype.recover = function recover(state) {
56
- Object.assign(this[kCounters], state.counters);
74
+ Object.assign(this[K_COUNTERS], state.counters);
57
75
  this.broker.recover(state.broker);
58
76
  };
59
77
 
78
+ /**
79
+ * Resolve a message-scoped Api wrapper.
80
+ * @param {import('#types').ElementBrokerMessage} [message]
81
+ * @returns {import('#types').IApi<this>}
82
+ */
60
83
  MessageFlow.prototype.getApi = function getApi(message) {
61
84
  return new Api('message', this.broker, message || { content: this._createMessageContent() });
62
85
  };
63
86
 
87
+ /**
88
+ * Subscribe to the source element's message and end events to bridge the message across.
89
+ */
64
90
  MessageFlow.prototype.activate = function activate() {
65
- const sourceElement = this[kSourceElement];
91
+ const sourceElement = this[K_SOURCE_ELEMENT];
66
92
  const safeId = brokerSafeId(this.id);
67
93
  sourceElement.on('message', this.deactivate.bind(this), { consumerTag: `_message-on-message-${safeId}` });
68
94
  sourceElement.on('end', this._onSourceEnd.bind(this), { consumerTag: `_message-on-end-${safeId}` });
69
95
  };
70
96
 
97
+ /**
98
+ * Cancel the source element subscriptions added by activate.
99
+ */
71
100
  MessageFlow.prototype.deactivate = function deactivate() {
72
- const sourceElement = this[kSourceElement];
101
+ const sourceElement = this[K_SOURCE_ELEMENT];
73
102
  const safeId = brokerSafeId(this.id);
74
103
  sourceElement.broker.cancel(`_message-on-end-${safeId}`);
75
104
  sourceElement.broker.cancel(`_message-on-message-${safeId}`);
76
105
  };
77
106
 
107
+ /** @internal */
78
108
  MessageFlow.prototype._onSourceEnd = function onSourceEnd({ content }) {
79
- ++this[kCounters].messages;
109
+ ++this[K_COUNTERS].messages;
80
110
  const source = this.source;
81
111
  const target = this.target;
82
112
  this.logger.debug(
@@ -85,6 +115,7 @@ MessageFlow.prototype._onSourceEnd = function onSourceEnd({ content }) {
85
115
  this.broker.publish('event', 'message.outbound', this._createMessageContent(content.message));
86
116
  };
87
117
 
118
+ /** @internal */
88
119
  MessageFlow.prototype._createMessageContent = function createMessage(message) {
89
120
  return {
90
121
  id: this.id,
@@ -3,18 +3,22 @@ import { getUniqueId } from '../shared.js';
3
3
  import { EventBroker } from '../EventBroker.js';
4
4
  import { FlowApi } from '../Api.js';
5
5
  import { ScriptCondition, ExpressionCondition } from '../condition.js';
6
-
7
- const kCounters = Symbol.for('counters');
8
-
9
- export default SequenceFlow;
10
-
11
- function SequenceFlow(flowDef, { environment }) {
6
+ import { K_COUNTERS } from '../constants.js';
7
+
8
+ /**
9
+ * Sequence flow connecting two activities. Owns its broker and publishes take/discard/looped
10
+ * events; activities subscribe to drive their inbound queue.
11
+ * @param {import('moddle-context-serializer').SequenceFlow} flowDef
12
+ * @param {import('#types').ContextInstance} context
13
+ */
14
+ export function SequenceFlow(flowDef, { environment }) {
12
15
  const { id, type = 'sequenceflow', name, parent, targetId, sourceId, isDefault, behaviour = {} } = flowDef;
13
16
 
14
17
  this.id = id;
15
18
  this.type = type;
16
19
  this.name = name;
17
20
  this.parent = cloneParent(parent);
21
+ /** @type {Record<string, any>} */
18
22
  this.behaviour = behaviour;
19
23
  this.sourceId = sourceId;
20
24
  this.targetId = targetId;
@@ -23,7 +27,7 @@ function SequenceFlow(flowDef, { environment }) {
23
27
  this.environment = environment;
24
28
  const logger = (this.logger = environment.Logger(type.toLowerCase()));
25
29
 
26
- this[kCounters] = {
30
+ this[K_COUNTERS] = {
27
31
  looped: 0,
28
32
  take: 0,
29
33
  discard: 0,
@@ -42,27 +46,38 @@ function SequenceFlow(flowDef, { environment }) {
42
46
  }
43
47
 
44
48
  Object.defineProperty(SequenceFlow.prototype, 'counters', {
49
+ /** @returns {{ take: number, discard: number, looped: number }} */
45
50
  get() {
46
- return { ...this[kCounters] };
51
+ return { ...this[K_COUNTERS] };
47
52
  },
48
53
  });
49
54
 
55
+ /**
56
+ * Take the flow and publish flow.take.
57
+ * @param {Record<string, any>} [content]
58
+ */
50
59
  SequenceFlow.prototype.take = function take(content) {
51
60
  const sequenceId = content?.sequenceId;
52
61
 
53
62
  this.logger.debug(`<${sequenceId} (${this.id})> take, target <${this.targetId}>`);
54
- ++this[kCounters].take;
63
+ ++this[K_COUNTERS].take;
55
64
 
56
65
  this._publishEvent('take', content);
57
66
 
58
67
  return true;
59
68
  };
60
69
 
70
+ /**
71
+ * Discard the flow and publish flow.discard.
72
+ *
73
+ * @deprecated The execution runtime no longer discards sequence flows, so this is a no-op during a run. It will be removed in a future version.
74
+ * @param {Record<string, any>} [content]
75
+ */
61
76
  SequenceFlow.prototype.discard = function discard(content = {}) {
62
77
  const sequenceId = content?.sequenceId ?? getUniqueId(this.id);
63
- const discardSequence = (content.discardSequence = (content.discardSequence || []).slice());
78
+ const discardSequence = (content.discardSequence = content.discardSequence?.slice() || []);
64
79
  if (discardSequence.indexOf(this.targetId) > -1) {
65
- ++this[kCounters].looped;
80
+ ++this[K_COUNTERS].looped;
66
81
  this.logger.debug(`<${this.id}> discard loop detected <${this.sourceId}> -> <${this.targetId}>. Stop.`);
67
82
  return this._publishEvent('looped', content);
68
83
  }
@@ -70,10 +85,15 @@ SequenceFlow.prototype.discard = function discard(content = {}) {
70
85
  discardSequence.push(this.sourceId);
71
86
 
72
87
  this.logger.debug(`<${sequenceId} (${this.id})> discard, target <${this.targetId}>`);
73
- ++this[kCounters].discard;
88
+ ++this[K_COUNTERS].discard;
74
89
  this._publishEvent('discard', content);
75
90
  };
76
91
 
92
+ /**
93
+ * Snapshot flow state. Returns undefined when the broker has no state and `disableTrackState`
94
+ * is set.
95
+ * @returns {import('#types').SequenceFlowState | undefined}
96
+ */
77
97
  SequenceFlow.prototype.getState = function getState() {
78
98
  const brokerState = this.broker.getState(true);
79
99
  if (!brokerState && this.environment.settings.disableTrackState) return;
@@ -86,33 +106,65 @@ SequenceFlow.prototype.getState = function getState() {
86
106
  };
87
107
  };
88
108
 
109
+ /**
110
+ * Restore flow state captured by getState.
111
+ * @param {import('#types').SequenceFlowState} state
112
+ */
89
113
  SequenceFlow.prototype.recover = function recover(state) {
90
- Object.assign(this[kCounters], state.counters);
114
+ Object.assign(this[K_COUNTERS], state.counters);
91
115
  this.broker.recover(state.broker);
92
116
  };
93
117
 
118
+ /**
119
+ * Resolve a Flow Api wrapper.
120
+ * @param {import('#types').ElementBrokerMessage} [message]
121
+ * @returns {import('#types').IApi<this>}
122
+ */
94
123
  SequenceFlow.prototype.getApi = function getApi(message) {
95
124
  return FlowApi(this.broker, message || { content: this.createMessage() });
96
125
  };
97
126
 
127
+ /**
128
+ * Stop the flow's broker.
129
+ */
98
130
  SequenceFlow.prototype.stop = function stop() {
99
131
  this.broker.stop();
100
132
  };
101
133
 
134
+ /**
135
+ * Walk the flow as part of a process shake. Detects loops and publishes flow.shake.loop
136
+ * when the target was already visited, otherwise flow.shake.
137
+ * @param {import('#types').ElementBrokerMessage} message
138
+ */
102
139
  SequenceFlow.prototype.shake = function shake(message) {
103
140
  const content = cloneContent(message.content);
141
+
104
142
  content.sequence = content.sequence || [];
105
- content.sequence.push({ id: this.id, type: this.type, isSequenceFlow: true, targetId: this.targetId });
106
143
 
107
- if (content.id === this.targetId) return this.broker.publish('event', 'flow.shake.loop', content, { persistent: false, type: 'shake' });
144
+ const info = {
145
+ id: this.id,
146
+ type: this.type,
147
+ isSequenceFlow: true,
148
+ sourceId: this.sourceId,
149
+ targetId: this.targetId,
150
+ };
108
151
 
109
- for (const s of message.content.sequence || []) {
110
- if (s.id === this.id) return this.broker.publish('event', 'flow.shake.loop', content, { persistent: false, type: 'shake' });
152
+ if (content.id === this.targetId) {
153
+ content.sequence.push(info);
154
+ return this.broker.publish('event', 'flow.shake.loop', content, { persistent: false, type: 'shake' });
155
+ } else if (content.sequence?.find((f) => f.id === this.id)) {
156
+ return this.broker.publish('event', 'flow.shake.loop', content, { persistent: false, type: 'shake' });
157
+ } else {
158
+ content.sequence.push(info);
159
+ this.broker.publish('event', 'flow.shake', content, { persistent: false, type: 'shake' });
111
160
  }
112
-
113
- this.broker.publish('event', 'flow.shake', content, { persistent: false, type: 'shake' });
114
161
  };
115
162
 
163
+ /**
164
+ * Resolve the flow's condition (script or expression). Returns null when no condition is set.
165
+ * Emits a fatal error when the script language is missing or unsupported.
166
+ * @returns {import('#types').ICondition | null}
167
+ */
116
168
  SequenceFlow.prototype.getCondition = function getCondition() {
117
169
  const conditionExpression = this.behaviour.conditionExpression;
118
170
  if (!conditionExpression) return null;
@@ -133,6 +185,11 @@ SequenceFlow.prototype.getCondition = function getCondition() {
133
185
  return new ExpressionCondition(this, conditionExpression.body);
134
186
  };
135
187
 
188
+ /**
189
+ * Build a flow event message body, optionally merging override content.
190
+ * @param {Record<string, any>} [override]
191
+ * @returns {import('#types').ElementMessageContent}
192
+ */
136
193
  SequenceFlow.prototype.createMessage = function createMessage(override) {
137
194
  return {
138
195
  ...override,
@@ -147,6 +204,11 @@ SequenceFlow.prototype.createMessage = function createMessage(override) {
147
204
  };
148
205
  };
149
206
 
207
+ /**
208
+ * Evaluate the flow's condition for the source activity message. Default flows are always taken.
209
+ * @param {import('#types').ElementBrokerMessage} fromMessage Source activity message
210
+ * @param {(err: Error | null, result?: boolean | unknown) => void} callback Callback with truthy result if flow should be taken
211
+ */
150
212
  SequenceFlow.prototype.evaluate = function evaluate(fromMessage, callback) {
151
213
  if (this.isDefault) {
152
214
  return callback(null, true);
@@ -160,6 +222,7 @@ SequenceFlow.prototype.evaluate = function evaluate(fromMessage, callback) {
160
222
  flowCondition.execute(fromMessage, callback);
161
223
  };
162
224
 
225
+ /** @internal */
163
226
  SequenceFlow.prototype._publishEvent = function publishEvent(action, content) {
164
227
  const eventContent = this.createMessage({
165
228
  action,
@@ -1,5 +1,4 @@
1
- import Association from './Association.js';
2
- import MessageFlow from './MessageFlow.js';
3
- import SequenceFlow from './SequenceFlow.js';
4
-
1
+ import { Association } from './Association.js';
2
+ import { MessageFlow } from './MessageFlow.js';
3
+ import { SequenceFlow } from './SequenceFlow.js';
5
4
  export { Association, MessageFlow, SequenceFlow };