bpmn-elements 9.2.0 → 10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ // License MIT @ https://tolu.mit-license.org/
2
+
3
+ const numbers = '\\d+';
4
+ const fractionalNumbers = ''.concat(numbers, '(?:[\\.,]').concat(numbers, ')?');
5
+ const datePattern = '('.concat(numbers, 'Y)?(').concat(numbers, 'M)?(').concat(numbers, 'W)?(').concat(fractionalNumbers, 'D)?');
6
+ const timePattern = 'T('.concat(fractionalNumbers, 'H)?(').concat(fractionalNumbers, 'M)?(').concat(fractionalNumbers, 'S)?');
7
+
8
+ const rPattern = '(?:R('.concat(numbers).concat(')/)?');
9
+ const iso8601 = rPattern.concat('P(?:').concat(datePattern, '(?:').concat(timePattern, ')?)');
10
+ const objMap = [
11
+ 'years',
12
+ 'months',
13
+ 'weeks',
14
+ 'days',
15
+ 'hours',
16
+ 'minutes',
17
+ 'seconds',
18
+ ];
19
+ const defaultDuration = Object.freeze({
20
+ years: 0,
21
+ months: 0,
22
+ weeks: 0,
23
+ days: 0,
24
+ hours: 0,
25
+ minutes: 0,
26
+ seconds: 0,
27
+ });
28
+
29
+ /**
30
+ * The ISO8601 regex for matching / testing durations
31
+ */
32
+ const pattern = new RegExp(iso8601);
33
+
34
+ /** Parse PnYnMnDTnHnMnS format to object */
35
+ export function parse(durationString) {
36
+ const matches = durationString.replace(/,/g, '.').match(pattern);
37
+ if (!matches) {
38
+ throw new RangeError('invalid duration: ' + durationString);
39
+ }
40
+
41
+ // Slice away repeat and first entry in match-array (the input string)
42
+ const slicedMatches = matches.slice(2);
43
+ if (slicedMatches.filter(Boolean).length === 0) {
44
+ throw new RangeError('invalid duration: ' + durationString);
45
+ }
46
+ // Check only one fraction is used
47
+ if (slicedMatches.filter((v) => {
48
+ return /\./.test(v || '');
49
+ }).length > 1) {
50
+ throw new RangeError('Fractions are allowed on the smallest unit in the string, e.g. P0.5D or PT1.0001S but not PT0.5M0.1S: ' + durationString);
51
+ }
52
+
53
+ const result = {};
54
+ if (matches[1]) result.repeat = Number(matches[1]);
55
+
56
+ return slicedMatches.reduce((prev, next, idx) => {
57
+ prev[objMap[idx]] = parseFloat(next || '0') || 0;
58
+ return prev;
59
+ }, result);
60
+ }
61
+
62
+ /** Convert ISO8601 duration object to an end Date. */
63
+ export function end(durationInput, startDate) {
64
+ const duration = Object.assign({}, defaultDuration, durationInput);
65
+ // Create two equal timestamps, add duration to 'then' and return time difference
66
+ const timestamp = startDate.getTime();
67
+ const then = new Date(timestamp);
68
+ then.setFullYear(then.getFullYear() + duration.years);
69
+ then.setMonth(then.getMonth() + duration.months);
70
+ then.setDate(then.getDate() + duration.days);
71
+ // set time as milliseconds to get fractions working for minutes/hours
72
+ const hoursInMs = duration.hours * 3600 * 1000;
73
+ const minutesInMs = duration.minutes * 60 * 1000;
74
+ then.setMilliseconds(then.getMilliseconds() + duration.seconds * 1000 + hoursInMs + minutesInMs);
75
+ // Special case weeks
76
+ then.setDate(then.getDate() + duration.weeks * 7);
77
+ return then;
78
+ }
79
+
80
+ /** Convert ISO8601 duration object to seconds */
81
+ export function toSeconds(durationInput, startDate) {
82
+ if (startDate === void 0) {
83
+ startDate = new Date();
84
+ }
85
+ const duration = Object.assign({}, defaultDuration, durationInput);
86
+ const timestamp = startDate.getTime();
87
+ const now = new Date(timestamp);
88
+ const then = end(duration, now);
89
+ const seconds = (then.getTime() - now.getTime()) / 1000;
90
+ return seconds;
91
+ }
@@ -0,0 +1,27 @@
1
+ const kProcess = Symbol.for('process');
2
+
3
+ export default function Lane(process, laneDefinition) {
4
+ const {broker, environment} = process;
5
+ const {id, type, behaviour} = laneDefinition;
6
+
7
+ this[kProcess] = process;
8
+
9
+ this.id = id;
10
+ this.type = type;
11
+ this.name = behaviour.name;
12
+ this.parent = {
13
+ id: process.id,
14
+ type: process.type,
15
+ };
16
+ this.behaviour = {...behaviour};
17
+ this.environment = environment;
18
+ this.broker = broker;
19
+ this.context = process.context;
20
+ this.logger = environment.Logger(type.toLowerCase());
21
+ }
22
+
23
+ Object.defineProperty(Lane.prototype, 'process', {
24
+ get() {
25
+ return this[kProcess];
26
+ },
27
+ });
@@ -10,6 +10,7 @@ const kCounters = Symbol.for('counters');
10
10
  const kExec = Symbol.for('execution');
