bpmn-elements 16.1.0 → 16.2.1

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 (69) hide show
  1. package/dist/Api.js +1 -1
  2. package/dist/Context.js +2 -4
  3. package/dist/Environment.js +3 -3
  4. package/dist/EventBroker.js +1 -1
  5. package/dist/MessageFormatter.js +2 -2
  6. package/dist/Tracker.js +1 -0
  7. package/dist/activity/Activity.js +67 -163
  8. package/dist/activity/ActivityExecution.js +2 -2
  9. package/dist/activity/outbound-evaluator.js +131 -0
  10. package/dist/definition/Definition.js +4 -4
  11. package/dist/definition/DefinitionExecution.js +6 -6
  12. package/dist/error/Errors.js +7 -10
  13. package/dist/eventDefinitions/CancelEventDefinition.js +1 -2
  14. package/dist/eventDefinitions/CompensateEventDefinition.js +2 -3
  15. package/dist/eventDefinitions/ConditionalEventDefinition.js +2 -3
  16. package/dist/eventDefinitions/ErrorEventDefinition.js +3 -4
  17. package/dist/eventDefinitions/EscalationEventDefinition.js +1 -2
  18. package/dist/eventDefinitions/LinkEventDefinition.js +1 -2
  19. package/dist/eventDefinitions/MessageEventDefinition.js +2 -3
  20. package/dist/eventDefinitions/SignalEventDefinition.js +2 -3
  21. package/dist/eventDefinitions/TimerEventDefinition.js +2 -3
  22. package/dist/events/BoundaryEvent.js +2 -3
  23. package/dist/events/StartEvent.js +1 -2
  24. package/dist/flows/Association.js +2 -2
  25. package/dist/flows/SequenceFlow.js +3 -7
  26. package/dist/gateways/EventBasedGateway.js +7 -5
  27. package/dist/io/EnvironmentDataObject.js +1 -1
  28. package/dist/io/EnvironmentDataStore.js +1 -1
  29. package/dist/io/EnvironmentDataStoreReference.js +1 -1
  30. package/dist/io/InputOutputSpecification.js +2 -2
  31. package/dist/io/Properties.js +14 -14
  32. package/dist/process/Process.js +5 -7
  33. package/dist/process/ProcessExecution.js +13 -13
  34. package/dist/tasks/ServiceTask.js +1 -1
  35. package/package.json +2 -2
  36. package/src/Api.js +1 -1
  37. package/src/Context.js +2 -1
  38. package/src/Environment.js +3 -3
  39. package/src/EventBroker.js +1 -1
  40. package/src/MessageFormatter.js +2 -2
  41. package/src/Tracker.js +1 -0
  42. package/src/activity/Activity.js +65 -159
  43. package/src/activity/ActivityExecution.js +2 -2
  44. package/src/activity/outbound-evaluator.js +127 -0
  45. package/src/definition/Definition.js +4 -4
  46. package/src/definition/DefinitionExecution.js +6 -6
  47. package/src/error/Errors.js +7 -11
  48. package/src/eventDefinitions/CancelEventDefinition.js +1 -2
  49. package/src/eventDefinitions/CompensateEventDefinition.js +2 -3
  50. package/src/eventDefinitions/ConditionalEventDefinition.js +2 -3
  51. package/src/eventDefinitions/ErrorEventDefinition.js +3 -4
  52. package/src/eventDefinitions/EscalationEventDefinition.js +1 -2
  53. package/src/eventDefinitions/LinkEventDefinition.js +1 -2
  54. package/src/eventDefinitions/MessageEventDefinition.js +2 -3
  55. package/src/eventDefinitions/SignalEventDefinition.js +2 -3
  56. package/src/eventDefinitions/TimerEventDefinition.js +2 -3
  57. package/src/events/BoundaryEvent.js +2 -3
  58. package/src/events/StartEvent.js +1 -2
  59. package/src/flows/Association.js +2 -2
  60. package/src/flows/SequenceFlow.js +3 -3
  61. package/src/gateways/EventBasedGateway.js +5 -3
  62. package/src/io/EnvironmentDataObject.js +1 -1
  63. package/src/io/EnvironmentDataStore.js +1 -1
  64. package/src/io/EnvironmentDataStoreReference.js +1 -1
  65. package/src/io/InputOutputSpecification.js +2 -2
  66. package/src/io/Properties.js +14 -14
  67. package/src/process/Process.js +5 -7
  68. package/src/process/ProcessExecution.js +13 -13
  69. package/src/tasks/ServiceTask.js +1 -1
