bpmn-engine 19.0.1 → 20.0.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.
package/lib/index.cjs ADDED
@@ -0,0 +1,773 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var module$1 = require('module');
6
+ var events = require('events');
7
+ var url = require('url');
8
+ var BpmnModdle = require('bpmn-moddle');
9
+ var Elements = require('bpmn-elements');
10
+ var smqp = require('smqp');
11
+ var serializer = require('moddle-context-serializer');
12
+ var Debug = require('debug');
13
+ var vm = require('vm');
14
+
15
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
16
+ function _interopNamespaceDefault(e) {
17
+ var n = Object.create(null);
18
+ if (e) {
19
+ Object.keys(e).forEach(function (k) {
20
+ if (k !== 'default') {
21
+ var d = Object.getOwnPropertyDescriptor(e, k);
22
+ Object.defineProperty(n, k, d.get ? d : {
23
+ enumerable: true,
24
+ get: function () { return e[k]; }
25
+ });
26
+ }
27
+ });
28
+ }
29
+ n.default = e;
30
+ return Object.freeze(n);
31
+ }
32
+
33
+ var Elements__namespace = /*#__PURE__*/_interopNamespaceDefault(Elements);
34
+
35
+ function Logger(scope) {
36
+ return {
37
+ debug: Debug('bpmn-engine:' + scope),
38
+ error: Debug('bpmn-engine:error:' + scope),
39
+ warn: Debug('bpmn-engine:warn:' + scope),
40
+ };
41
+ }
42
+
43
+ function Scripts(disableDummy) {
44
+ if (!(this instanceof Scripts)) return new Scripts(disableDummy);
45
+ this.scripts = {};
46
+ this.disableDummy = disableDummy;
47
+ }
48
+
49
+ Scripts.prototype.register = function register({ id, type, behaviour, logger, environment }) {
50
+ let scriptBody, language;
51
+
52
+ switch (type) {
53
+ case 'bpmn:SequenceFlow': {
54
+ if (!behaviour.conditionExpression) return;
55
+ language = behaviour.conditionExpression.language;
56
+ if (!language) return;
57
+ scriptBody = behaviour.conditionExpression.body;
58
+ break;
59
+ }
60
+ default: {
61
+ language = behaviour.scriptFormat;
62
+ scriptBody = behaviour.script;
63
+ }
64
+ }
65
+
66
+ const filename = `${type}/${id}`;
67
+ if (!language || !scriptBody) {
68
+ if (this.disableDummy) return;
69
+ const script = new DummyScript(language, filename, logger);
70
+ this.scripts[id] = script;
71
+ return script;
72
+ }
73
+
74
+ if (!/^javascript$/i.test(language)) return;
75
+
76
+ const script = new JavaScript(language, filename, scriptBody, environment);
77
+ this.scripts[id] = script;
78
+
79
+ return script;
80
+ };
81
+
82
+ Scripts.prototype.getScript = function getScript(language, { id }) {
83
+ return this.scripts[id];
84
+ };
85
+
86
+ function JavaScript(language, filename, scriptBody, environment) {
87
+ this.id = filename;
88
+ this.script = new vm.Script(scriptBody, { filename });
89
+ this.language = language;
90
+ this.environment = environment;
91
+ }
92
+
93
+ JavaScript.prototype.execute = function execute(executionContext, callback) {
94
+ const timers = this.environment.timers.register(executionContext);
95
+ return this.script.runInNewContext({ ...executionContext, ...timers, next: callback });
96
+ };
97
+
98
+ function DummyScript(language, filename, logger) {
99
+ this.id = filename;
100
+ this.isDummy = true;
101
+ this.language = language;
102
+ this.logger = logger;
103
+ }
104
+
105
+ DummyScript.prototype.execute = function execute(executionContext, callback) {
106
+ const { id, executionId } = executionContext.content;
107
+ this.logger.debug(`<${executionId} (${id})> passthrough dummy script ${this.language || 'esperanto'}`);
108
+ callback();
109
+ };
110
+
111
+ function getOptionsAndCallback(optionsOrCallback, callback) {
112
+ let options;
113
+ if (typeof optionsOrCallback === 'function') {
114
+ callback = optionsOrCallback;
115
+ } else {
116
+ options = optionsOrCallback;
117
+ }
118
+
119
+ return [options, callback];
120
+ }
121
+
122
+ const kDataObjectDef = Symbol.for('data object definition');
123
+
124
+ function ProcessOutputDataObject(dataObjectDef, { environment }) {
125
+ this[kDataObjectDef] = dataObjectDef;
126
+ this.environment = environment;
127
+ this.behaviour = dataObjectDef.behaviour;
128
+ this.name = dataObjectDef.name;
129
+ this.parent = dataObjectDef.parent;
130
+ }
131
+
132
+ Object.defineProperties(ProcessOutputDataObject.prototype, {
133
+ id: {
134
+ get() {
135
+ return this[kDataObjectDef].id;
136
+ },
137
+ },
138
+ type: {
139
+ get() {
140
+ return this[kDataObjectDef].type;
141
+ },
142
+ },
143
+ });
144
+
145
+ ProcessOutputDataObject.prototype.read = function readDataObject(broker, exchange, routingKeyPrefix, messageProperties) {
146
+ const environment = this.environment;
147
+ const { id, name, type } = this;
148
+ const value = environment.variables.data && environment.variables.data[this.id];
149
+ return broker.publish(exchange, `${routingKeyPrefix}response`, { id, name, type, value }, messageProperties);
150
+ };
151
+
152
+ ProcessOutputDataObject.prototype.write = function writeDataObject(broker, exchange, routingKeyPrefix, value, messageProperties) {
153
+ const environment = this.environment;
154
+ const { id, name, type } = this;
155
+
156
+ environment.variables.data = environment.variables.data || {};
157
+ environment.variables.data[id] = value;
158
+
159
+ environment.output.data = environment.output.data || {};
160
+ environment.output.data[id] = value;
161
+ return broker.publish(exchange, `${routingKeyPrefix}response`, { id, name, type, value }, messageProperties);
162
+ };
163
+
164
+ const nodeRequire = module$1.createRequire(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
165
+ const { version: engineVersion } = nodeRequire('../package.json');
166
+
167
+ const kEngine = Symbol.for('engine');
168
+ const kEnvironment = Symbol.for('environment');
169
+ const kExecuting = Symbol.for('executing');
170
+ const kExecution = Symbol.for('execution');
171
+ const kLoadedDefinitions = Symbol.for('loaded definitions');
172
+ const kOnBrokerReturn = Symbol.for('onBrokerReturn');
173
+ const kPendingSources = Symbol.for('pending sources');
174
+ const kSources = Symbol.for('sources');
175
+ const kState = Symbol.for('state');
176
+ const kStopped = Symbol.for('stopped');
177
+ const kTypeResolver = Symbol.for('type resolver');
178
+
179
+ function Engine(options = {}) {
180
+ if (!(this instanceof Engine)) return new Engine(options);
181
+
182
+ events.EventEmitter.call(this);
183
+
184
+ const opts = (this.options = {
185
+ Logger: Logger,
186
+ scripts: new Scripts(options.disableDummyScript),
187
+ ...options,
188
+ });
189
+
190
+ this.logger = opts.Logger('engine');
191
+
192
+ this[kTypeResolver] = serializer.TypeResolver(
193
+ {
194
+ ...Elements__namespace,
195
+ ...opts.elements,
196
+ },
197
+ opts.typeResolver || defaultTypeResolver
198
+ );
199
+
200
+ this[kEnvironment] = new Elements__namespace.Environment(opts);
201
+
202
+ const broker = (this.broker = new smqp.Broker(this));
203
+ broker.assertExchange('event', 'topic', { autoDelete: false });
204
+
205
+ this[kExecution] = null;
206
+ this[kLoadedDefinitions] = null;
207
+ this[kSources] = [];
208
+
209
+ const pendingSources = (this[kPendingSources] = []);
210
+ if (opts.source) pendingSources.push(this._serializeSource(opts.source));
211
+ if (opts.moddleContext) pendingSources.push(this._serializeModdleContext(opts.moddleContext));
212
+ if (opts.sourceContext) pendingSources.push(opts.sourceContext);
213
+ }
214
+
215
+ function defaultTypeResolver(elementTypes) {
216
+ elementTypes['bpmn:DataObject'] = ProcessOutputDataObject;
217
+ elementTypes['bpmn:DataStoreReference'] = ProcessOutputDataObject;
218
+ }
219
+
220
+ Engine.prototype = Object.create(events.EventEmitter.prototype);
221
+
222
+ Object.defineProperties(Engine.prototype, {
223
+ name: {
224
+ get() {
225
+ return this.options.name;
226
+ },
227
+ set(value) {
228
+ this.options.name = value;
229
+ },
230
+ },
231
+ environment: {
232
+ get() {
233
+ return this[kEnvironment];
234
+ },
235
+ },
236
+ state: {
237
+ get() {
238
+ const execution = this.execution;
239
+ if (execution) return execution.state;
240
+ return 'idle';
241
+ },
242
+ },
243
+ stopped: {
244
+ get() {
245
+ const execution = this.execution;
246
+ if (execution) return execution.stopped;
247
+ return false;
248
+ },
249
+ },
250
+ execution: {
251
+ enumerable: true,
252
+ get() {
253
+ return this[kExecution];
254
+ },
255
+ },
256
+ activityStatus: {
257
+ get() {
258
+ const execution = this.execution;
259
+ if (execution) return execution.activityStatus;
260
+ return 'idle';
261
+ },
262
+ },
263
+ });
264
+
265
+ Engine.prototype.execute = async function execute(...args) {
266
+ const [executeOptions, callback] = getOptionsAndCallback(...args);
267
+ try {
268
+ var definitions = await this._loadDefinitions(executeOptions); // eslint-disable-line no-var
269
+ } catch (err) {
270
+ if (callback) return callback(err);
271
+ throw err;
272
+ }
273
+
274
+ const execution = (this[kExecution] = new Execution(this, definitions, this.options));
275
+ return execution._execute(executeOptions, callback);
276
+ };
277
+
278
+ Engine.prototype.stop = function stop() {
279
+ const execution = this.execution;
280
+ if (!execution) return;
281
+ return execution.stop();
282
+ };
283
+
284
+ Engine.prototype.recover = function recover(savedState, recoverOptions) {
285
+ if (!savedState) return this;
286
+
287
+ let name = this.name;
288
+ if (!name) name = this.name = savedState.name;
289
+
290
+ this.logger.debug(`<${name}> recover`);
291
+
292
+ if (recoverOptions) this[kEnvironment] = new Elements__namespace.Environment(recoverOptions);
293
+ if (savedState.environment) this[kEnvironment] = this[kEnvironment].recover(savedState.environment);
294
+
295
+ if (!savedState.definitions) return this;
296
+
297
+ const pendingSources = this[kPendingSources];
298
+ const preSources = pendingSources.splice(0);
299
+
300
+ const typeResolver = this[kTypeResolver];
301
+ const loadedDefinitions = (this[kLoadedDefinitions] = savedState.definitions.map((dState) => {
302
+ let source;
303
+ if (dState.source) source = serializer.deserialize(JSON.parse(dState.source), typeResolver);
304
+ else source = preSources.find((s) => s.id === dState.id);
305
+
306
+ pendingSources.push(source);
307
+
308
+ this.logger.debug(`<${name}> recover ${dState.type} <${dState.id}>`);
309
+
310
+ const definition = this._loadDefinition(source);
311
+ definition.recover(dState);
312
+
313
+ return definition;
314
+ }));
315
+
316
+ this[kExecution] = new Execution(this, loadedDefinitions, {}, true);
317
+
318
+ return this;
319
+ };
320
+
321
+ Engine.prototype.resume = async function resume(...args) {
322
+ const [resumeOptions, callback] = getOptionsAndCallback(...args);
323
+
324
+ let execution = this.execution;
325
+ if (!execution) {
326
+ const definitions = await this.getDefinitions();
327
+ if (!definitions.length) {
328
+ const err = new Error('nothing to resume');
329
+ if (callback) return callback(err);
330
+ throw err;
331
+ }
332
+ execution = this[kExecution] = new Execution(this, definitions, this.options);
333
+ }
334
+
335
+ return execution._resume(resumeOptions, callback);
336
+ };
337
+
338
+ Engine.prototype.addSource = function addSource({ sourceContext: addContext } = {}) {
339
+ if (!addContext) return;
340
+ const loadedDefinitions = this[kLoadedDefinitions];
341
+ if (loadedDefinitions) loadedDefinitions.splice(0);
342
+ this[kPendingSources].push(addContext);
343
+ };
344
+
345
+ Engine.prototype.getDefinitions = function getDefinitions(executeOptions) {
346
+ const loadedDefinitions = this[kLoadedDefinitions];
347
+ if (loadedDefinitions?.length) return Promise.resolve(loadedDefinitions);
348
+ return this._loadDefinitions(executeOptions);
349
+ };
350
+
351
+ Engine.prototype.getDefinitionById = async function getDefinitionById(id) {
352
+ return (await this.getDefinitions()).find((d) => d.id === id);
353
+ };
354
+
355
+ Engine.prototype.getState = async function getState() {
356
+ const execution = this.execution;
357
+ if (execution) return execution.getState();
358
+
359
+ const definitions = await this.getDefinitions();
360
+ return new Execution(this, definitions, this.options).getState();
361
+ };
362
+
363
+ Engine.prototype.waitFor = function waitFor(eventName) {
364
+ const self = this;
365
+ return new Promise((resolve, reject) => {
366
+ self.once(eventName, onEvent);
367
+ self.once('error', onError);
368
+
369
+ function onEvent(api) {
370
+ self.removeListener('error', onError);
371
+ resolve(api);
372
+ }
373
+ function onError(err) {
374
+ self.removeListener(eventName, onEvent);
375
+ reject(err);
376
+ }
377
+ });
378
+ };
379
+
380
+ Engine.prototype._loadDefinitions = async function loadDefinitions(executeOptions) {
381
+ const runSources = await Promise.all(this[kPendingSources]);
382
+ const loadedDefinitions = (this[kLoadedDefinitions] = runSources.map((source) => this._loadDefinition(source, executeOptions)));
383
+ return loadedDefinitions;
384
+ };
385
+
386
+ Engine.prototype._loadDefinition = function loadDefinition(serializedContext, executeOptions = {}) {
387
+ const { settings, variables } = executeOptions;
388
+
389
+ const environment = this.environment;
390
+ const context = new Elements__namespace.Context(
391
+ serializedContext,
392
+ environment.clone({
393
+ listener: environment.options.listener,
394
+ ...executeOptions,
395
+ settings: {
396
+ ...environment.settings,
397
+ ...settings,
398
+ },
399
+ variables: {
400
+ ...environment.variables,
401
+ ...variables,
402
+ },
403
+ source: serializedContext,
404
+ })
405
+ );
406
+
407
+ return new Elements__namespace.Definition(context);
408
+ };
409
+
410
+ Engine.prototype._serializeSource = async function serializeSource(source) {
411
+ const moddleContext = await this._getModdleContext(source);
412
+ return this._serializeModdleContext(moddleContext);
413
+ };
414
+
415
+ Engine.prototype._serializeModdleContext = function serializeModdleContext(moddleContext) {
416
+ const serialized = serializer(moddleContext, this[kTypeResolver]);
417
+ this[kSources].push(serialized);
418
+ return serialized;
419
+ };
420
+
421
+ Engine.prototype._getModdleContext = function getModdleContext(source) {
422
+ const bpmnModdle = new BpmnModdle(this.options.moddleOptions);
423
+ return bpmnModdle.fromXML(Buffer.isBuffer(source) ? source.toString() : source.trim());
424
+ };
425
+
426
+ function Execution(engine, definitions, options, isRecovered = false) {
427
+ this.name = engine.name;
428
+ this.options = options;
429
+ this.definitions = definitions;
430
+ this[kState] = 'idle';
431
+ this[kStopped] = isRecovered;
432
+ this[kEnvironment] = engine.environment;
433
+ this[kEngine] = engine;
434
+ this[kExecuting] = [];
435
+ const onBrokerReturn = (this[kOnBrokerReturn] = this._onBrokerReturn.bind(this));
436
+ engine.broker.on('return', onBrokerReturn);
437
+ }
438
+
439
+ Object.defineProperties(Execution.prototype, {
440
+ state: {
441
+ get() {
442
+ return this[kState];
443
+ },
444
+ },
445
+ stopped: {
446
+ get() {
447
+ return this[kStopped];
448
+ },
449
+ },
450
+ broker: {
451
+ get() {
452
+ return this[kEngine].broker;
453
+ },
454
+ },
455
+ environment: {
456
+ get() {
457
+ return this[kEnvironment];
458
+ },
459
+ },
460
+ activityStatus: {
461
+ get() {
462
+ return this._getActivityStatus();
463
+ },
464
+ },
465
+ });
466
+
467
+ Execution.prototype._execute = function execute(executeOptions, callback) {
468
+ this._setup(executeOptions);
469
+ this[kStopped] = false;
470
+ this._debug('execute');
471
+
472
+ this._addConsumerCallbacks(callback);
473
+ const definitionExecutions = this.definitions.reduce((result, definition) => {
474
+ if (!definition.getExecutableProcesses().length) return result;
475
+ result.push(definition.run());
476
+ return result;
477
+ }, []);
478
+
479
+ if (!definitionExecutions.length) {
480
+ const error = new Error('No executable processes');
481
+ if (!callback) return this[kEngine].emit('error', error);
482
+ return callback(error);
483
+ }
484
+
485
+ return this;
486
+ };
487
+
488
+ Execution.prototype._resume = function resume(resumeOptions, callback) {
489
+ this._setup(resumeOptions);
490
+
491
+ this[kStopped] = false;
492
+ this._debug('resume');
493
+ this._addConsumerCallbacks(callback);
494
+
495
+ this[kExecuting].splice(0);
496
+ this.definitions.forEach((definition) => definition.resume());
497
+
498
+ return this;
499
+ };
500
+
501
+ Execution.prototype._addConsumerCallbacks = function addConsumerCallbacks(callback) {
502
+ if (!callback) return;
503
+
504
+ const broker = this.broker;
505
+ const onBrokerReturn = this[kOnBrokerReturn];
506
+
507
+ broker.off('return', onBrokerReturn);
508
+
509
+ clearConsumers();
510
+
511
+ broker.subscribeOnce(
512
+ 'event',
513
+ 'engine.stop',
514
+ () => {
515
+ clearConsumers();
516
+ return callback(null, this);
517
+ },
518
+ { consumerTag: 'ctag-cb-stop' }
519
+ );
520
+
521
+ broker.subscribeOnce(
522
+ 'event',
523
+ 'engine.end',
524
+ () => {
525
+ clearConsumers();
526
+ return callback(null, this);
527
+ },
528
+ { consumerTag: 'ctag-cb-end' }
529
+ );
530
+
531
+ broker.subscribeOnce(
532
+ 'event',
533
+ 'engine.error',
534
+ (_, message) => {
535
+ clearConsumers();
536
+ return callback(message.content);
537
+ },
538
+ { consumerTag: 'ctag-cb-error' }
539
+ );
540
+
541
+ return callback;
542
+
543
+ function clearConsumers() {
544
+ broker.cancel('ctag-cb-stop');
545
+ broker.cancel('ctag-cb-end');
546
+ broker.cancel('ctag-cb-error');
547
+ broker.on('return', onBrokerReturn);
548
+ }
549
+ };
550
+
551
+ Execution.prototype.stop = async function stop() {
552
+ const engine = this[kEngine];
553
+ const prom = engine.waitFor('stop');
554
+ this[kStopped] = true;
555
+ const timers = engine.environment.timers;
556
+
557
+ timers.executing.slice().forEach((ref) => timers.clearTimeout(ref));
558
+
559
+ this[kExecuting].splice(0).forEach((d) => d.stop());
560
+
561
+ const result = await prom;
562
+ this[kState] = 'stopped';
563
+ return result;
564
+ };
565
+
566
+ Execution.prototype._setup = function setup(setupOptions = {}) {
567
+ const listener = setupOptions.listener || this.options.listener;
568
+ if (listener && typeof listener.emit !== 'function') throw new Error('listener.emit is not a function');
569
+
570
+ const onChildMessage = this._onChildMessage.bind(this);
571
+
572
+ for (const definition of this.definitions) {
573
+ if (listener) definition.environment.options.listener = listener;
574
+
575
+ const { queueName } = definition.broker.subscribeTmp('event', 'definition.#', onChildMessage, { noAck: true, consumerTag: '_engine_definition' });
576
+ definition.broker.bindQueue(queueName, 'event', 'process.#');
577
+ definition.broker.bindQueue(queueName, 'event', 'activity.#');
578
+ definition.broker.bindQueue(queueName, 'event', 'flow.#');
579
+ }
580
+ };
581
+
582
+ Execution.prototype._onChildMessage = function onChildMessage(routingKey, message, owner) {
583
+ const { environment: ownerEnvironment } = owner;
584
+ const listener = ownerEnvironment.options?.listener;
585
+ this[kState] = 'running';
586
+
587
+ let newState;
588
+ const elementApi = owner.getApi && owner.getApi(message);
589
+
590
+ switch (routingKey) {
591
+ case 'definition.resume':
592
+ case 'definition.enter': {
593
+ const executing = this[kExecuting];
594
+ const idx = executing.indexOf(owner);
595
+ if (idx > -1) break;
596
+ executing.push(owner);
597
+ break;
598
+ }
599
+ case 'definition.stop': {
600
+ this._teardownDefinition(owner);
601
+
602
+ const executing = this[kExecuting];
603
+ if (executing.some((d) => d.isRunning)) break;
604
+
605
+ newState = 'stopped';
606
+ this[kStopped] = true;
607
+ break;
608
+ }
609
+ case 'definition.leave':
610
+ this._teardownDefinition(owner);
611
+
612
+ if (this[kExecuting].some((d) => d.isRunning)) break;
613
+
614
+ newState = 'idle';
615
+ break;
616
+ case 'definition.error': {
617
+ this._saveOutput(owner.environment.output);
618
+ this._teardownDefinition(owner);
619
+ newState = 'error';
620
+ break;
621
+ }
622
+ case 'activity.wait': {
623
+ if (listener) listener.emit('wait', owner.getApi(message), this);
624
+ break;
625
+ }
626
+ case 'process.end': {
627
+ if (message.content.inbound) break;
628
+ this._saveOutput(message.content.output);
629
+ break;
630
+ }
631
+ }
632
+
633
+ if (listener) listener.emit(routingKey, elementApi, this);
634
+
635
+ const broker = this.broker;
636
+ broker.publish('event', routingKey, { ...message.content }, { ...message.properties, mandatory: false });
637
+
638
+ if (!newState) return;
639
+
640
+ this[kState] = newState;
641
+
642
+ switch (newState) {
643
+ case 'stopped':
644
+ this._debug('stopped');
645
+ return this._complete('stop', {}, { type: 'stop' });
646
+ case 'idle':
647
+ this._debug('completed');
648
+ return this._complete('end', {}, { type: 'end' });
649
+ case 'error':
650
+ this._debug('error');
651
+ return this._complete('error', message.content.error, { type: 'error', mandatory: true });
652
+ }
653
+ };
654
+
655
+ Execution.prototype._complete = function complete(eventType, content, messageProperties) {
656
+ const timers = this.environment.timers;
657
+ timers.executing.slice().forEach((ref) => timers.clearTimeout(ref));
658
+ this.broker.publish('event', 'engine.' + eventType, content, messageProperties);
659
+ return eventType !== 'error' && this[kEngine].emit(eventType, this);
660
+ };
661
+
662
+ Execution.prototype._teardownDefinition = function teardownDefinition(definition) {
663
+ const executing = this[kExecuting];
664
+ const idx = executing.indexOf(definition);
665
+ if (idx > -1) executing.splice(idx, 1);
666
+
667
+ definition.broker.cancel('_engine_definition');
668
+ };
669
+
670
+ Execution.prototype._saveOutput = function saveOutput(output) {
671
+ if (!output || typeof output !== 'object') return;
672
+
673
+ const environmentOutput = this.environment.output;
674
+
675
+ for (const key in output) {
676
+ if (key === 'data') {
677
+ const data = (environmentOutput.data = environmentOutput.data || {});
678
+ environmentOutput.data = { ...data, ...output.data };
679
+ } else {
680
+ environmentOutput[key] = output[key];
681
+ }
682
+ }
683
+ };
684
+
685
+ Execution.prototype.getState = function getState() {
686
+ const definitions = [];
687
+ for (const definition of this.definitions) {
688
+ definitions.push({
689
+ ...definition.getState(),
690
+ source: definition.environment.options.source.serialize(),
691
+ });
692
+ }
693
+
694
+ return {
695
+ name: this[kEngine].name,
696
+ state: this.state,
697
+ stopped: this.stopped,
698
+ engineVersion,
699
+ environment: this.environment.getState(),
700
+ definitions,
701
+ };
702
+ };
703
+
704
+ Execution.prototype.getActivityById = function getActivityById(activityId) {
705
+ for (const definition of this.definitions) {
706
+ const activity = definition.getActivityById(activityId);
707
+ if (activity) return activity;
708
+ }
709
+ };
710
+
711
+ Execution.prototype.getPostponed = function getPostponed() {
712
+ const defs = this.stopped ? this.definitions : this[kExecuting];
713
+ return defs.reduce((result, definition) => {
714
+ result = result.concat(definition.getPostponed());
715
+ return result;
716
+ }, []);
717
+ };
718
+
719
+ Execution.prototype.signal = function signal(payload, { ignoreSameDefinition } = {}) {
720
+ for (const definition of this[kExecuting]) {
721
+ if (ignoreSameDefinition && payload?.parent?.id === definition.id) continue;
722
+ definition.signal(payload);
723
+ }
724
+ };
725
+
726
+ Execution.prototype.cancelActivity = function cancelActivity(payload) {
727
+ for (const definition of this[kExecuting]) {
728
+ definition.cancelActivity(payload);
729
+ }
730
+ };
731
+
732
+ Execution.prototype.waitFor = function waitFor(...args) {
733
+ return this[kEngine].waitFor(...args);
734
+ };
735
+
736
+ Execution.prototype._onBrokerReturn = function onBrokerReturn(message) {
737
+ if (message.properties.type === 'error') {
738
+ this[kEngine].emit('error', message.content);
739
+ }
740
+ };
741
+
742
+ Execution.prototype._debug = function debug(msg) {
743
+ this[kEngine].logger.debug(`<${this.name}> ${msg}`);
744
+ };
745
+
746
+ Execution.prototype._getActivityStatus = function getActivityStatus() {
747
+ let status = 'idle';
748
+ const running = this[kExecuting];
749
+ if (!running.length) return status;
750
+ else if (running.length === 1) return running[0].activityStatus;
751
+
752
+ for (const def of running) {
753
+ const bpStatus = def.activityStatus;
754
+ switch (def.activityStatus) {
755
+ case 'executing':
756
+ return bpStatus;
757
+ case 'timer':
758
+ status = bpStatus;
759
+ break;
760
+ case 'wait':
761
+ if (status === 'idle') status = bpStatus;
762
+ break;
763
+ }
764
+ }
765
+
766
+ return status;
767
+ };
768
+
769
+ exports.Engine = Engine;
770
+ exports.Execution = Execution;
771
+ exports.JavaScripts = Scripts;
772
+ exports.default = Engine;
773
+ module.exports = Object.assign(exports.default, exports);