11
11
  const kExecuteMessage = Symbol.for('executeMessage');
12
12
  const kExtensions = Symbol.for('extensions');
13
+ const kLanes = Symbol.for('lanes');
13
14
  const kMessageHandlers = Symbol.for('messageHandlers');
14
15
  const kStateMessage = Symbol.for('stateMessage');
15
16
  const kStatus = Symbol.for('status');
@@ -53,6 +54,9 @@ export function Process(processDef, context) {
53
54
 
54
55
  this.logger = environment.Logger(type.toLowerCase());
55
56
 
57
+ if (behaviour.lanes) {
58
+ this[kLanes] = behaviour.lanes.map((lane) => new lane.Behaviour(this, lane));
59
+ }
56
60
  this[kExtensions] = context.loadExtensions(this);
57
61
  }
58
62
 
@@ -63,6 +67,14 @@ Object.defineProperty(Process.prototype, 'counters', {
63
67
  },
64
68
  });
65
69
 
70
+ Object.defineProperty(Process.prototype, 'lanes', {
71
+ enumerable: true,
72
+ get() {
73
+ const lanes = this[kLanes];
74
+ return lanes && lanes.slice();
75
+ },
76
+ });
77
+
66
78
  Object.defineProperty(Process.prototype, 'extensions', {
67
79
  enumerable: true,
68
80
  get() {
@@ -399,6 +411,12 @@ Process.prototype.getSequenceFlows = function getSequenceFlows() {
399
411
  return this.context.getSequenceFlows();
400
412
  };
401
413
 
414
+ Process.prototype.getLaneById = function getLaneById(laneId) {
415
+ const lanes = this[kLanes];
416
+ if (!lanes) return;
417
+ return lanes.find((lane) => lane.id === laneId);
418
+ };
419
+
402
420
  Process.prototype.getPostponed = function getPostponed(...args) {
403
421
  const execution = this.execution;
404
422
  if (!execution) return [];
@@ -135,7 +135,7 @@ SubProcessBehaviour.prototype.recover = function recover(state) {
135
135
  }
136
136
 
137
137
  const subEnvironment = this.environment.clone().recover(state.environment);
138
- const subContext = this.context.clone(subEnvironment);
138
+ const subContext = this.context.clone(subEnvironment, this.activity);
139
139
 
140
140
  const execution = new ProcessExecution(this.activity, subContext).recover(state);
141
141
 
@@ -176,7 +176,7 @@ SubProcessBehaviour.prototype._upsertExecution = function upsertExecution(execut
176
176
  }
177
177
 
178
178
  const subEnvironment = this.environment.clone();
179
- const subContext = this.context.clone(subEnvironment);
179
+ const subContext = this.context.clone(subEnvironment, this.activity);
180
180
 
181
181
  execution = new ProcessExecution(this.activity, subContext);
182
182
  this[kExecutions].push(execution);
package/types/index.d.ts CHANGED
@@ -37,7 +37,8 @@ declare module 'bpmn-elements' {
37
37
  content: ElementMessageContent,
38
38
  }
39
39
 
40
- interface EventDefinition {
40
+ class EventDefinition {
41
+ constructor(activity: Activity, eventDefinitionElement: SerializableElement)
41
42
  get id(): string;
42
43
  get type(): string;
43
44
  get executionId(): string;
@@ -287,6 +288,8 @@ declare module 'bpmn-elements' {
287
288
  get sid(): string;
288
289
  get definitionContext(): SerializableContext;
289
290
  get environment(): Environment;
291
+ /** Context owner, Process or SubProcess activity */
292
+ get owner(): Process | Activity | undefined;
290
293
  getActivityById<T>(activityId: string): T;
291
294
  getSequenceFlowById(sequenceFlowId: string): SequenceFlow;
292
295
  getInboundSequenceFlows(activityId: string): SequenceFlow[];
@@ -428,6 +431,7 @@ declare module 'bpmn-elements' {
428
431
  constructor(processDef: SerializableElement, context: Context);
429
432
  get isExecutable(): boolean;
430
433
  get counters(): completedCounters;
434
+ get lanes(): Lane[] | undefined;
431
435
  get extensions(): IExtension;
432
436
  get stopped(): boolean;
433
437
  get isRunning(): boolean;
@@ -447,6 +451,7 @@ declare module 'bpmn-elements' {
447
451
  getActivities(): Activity[];
448
452
  getStartActivities(filterOptions?: startActivityFilterOptions): Activity[];
449
453
  getSequenceFlows(): SequenceFlow[];
454
+ getLaneById(laneId: string): Lane | undefined;
450
455
  getPostponed(filterFn: filterPostponed): Api<ElementBase>[];
451
456
  }
452
457
 
@@ -470,6 +475,24 @@ declare module 'bpmn-elements' {
470
475
  getApi(message?: ElementBrokerMessage): Api<ElementBase>;
471
476
  }
472
477
 
478
+ class Lane extends ElementBase {
479
+ constructor(process: Process, laneDefinition: SerializableElement);
480
+ /** Process broker */
481
+ get broker(): Broker;
482
+ get process(): Process;
483
+ }
484
+
485
+ interface ISequenceFlowCondition {
486
+ /** Condition type, e.g. script or expression */
487
+ get type(): string;
488
+ /**
489
+ * Execute sequence flow condition
490
+ * @param message Source element execution message
491
+ * @param callback Callback with truthy result if flow should be taken
492
+ */
493
+ execute(message: ElementBrokerMessage, callback: (err: Error, result: any) => void): void;
494
+ }
495
+
473
496
  class SequenceFlow extends Element<SequenceFlow> {
474
497
  get sourceId(): string;
475
498
  get targetId(): string;
@@ -479,7 +502,7 @@ declare module 'bpmn-elements' {
479
502
  take(content?: any): boolean;
480
503
  discard(content?: any): void;
481
504
  shake(message: any): number;
482
- getCondition(): any;
505
+ getCondition(): ISequenceFlowCondition | null;
483
506
  createMessage(override?: any): object;
484
507
  /**
485
508
  * Evaluate flow
@@ -495,6 +518,7 @@ declare module 'bpmn-elements' {
495
518
  get id(): string;
496
519
  get processId(): string;
497
520
  }
521
+
498
522
  class MessageFlow extends Element<MessageFlow> {
499
523
  get source(): MessageFlowReference;
500
524
  get target(): MessageFlowReference;
@@ -521,15 +545,53 @@ declare module 'bpmn-elements' {
521
545
  [x: string]: any,
522
546
  }
523
547
 
524
- type wrappedSetTimeout = (handler: CallableFunction, timeout: number, ...args: unknown[]) => any;
525
- type wrappedClearTimeout = (id?: any) => void;
548
+ type wrappedSetTimeout = (handler: TimerHandler, delay: number, ...args: any[]) => Timer;
549
+ type wrappedClearTimeout = (ref: any) => void;
550
+
551
+ interface Timer {
552
+ /** The function to call when the timer elapses */
553
+ readonly callback: TimerHandler;
554
+ /** The number of milliseconds to wait before calling the callback */
555
+ readonly delay: number;
556
+ /** Optional arguments to pass when the callback is called */
557
+ readonly args?: any[];
558
+ /** Timer owner if any */
559
+ readonly owner?: any;
560
+ /** Timer Id */
561
+ readonly timerId: string;
562
+ /** Timeout, return from setTimeout */
563
+ readonly timerRef: any;
564
+ [x: string]: any;
565
+ }
566
+
567
+ interface RegisteredTimer {
568
+ owner?: any;
569
+ get setTimeout(): wrappedSetTimeout;
570
+ get clearTimeout(): wrappedClearTimeout;
571
+ }
526
572
 
527
573
  interface ITimers {
528
- get executing(): any[];
529
574
  get setTimeout(): wrappedSetTimeout;
530
575
  get clearTimeout(): wrappedClearTimeout;
531
- register(owner?: any): { setTimeout: wrappedSetTimeout, clearTimeout: wrappedClearTimeout };
532
- [x: string]: any,
576
+ register(owner?: any): RegisteredTimer;
577
+ [x: string]: any;
578
+ }
579
+
580
+ interface TimersOptions {
581
+ /** Defaults to builtin setTimeout */
582
+ setTimeout?: typeof setTimeout;
583
+ /** Defaults to builtin clearTimeout */
584
+ clearTimeout?: typeof clearTimeout;
585
+ [x: string]: any;
586
+ }
587
+
588
+ class Timers implements ITimers {
589
+ options: TimersOptions;
590
+ constructor(options?: TimersOptions);
591
+ get executing(): Timer[];
592
+ get setTimeout(): wrappedSetTimeout;
593
+ get clearTimeout(): wrappedClearTimeout;
594
+ register(owner?: any): RegisteredTimer;
533
595
  }
534
596
 
535
597
  interface IScripts {
@@ -557,6 +619,8 @@ declare module 'bpmn-elements' {
557
619
  get triggeredByEvent(): boolean;
558
620
  get attachedTo(): Activity;
559
621
  get eventDefinitions(): EventDefinition[];
622
+ /** Parent element process or sub process reference */
623
+ get parentElement(): Process | Activity;
560
624
  activate(): void;
561
625
  deactivate(): void;
562
626
  init(initContent?: any): void;
@@ -602,7 +666,30 @@ declare module 'bpmn-elements' {
602
666
  var MessageEventDefinition: EventDefinition;
603
667
  var SignalEventDefinition: EventDefinition;
604
668
  var TerminateEventDefinition: EventDefinition;
605
- var TimerEventDefinition: EventDefinition;
669
+
670
+ const enum TimerType {
671
+ TimeCycle = 'timeCycle',
672
+ TimeDuration = 'timeDuration',
673
+ TimeDate = 'timeDate',
674
+ }
675
+
676
+ type parsedTimer = {
677
+ /** Expires at date time */
678
+ expireAt?: Date,
679
+ /** Repeat number of times */
680
+ repeat?: number,
681
+ /** Delay in milliseconds */
682
+ delay?: number,
683
+ };
684
+
685
+ class TimerEventDefinition extends EventDefinition {
686
+ /**
687
+ * Parse timer type
688
+ * @param timerType type of timer
689
+ * @param timerValue resolved expression timer string
690
+ */
691
+ parse(timerType: TimerType, timerValue: string): parsedTimer;
692
+ }
606
693
 
607
694
  class BpmnError {
608
695
  get id(): string;
@@ -641,6 +728,28 @@ declare module 'bpmn-elements' {
641
728
  code?: string;
642
729
  constructor(description: string, sourceMessage: MessageMessage, inner?: Error);
643
730
  }
731
+
732
+ interface Duration {
733
+ years?: number;
734
+ months?: number;
735
+ weeks?: number;
736
+ days?: number;
737
+ hours?: number;
738
+ minutes?: number;
739
+ seconds?: number;
740
+ repeat?: number;
741
+ }
742
+
743
+ type ISODurationApi = {
744
+ /** Parse PnYnMnDTnHnMnS format to object */
745
+ parse: (durationString: string) => Duration,
746
+ /** Convert ISO8601 duration object to an end Date. */
747
+ end: (durationInput: Duration, startDate?: Date) => Date,
748
+ /** Convert ISO8601 duration object to seconds */
749
+ toSeconds: (durationInput: Duration, startDate?: Date) => number,
750
+ }
751
+
752
+ const ISODuration: ISODurationApi;
644
753
  }
645
754
 
646
755
  /**