@@ -59,7 +59,7 @@ Environment.prototype.recover = function recover(state) {
59
59
  return this;
60
60
  };
61
61
 
62
- Environment.prototype.clone = function clone(overrideOptions = {}) {
62
+ Environment.prototype.clone = function clone(overrideOptions) {
63
63
  const services = this[kServices];
64
64
  const newOptions = {
65
65
  settings: { ...this.settings },
@@ -74,7 +74,7 @@ Environment.prototype.clone = function clone(overrideOptions = {}) {
74
74
  services,
75
75
  };
76
76
 
77
- if (overrideOptions.services) newOptions.services = { ...services, ...overrideOptions.services };
77
+ if (overrideOptions?.services) newOptions.services = { ...services, ...overrideOptions.services };
78
78
 
79
79
  return new this.constructor(newOptions);
80
80
  };
@@ -109,7 +109,7 @@ Environment.prototype.getServiceByName = function getServiceByName(serviceName)
109
109
  return this[kServices][serviceName];
110
110
  };
111
111
 
112
- Environment.prototype.resolveExpression = function resolveExpression(expression, message = {}, expressionFnContext) {
112
+ Environment.prototype.resolveExpression = function resolveExpression(expression, message, expressionFnContext) {
113
113
  const from = {
114
114
  environment: this,
115
115
  ...message,
@@ -78,7 +78,7 @@ EventBroker.prototype.on = function on(eventName, callback, eventOptions = { onc
78
78
  }
79
79
  };
80
80
 
81
- EventBroker.prototype.once = function once(eventName, callback, eventOptions = {}) {
81
+ EventBroker.prototype.once = function once(eventName, callback, eventOptions) {
82
82
  return this.on(eventName, callback, { ...eventOptions, once: true });
83
83
  };
84
84
 
@@ -65,7 +65,7 @@ Formatter.prototype._onMessage = function onMessage(routingKey, message) {
65
65
  default: {
66
66
  message.ack();
67
67
 
68
- const endRoutingKey = message.content && message.content.endRoutingKey;
68
+ const endRoutingKey = message.content?.endRoutingKey;
69
69
  if (endRoutingKey) {
70
70
  this._decorate(message.content);
71
71
  pending.push(message);
@@ -99,7 +99,7 @@ Formatter.prototype._complete = function complete(message, isError) {
99
99
  this.broker.cancel(message.fields.consumerTag);
100
100
 
101
101
  if (isError) {
102
- const error = (message.content && message.content.error) || new Error('formatting failed');
102
+ const error = message.content?.error || new Error('formatting failed');
103
103
  const errMessage = error.message || 'formatting failed';
104
104
  this._debug(`formatting of ${formatKey} failed with ${message.fields.routingKey}: ${errMessage}`);
105
105
  return callback(new ActivityError(errMessage, cloneMessage(runMessage), error));
package/src/Tracker.js CHANGED
@@ -30,6 +30,7 @@ ActivityTracker.prototype.track = function track(routingKey, message) {
30
30
  break;
31
31
  case 'activity.execution.outbound.take':
32
32
  case 'activity.detach':
33
+ case 'activity.call':
33
34
  case 'activity.wait': {
34
35
  if (content.isMultiInstance) this._waiting(content.parent.executionId);
35
36
  else this._waiting(executionId);
@@ -5,6 +5,7 @@ import { ActivityBroker } from '../EventBroker.js';
5
5
  import { Formatter } from '../MessageFormatter.js';
6
6
  import { cloneContent, cloneParent, cloneMessage } from '../messageHelper.js';
7
7
  import { makeErrorFromMessage, ActivityError } from '../error/Errors.js';
8
+ import { OutboundEvaluator, formatFlowAction } from './outbound-evaluator.js';
8
9
 
9
10
  const kActivityDef = Symbol.for('activityDefinition');
10
11
  const kConsuming = Symbol.for('consuming');
@@ -68,16 +69,21 @@ function Activity(Behaviour, activityDef, context) {
68
69
  inboundTriggers = inboundSequenceFlows.slice();
69
70
  }
70
71
  const outboundSequenceFlows = context.getOutboundSequenceFlows(id);
72
+
73
+ const isParallelJoin = activityDef.isParallelGateway && inboundSequenceFlows.length > 1;
74
+
71
75
  const flows = (this[kFlows] = {
72
76
  inboundSequenceFlows,
73
77
  inboundAssociations,
74
- inboundJoinFlows: new Set(),
75
78
  inboundTriggers,
76
79
  outboundSequenceFlows,
77
80
  outboundEvaluator: new OutboundEvaluator(this, outboundSequenceFlows),
81
+ ...(isParallelJoin && {
82
+ inboundJoinFlows: new Set(),
83
+ inboundSourceIds: new Set(inboundSequenceFlows.map(({ sourceId }) => sourceId)),
84
+ }),
78
85
  });
79
86
 
80
- const isParallelJoin = activityDef.isParallelGateway && flows.inboundSequenceFlows.length > 1;
81
87
  this[kFlags] = {
82
88
  isEnd: flows.outboundSequenceFlows.length === 0,
83
89
  isStart: flows.inboundSequenceFlows.length === 0 && !attachedTo && !behaviour.triggeredByEvent && !isForCompensation,
@@ -88,7 +94,7 @@ function Activity(Behaviour, activityDef, context) {
88
94
  isTransaction: activityDef.isTransaction,
89
95
  isParallelJoin,
90
96
  isThrowing: activityDef.isThrowing,
91
- lane: activityDef.lane && activityDef.lane.id,
97
+ lane: activityDef.lane?.id,
92
98
  };
93
99
  this[kExec] = new Map();
94
100
 
@@ -99,7 +105,7 @@ function Activity(Behaviour, activityDef, context) {
99
105
  onExecutionMessage: this._onExecutionMessage.bind(this),
100
106
  };
101
107
 
102
- this[kEventDefinitions] = eventDefinitions && eventDefinitions.map((ed, idx) => new ed.Behaviour(this, ed, context, idx));
108
+ this[kEventDefinitions] = eventDefinitions?.map((ed, idx) => new ed.Behaviour(this, ed, context, idx));
103
109
  this[kExtensions] = context.loadExtensions(this);
104
110
  this[kConsuming] = false;
105
111
  this[kConsumingRunQ] = undefined;
@@ -129,7 +135,7 @@ Object.defineProperties(Activity.prototype, {
129
135
  bpmnIo: {
130
136
  get() {
131
137
  const extensions = this[kExtensions];
132
- return extensions && extensions.extensions.find((e) => e.type === 'bpmnio');
138
+ return extensions?.extensions.find((e) => e.type === 'bpmnio');
133
139
  },
134
140
  },
135
141
  formatter: {
@@ -502,16 +508,16 @@ Activity.prototype._onInbound = function onInbound(routingKey, message) {
502
508
 
503
509
  Activity.prototype._onJoinInbound = function onJoinInbound(routingKey, message) {
504
510
  const { content } = message;
505
- const { inboundJoinFlows, inboundTriggers } = this[kFlows];
511
+ const { inboundJoinFlows, inboundSourceIds } = this[kFlows];
506
512
  let alreadyTouched = false;
507
513
 
508
514
  const touched = new Set();
509
515
 
510
516
  let taken;
511
517
  for (const msg of inboundJoinFlows) {
512
- const flowId = msg.content.id;
513
- touched.add(flowId);
514
- if (flowId === content.id) {
518
+ const sourceId = msg.content.sourceId;
519
+ touched.add(sourceId);
520
+ if (sourceId === content.sourceId) {
515
521
  alreadyTouched = true;
516
522
  }
517
523
  }
@@ -520,7 +526,7 @@ Activity.prototype._onJoinInbound = function onJoinInbound(routingKey, message)
520
526
 
521
527
  if (alreadyTouched) return;
522
528
 
523
- const remaining = inboundTriggers.length - touched.size - 1;
529
+ const remaining = inboundSourceIds.size - touched.size - 1;
524
530
  if (remaining) {
525
531
  return this.logger.debug(`<${this.id}> inbound ${message.content.action} from <${message.content.id}>, ${remaining} remaining`);
526
532
  }
@@ -649,7 +655,7 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
649
655
  break;
650
656
  }
651
657
  case 'run.execute.passthrough': {
652
- const execution = this.execution;
658
+ const execution = this[kExec].get('execution');
653
659
  if (!isRedelivered && execution) {
654
660
  if (execution.completed) return message.ack();
655
661
  this[kExecuteMessage] = message;
@@ -660,13 +666,19 @@ Activity.prototype._continueRunMessage = function continueRunMessage(routingKey,
660
666
  this.status = 'executing';
661
667
  this[kExecuteMessage] = message;
662
668
 
663
- const exec = this[kExec];
664
669
  if (isRedelivered && this.extensions) this.extensions.activate(cloneMessage(message));
665
- if (!exec.has('execution')) exec.set('execution', new ActivityExecution(this, this.context));
670
+
671
+ const exec = this[kExec];
672
+ let execution = exec.get('execution');
673
+ if (!execution) {
674
+ execution = new ActivityExecution(this, this.context);
675
+ exec.set('execution', execution);
676
+ }
677
+
666
678
  this.broker
667
679
  .getQueue('execution-q')
668
680
  .assertConsumer(this[kMessageHandlers].onExecutionMessage, { exclusive: true, consumerTag: '_activity-execution' });
669
- return exec.get('execution').execute(message);
681
+ return execution.execute(message);
670
682
  }
671
683
  case 'run.end': {
672
684
  this.logger.debug(`<${id}> end`, isRedelivered ? 'redelivered' : '');
@@ -821,14 +833,14 @@ Activity.prototype._doOutbound = function doOutbound(fromMessage, isDiscarded, c
821
833
  const fromContent = fromMessage.content;
822
834
 
823
835
  let discardSequence = fromContent.discardSequence;
824
- if (isDiscarded && !discardSequence && this[kFlags].attachedTo && fromContent.inbound && fromContent.inbound[0]) {
836
+ if (isDiscarded && !discardSequence && this[kFlags].attachedTo && fromContent.inbound?.[0]) {
825
837
  discardSequence = [fromContent.inbound[0].id];
826
838
  }
827
839
 
828
840
  let outboundFlows;
829
841
  if (isDiscarded) {
830
842
  outboundFlows = outboundSequenceFlows.map((flow) => formatFlowAction(flow, { action: 'discard' }));
831
- } else if (fromContent.outbound && fromContent.outbound.length) {
843
+ } else if (fromContent.outbound?.length) {
832
844
  outboundFlows = outboundSequenceFlows.map((flow) => formatFlowAction(flow, fromContent.outbound.filter((f) => f.id === flow.id).pop()));
833
845
  }
834
846
 
@@ -845,24 +857,44 @@ Activity.prototype._doOutbound = function doOutbound(fromMessage, isDiscarded, c
845
857
  };
846
858
 
847
859
  Activity.prototype._doRunOutbound = function doRunOutbound(outboundList, content, discardSequence) {
848
- for (const outboundFlow of outboundList) {
849
- const { id: flowId, action, result } = outboundFlow;
850
- this.broker.publish(
851
- 'run',
852
- 'run.outbound.' + action,
853
- cloneContent(content, {
854
- flow: {
855
- ...(result && typeof result === 'object' && result),
856
- ...outboundFlow,
857
- sequenceId: getUniqueId(`${flowId}_${action}`),
858
- ...(discardSequence && { discardSequence: discardSequence.slice() }),
859
- },
860
- }),
861
- );
860
+ if (outboundList.length === 1) {
861
+ this._publishRunOutbound(outboundList[0], content, discardSequence);
862
+ } else {
863
+ const targets = new Map();
864
+
865
+ for (const outboundFlow of outboundList) {
866
+ const prevTarget = targets.get(outboundFlow.targetId);
867
+ if (!prevTarget) {
868
+ targets.set(outboundFlow.targetId, outboundFlow);
869
+ } else if (outboundFlow.action === 'take' && outboundFlow.action !== prevTarget.action) {
870
+ targets.set(outboundFlow.targetId, outboundFlow);
871
+ }
872
+ }
873
+
874
+ for (const outboundFlow of targets.values()) {
875
+ this._publishRunOutbound(outboundFlow, content, discardSequence);
876
+ }
862
877
  }
878
+
863
879
  return outboundList;
864
880
  };
865
881
 
882
+ Activity.prototype._publishRunOutbound = function publishRunOutbound(outboundFlow, content, discardSequence) {
883
+ const { id: flowId, action, result } = outboundFlow;
884
+ this.broker.publish(
885
+ 'run',
886
+ 'run.outbound.' + action,
887
+ cloneContent(content, {
888
+ flow: {
889
+ ...(result && typeof result === 'object' && result),
890
+ ...outboundFlow,
891
+ sequenceId: getUniqueId(`${flowId}_${action}`),
892
+ ...(discardSequence && { discardSequence: discardSequence.slice() }),
893
+ },
894
+ }),
895
+ );
896
+ };
897
+
866
898
  Activity.prototype._onResumeMessage = function onResumeMessage(message) {
867
899
  message.ack();
868
900
 
@@ -888,7 +920,7 @@ Activity.prototype._onResumeMessage = function onResumeMessage(message) {
888
920
  return this.broker.publish('run', fields.routingKey, cloneContent(stateMessage.content), stateMessage.properties);
889
921
  };
890
922
 
891
- Activity.prototype._publishEvent = function publishEvent(state, content, properties = {}) {
923
+ Activity.prototype._publishEvent = function publishEvent(state, content, properties) {
892
924
  this.broker.publish('event', `activity.${state}`, cloneContent(content, { state }), {
893
925
  ...properties,
894
926
  type: state,
@@ -943,9 +975,8 @@ Activity.prototype._onApiMessage = function onApiMessage(routingKey, message) {
943
975
  };
944
976
 
945
977
  Activity.prototype._createMessage = function createMessage(override) {
946
- const name = this.name,
947
- status = this.status,
948
- parent = this.parent;
978
+ const { name, status, parent } = this;
979
+
949
980
  const result = {
950
981
  ...override,
951
982
  id: this.id,
@@ -973,128 +1004,3 @@ Activity.prototype._deactivateRunConsumers = function _deactivateRunConsumers()
973
1004
  broker.cancel('_activity-execution');
974
1005
  this[kConsuming] = false;
975
1006
  };
976
-
977
- function OutboundEvaluator(activity, outboundFlows) {
978
- this.activity = activity;
979
- this.broker = activity.broker;
980
- const flows = (this.outboundFlows = outboundFlows.slice());
981
- const defaultFlowIdx = flows.findIndex(({ isDefault }) => isDefault);
982
- if (defaultFlowIdx > -1) {
983
- const [defaultFlow] = flows.splice(defaultFlowIdx, 1);
984
- flows.push(defaultFlow);
985
- }
986
-
987
- this.defaultFlowIdx = outboundFlows.findIndex(({ isDefault }) => isDefault);
988
- this._onEvaluated = this.onEvaluated.bind(this);
989
- this.evaluateArgs = {};
990
- }
991
-
992
- OutboundEvaluator.prototype.evaluate = function evaluate(fromMessage, discardRestAtTake, callback) {
993
- const outboundFlows = this.outboundFlows;
994
-
995
- const args = (this.evaluateArgs = {
996
- fromMessage,
997
- evaluationId: fromMessage.content.executionId,
998
- discardRestAtTake,
999
- callback,
1000
- conditionMet: false,
1001
- result: {},
1002
- takenCount: 0,
1003
- });
1004
-
1005
- if (!outboundFlows.length) return this.completed();
1006
-
1007
- const flows = (args.flows = outboundFlows.slice());
1008
-
1009
- this.broker.subscribeTmp('execution', 'evaluate.flow.#', this._onEvaluated, {
1010
- consumerTag: `_flow-evaluation-${args.evaluationId}`,
1011
- });
1012
-
1013
- return this.evaluateFlow(flows.shift());
1014
- };
1015
-
1016
- OutboundEvaluator.prototype.onEvaluated = function onEvaluated(routingKey, message) {
1017
- const content = message.content;
1018
- const { id: flowId, action, evaluationId } = message.content;
1019
- const args = this.evaluateArgs;
1020
-
1021
- if (action === 'take') {
1022
- args.takenCount++;
1023
- args.conditionMet = true;
1024
- }
1025
-
1026
- args.result[flowId] = content;
1027
-
1028
- if ('result' in content) {
1029
- this.activity.logger.debug(`<${evaluationId} (${this.activity.id})> flow <${flowId}> evaluated to: ${!!content.result}`);
1030
- }
1031
-
1032
- let nextFlow = args.flows.shift();
1033
- if (!nextFlow) return this.completed();
1034
-
1035
- if (args.discardRestAtTake && args.conditionMet) {
1036
- do {
1037
- args.result[nextFlow.id] = formatFlowAction(nextFlow, { action: 'discard' });
1038
- } while ((nextFlow = args.flows.shift()));
1039
- return this.completed();
1040
- }
1041
-
1042
- if (args.conditionMet && nextFlow.isDefault) {
1043
- args.result[nextFlow.id] = formatFlowAction(nextFlow, { action: 'discard' });
1044
- return this.completed();
1045
- }
1046
-
1047
- message.ack();
1048
- this.evaluateFlow(nextFlow);
1049
- };
1050
-
1051
- OutboundEvaluator.prototype.evaluateFlow = function evaluateFlow(flow) {
1052
- const broker = this.broker;
1053
- const { fromMessage, evaluationId } = this.evaluateArgs;
1054
- flow.evaluate(cloneMessage(fromMessage), (err, result) => {
1055
- if (err) return this.completed(err);
1056
- const action = result ? 'take' : 'discard';
1057
- return broker.publish(
1058
- 'execution',
1059
- 'evaluate.flow.' + action,
1060
- formatFlowAction(flow, {
1061
- action,
1062
- result,
1063
- evaluationId,
1064
- }),
1065
- { persistent: false },
1066
- );
1067
- });
1068
- };
1069
-
1070
- OutboundEvaluator.prototype.completed = function completed(err) {
1071
- const { callback, evaluationId, fromMessage, result, takenCount } = this.evaluateArgs;
1072
- this.broker.cancel(`_flow-evaluation-${evaluationId}`);
1073
-
1074
- if (err) return callback(err);
1075
-
1076
- if (!takenCount && this.outboundFlows.length) {
1077
- const nonTakenError = new ActivityError(`<${this.activity.id}> no conditional flow taken`, fromMessage);
1078
- return callback(nonTakenError);
1079
- }
1080
-
1081
- const message = fromMessage.content.message;
1082
- const evaluationResult = [];
1083
- for (const flow of Object.values(result)) {
1084
- evaluationResult.push({
1085
- ...flow,
1086
- ...(message !== undefined && { message }),
1087
- });
1088
- }
1089
-
1090
- return callback(null, evaluationResult);
1091
- };
1092
-
1093
- function formatFlowAction(flow, options) {
1094
- return {
1095
- ...options,
1096
- id: flow.id,
1097
- action: options.action,
1098
- ...(flow.isDefault && { isDefault: true }),
1099
- };
1100
- }
@@ -32,7 +32,7 @@ Object.defineProperty(ActivityExecution.prototype, 'completed', {
32
32
 
33
33
  ActivityExecution.prototype.execute = function execute(executeMessage) {
34
34
  if (!executeMessage) throw new Error('Execution requires message');
35
- const executionId = executeMessage.content && executeMessage.content.executionId;
35
+ const executionId = executeMessage.content?.executionId;
36
36
  if (!executionId) throw new Error('Execution requires execution id');
37
37
 
38
38
  this.executionId = executionId;
@@ -347,7 +347,7 @@ ActivityExecution.prototype._onParentApiMessage = function onParentApiMessage(ro
347
347
  };
348
348
 
349
349
  ActivityExecution.prototype._onStop = function onStop(message) {
350
- const stoppedId = message && message.content && message.content.executionId;
350
+ const stoppedId = message?.content?.executionId;
351
351
  const running = this.getPostponed();
352
352
  for (const api of running) {
353
353
  if (stoppedId !== api.content.executionId) {
@@ -0,0 +1,127 @@
1
+ import { ActivityError } from '../error/Errors.js';
2
+ import { cloneMessage } from '../messageHelper.js';
3
+
4
+ export function OutboundEvaluator(activity, outboundFlows) {
5
+ this.activity = activity;
6
+ this.broker = activity.broker;
7
+ const flows = (this.outboundFlows = outboundFlows.slice());
8
+ const defaultFlowIdx = flows.findIndex(({ isDefault }) => isDefault);
9
+ if (defaultFlowIdx > -1) {
10
+ const [defaultFlow] = flows.splice(defaultFlowIdx, 1);
11
+ flows.push(defaultFlow);
12
+ }
13
+
14
+ this._onEvaluated = this.onEvaluated.bind(this);
15
+ this.evaluateArgs = {};
16
+ }
17
+
18
+ OutboundEvaluator.prototype.evaluate = function evaluate(fromMessage, discardRestAtTake, callback) {
19
+ const outboundFlows = this.outboundFlows;
20
+
21
+ const args = (this.evaluateArgs = {
22
+ fromMessage,
23
+ evaluationId: fromMessage.content.executionId,
24
+ discardRestAtTake,
25
+ callback,
26
+ conditionMet: false,
27
+ result: {},
28
+ takenCount: 0,
29
+ });
30
+
31
+ if (!outboundFlows.length) return this.completed();
32
+
33
+ const flows = (args.flows = outboundFlows.slice());
34
+
35
+ this.broker.subscribeTmp('execution', 'evaluate.flow.#', this._onEvaluated, {
36
+ consumerTag: `_flow-evaluation-${args.evaluationId}`,
37
+ });
38
+
39
+ return this.evaluateFlow(flows.shift());
40
+ };
41
+
42
+ OutboundEvaluator.prototype.onEvaluated = function onEvaluated(routingKey, message) {
43
+ const content = message.content;
44
+ const { id: flowId, action, evaluationId } = message.content;
45
+ const args = this.evaluateArgs;
46
+
47
+ if (action === 'take') {
48
+ args.takenCount++;
49
+ args.conditionMet = true;
50
+ }
51
+
52
+ args.result[flowId] = content;
53
+
54
+ if ('result' in content) {
55
+ this.activity.logger.debug(`<${evaluationId} (${this.activity.id})> flow <${flowId}> evaluated to: ${!!content.result}`);
56
+ }
57
+
58
+ let nextFlow = args.flows.shift();
59
+ if (!nextFlow) return this.completed();
60
+
61
+ if (args.discardRestAtTake && args.conditionMet) {
62
+ do {
63
+ args.result[nextFlow.id] = formatFlowAction(nextFlow, { action: 'discard' });
64
+ } while ((nextFlow = args.flows.shift()));
65
+ return this.completed();
66
+ }
67
+
68
+ if (args.conditionMet && nextFlow.isDefault) {
69
+ args.result[nextFlow.id] = formatFlowAction(nextFlow, { action: 'discard' });
70
+ return this.completed();
71
+ }
72
+
73
+ message.ack();
74
+ this.evaluateFlow(nextFlow);
75
+ };
76
+
77
+ OutboundEvaluator.prototype.evaluateFlow = function evaluateFlow(flow) {
78
+ const broker = this.broker;
79
+ const { fromMessage, evaluationId } = this.evaluateArgs;
80
+ flow.evaluate(cloneMessage(fromMessage), (err, result) => {
81
+ if (err) return this.completed(err);
82
+ const action = result ? 'take' : 'discard';
83
+ return broker.publish(
84
+ 'execution',
85
+ 'evaluate.flow.' + action,
86
+ formatFlowAction(flow, {
87
+ action,
88
+ result,
89
+ evaluationId,
90
+ }),
91
+ { persistent: false },
92
+ );
93
+ });
94
+ };
95
+
96
+ OutboundEvaluator.prototype.completed = function completed(err) {
97
+ const { callback, evaluationId, fromMessage, result, takenCount } = this.evaluateArgs;
98
+ this.broker.cancel(`_flow-evaluation-${evaluationId}`);
99
+
100
+ if (err) return callback(err);
101
+
102
+ if (!takenCount && this.outboundFlows.length) {
103
+ const nonTakenError = new ActivityError(`<${this.activity.id}> no conditional flow taken`, fromMessage);
104
+ return callback(nonTakenError);
105
+ }
106
+
107
+ const message = fromMessage.content.message;
108
+ const evaluationResult = [];
109
+ for (const flow of Object.values(result)) {
110
+ evaluationResult.push({
111
+ ...flow,
112
+ ...(message !== undefined && { message }),
113
+ });
114
+ }
115
+
116
+ return callback(null, evaluationResult);
117
+ };
118
+
119
+ export function formatFlowAction(flow, options) {
120
+ return {
121
+ ...options,
122
+ id: flow.id,
123
+ action: options.action,
124
+ targetId: flow.targetId,
125
+ ...(flow.isDefault && { isDefault: true }),
126
+ };
127
+ }
@@ -98,7 +98,7 @@ Object.defineProperties(Definition.prototype, {
98
98
  activityStatus: {
99
99
  get() {
100
100
  const execution = this[kExec].get('execution');
101
- return (execution && execution.activityStatus) || 'idle';
101
+ return execution?.activityStatus || 'idle';
102
102
  },
103
103
  },
104
104
  });
@@ -160,7 +160,7 @@ Definition.prototype.getState = function getState() {
160
160
  stopped: this.stopped,
161
161
  counters: this.counters,
162
162
  environment: this.environment.getState(),
163
- execution: this.execution && this.execution.getState(),
163
+ execution: this.execution?.getState(),
164
164
  broker: this.broker.getState(true),
165
165
  });
166
166
  };
@@ -289,8 +289,8 @@ Definition.prototype.cancelActivity = function cancelActivity(message) {
289
289
  Definition.prototype.sendMessage = function sendMessage(message) {
290
290
  const messageContent = { message };
291
291
  let messageType = 'message';
292
- const reference = message && message.id && this.getElementById(message.id);
293
- if (reference && reference.resolve) {
292
+ const reference = message?.id && this.getElementById(message.id);
293
+ if (reference?.resolve) {
294
294
  const resolvedReference = reference.resolve(this._createMessage({ message }));
295
295
  messageType = resolvedReference.messageType || messageType;
296
296
  messageContent.message = { ...message, ...resolvedReference };
@@ -408,7 +408,7 @@ DefinitionExecution.prototype._onProcessMessage = function onProcessMessage(rout
408
408
  this[kStatus] = 'executing';
409
409
  break;
410
410
  case 'process.discarded': {
411
- if (inbound && inbound.length) {
411
+ if (inbound?.length) {
412
412
  const calledFrom = inbound[0];
413
413
  this._getProcessApi({ content: calledFrom }).cancel({
414
414
  executionId: calledFrom.executionId,
@@ -417,7 +417,7 @@ DefinitionExecution.prototype._onProcessMessage = function onProcessMessage(rout
417
417
  break;
418
418
  }
419
419
  case 'process.end': {
420
- if (inbound && inbound.length) {
420
+ if (inbound?.length) {
421
421
  const calledFrom = inbound[0];
422
422
 
423
423
  this._getProcessApi({ content: calledFrom }).signal({
@@ -430,7 +430,7 @@ DefinitionExecution.prototype._onProcessMessage = function onProcessMessage(rout
430
430
  break;
431
431
  }
432
432
  case 'process.error': {
433
- if (inbound && inbound.length) {
433
+ if (inbound?.length) {
434
434
  const calledFrom = inbound[0];
435
435
 
436
436
  this._getProcessApi({ content: calledFrom }).sendApiMessage(
@@ -478,7 +478,7 @@ DefinitionExecution.prototype._onProcessCompleted = function onProcessCompleted(
478
478
  message.ack();
479
479
  this._debug(`left <${executionId} (${id})> (${type}), pending runs ${this.postponedCount}`);
480
480
 
481
- if (inbound && inbound.length) {
481
+ if (inbound?.length) {
482
482
  const bp = this._removeProcessByExecutionId(executionId);
483
483
  this._deactivateProcess(bp);
484
484
  }
@@ -651,7 +651,7 @@ DefinitionExecution.prototype._onDelegateMessage = function onDelegateMessage(ro
651
651
  const delegateMessage = executeMessage.content.message;
652
652
 
653
653
  const reference = this.context.getActivityById(delegateMessage.id);
654
- const message = reference && reference.resolve(executeMessage);
654
+ const message = reference?.resolve(executeMessage);
655
655
 
656
656
  this._debug(
657
657
  `<${reference ? `${messageType} ${delegateMessage.id}>` : `anonymous ${messageType}`} event received from <${content.parent.id}.${content.id}>. Delegating.`,
@@ -710,7 +710,7 @@ DefinitionExecution.prototype._complete = function complete(completionType, cont
710
710
  );
711
711
  };
712
712
 
713
- DefinitionExecution.prototype._createMessage = function createMessage(content = {}) {
713
+ DefinitionExecution.prototype._createMessage = function createMessage(content) {
714
714
  return {
715
715
  id: this.id,
716
716
  type: this.type,
@@ -6,8 +6,7 @@ class ActivityError extends Error {
6
6
  this.type = 'ActivityError';
7
7
  this.name = this.constructor.name;
8
8
  this.description = description;
9
- if (sourceMessage)
10
- this.source = cloneMessage(sourceMessage, sourceMessage.content && sourceMessage.content.error && { error: undefined });
9
+ if (sourceMessage) this.source = cloneMessage(sourceMessage, sourceMessage.content?.error && { error: undefined });
11
10
  if (inner) {
12
11
  this.inner = inner;
13
12
  if (inner.name) this.name = inner.name;
@@ -24,17 +23,14 @@ class RunError extends ActivityError {
24
23
  }
25
24
 
26
25
  class BpmnError extends Error {
27
- constructor(description, behaviour = {}, sourceMessage, inner) {
28
- const { errorCode } = behaviour;
29
-
26
+ constructor(description, behaviour, sourceMessage, inner) {
30
27
  super(description);
31
28
  this.type = 'BpmnError';
32
- this.name = behaviour.name || this.constructor.name;
29
+ this.name = behaviour?.name ?? this.constructor.name;
33
30
  this.description = description;
34
- this.code = ('errorCode' in behaviour && errorCode && errorCode.toString()) || behaviour.code;
35
- this.id = behaviour.id;
36
- if (sourceMessage)
37
- this.source = cloneMessage(sourceMessage, sourceMessage.content && sourceMessage.content.error && { error: undefined });
31
+ this.code = behaviour?.errorCode?.toString() ?? behaviour?.code;
32
+ this.id = behaviour?.id;
33
+ if (sourceMessage) this.source = cloneMessage(sourceMessage, sourceMessage.content?.error && { error: undefined });
38
34
  if (inner) this.inner = inner;
39
35
  }
40
36
  }
@@ -47,7 +43,7 @@ function makeErrorFromMessage(errorMessage) {
47
43
  if (isKnownError(content)) return content;
48
44
 
49
45
  const { error } = content;
50
- if (!error) return new Error(`Malformatted error message with routing key ${errorMessage.fields && errorMessage.fields.routingKey}`);
46
+ if (!error) return new Error(`Malformatted error message with routing key ${errorMessage.fields?.routingKey}`);
51
47
 
52
48
  if (isKnownError(error)) return error;
53
49