bpmn-elements 9.2.0 → 10.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.
- package/CHANGELOG.md +6 -0
- package/README.md +4 -0
- package/dist/Environment.js +1 -1
- package/dist/Timers.js +63 -43
- package/dist/eventDefinitions/TimerEventDefinition.js +51 -41
- package/dist/index.js +12 -0
- package/dist/iso-duration.js +88 -0
- package/package.json +6 -7
- package/src/Environment.js +1 -1
- package/src/Timers.js +71 -40
- package/src/eventDefinitions/TimerEventDefinition.js +49 -40
- package/src/index.js +4 -0
- package/src/iso-duration.js +91 -0
- package/types/index.d.ts +91 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
# 10.0.0
|
|
5
|
+
|
|
6
|
+
- drop iso8601-duration dependency and copy source (with licence). Export as `ISODuration`. Extend with repeat pattern parsing, e.g. `R3/PT1H` that corresponds to three repetitions every one hour
|
|
7
|
+
- expose `TimerEventDefinition.parse(timerType, value)` function for extension purposes
|
|
8
|
+
- prototype and export built-in `Timers`
|
|
9
|
+
|
|
4
10
|
# 9.2.0
|
|
5
11
|
|
|
6
12
|
- move outbound sequence flow evaluation logic from activity to sequence flow, where it belongs
|
package/README.md
CHANGED
|
@@ -77,3 +77,7 @@ The following elements are tested and supported.
|
|
|
77
77
|
- Transaction
|
|
78
78
|
|
|
79
79
|
All activities share the same [base](/docs/Activity.md) and and [api](/docs/SharedApi.md).
|
|
80
|
+
|
|
81
|
+
# Acknowledgments
|
|
82
|
+
|
|
83
|
+
ISO 8601 duration parser [iso8601-duration](https://www.npmjs.com/package/iso8601-duration) source is copied and extended with repeat pattern. License [MIT @ tolu](https://tolu.mit-license.org/)
|
package/dist/Environment.js
CHANGED
|
@@ -17,7 +17,7 @@ function Environment(options = {}) {
|
|
|
17
17
|
this.extensions = options.extensions;
|
|
18
18
|
this.output = options.output || {};
|
|
19
19
|
this.scripts = options.scripts || (0, _Scripts.Scripts)();
|
|
20
|
-
this.timers = options.timers ||
|
|
20
|
+
this.timers = options.timers || new _Timers.Timers();
|
|
21
21
|
this.settings = {
|
|
22
22
|
...options.settings
|
|
23
23
|
};
|
package/dist/Timers.js
CHANGED
|
@@ -4,57 +4,77 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.Timers = Timers;
|
|
7
|
+
const kExecuting = Symbol.for('executing');
|
|
8
|
+
const kTimerApi = Symbol.for('timers api');
|
|
9
|
+
const MAX_DELAY = 2147483647;
|
|
7
10
|
function Timers(options) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
options = {
|
|
11
|
+
this.count = 0;
|
|
12
|
+
this.options = {
|
|
11
13
|
setTimeout,
|
|
12
14
|
clearTimeout,
|
|
13
15
|
...options
|
|
14
16
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
};
|
|
23
|
-
return timersApi;
|
|
24
|
-
function register(owner) {
|
|
25
|
-
return {
|
|
26
|
-
setTimeout: registerTimeout(owner),
|
|
27
|
-
clearTimeout: timersApi.clearTimeout
|
|
28
|
-
};
|
|
17
|
+
this[kExecuting] = [];
|
|
18
|
+
this.setTimeout = this.setTimeout.bind(this);
|
|
19
|
+
this.clearTimeout = this.clearTimeout.bind(this);
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(Timers.prototype, 'executing', {
|
|
22
|
+
get() {
|
|
23
|
+
return this[kExecuting].slice();
|
|
29
24
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
});
|
|
26
|
+
Timers.prototype.register = function register(owner) {
|
|
27
|
+
return new RegisteredTimers(this, owner);
|
|
28
|
+
};
|
|
29
|
+
Timers.prototype.setTimeout = function wrappedSetTimeout(callback, delay, ...args) {
|
|
30
|
+
return this._setTimeout(null, callback, delay, ...args);
|
|
31
|
+
};
|
|
32
|
+
Timers.prototype.clearTimeout = function wrappedClearTimeout(ref) {
|
|
33
|
+
const executing = this[kExecuting];
|
|
34
|
+
const idx = executing.indexOf(ref);
|
|
35
|
+
if (idx > -1) {
|
|
36
|
+
executing.splice(idx, 1);
|
|
37
|
+
ref.timerRef = this.options.clearTimeout(ref.timerRef);
|
|
38
|
+
return;
|
|
34
39
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
executing.push(ref);
|
|
44
|
-
ref.timerRef = options.setTimeout.call(null, onTimeout, delay, ...args);
|
|
45
|
-
return ref;
|
|
46
|
-
function onTimeout(...rargs) {
|
|
47
|
-
const idx = executing.indexOf(ref);
|
|
48
|
-
if (idx > -1) executing.splice(idx, 1);
|
|
49
|
-
return callback(...rargs);
|
|
50
|
-
}
|
|
40
|
+
return this.options.clearTimeout(ref);
|
|
41
|
+
};
|
|
42
|
+
Timers.prototype._setTimeout = function setTimeout(owner, callback, delay, ...args) {
|
|
43
|
+
const executing = this[kExecuting];
|
|
44
|
+
const ref = this._getReference(owner, callback, delay, args);
|
|
45
|
+
executing.push(ref);
|
|
46
|
+
if (delay < MAX_DELAY) {
|
|
47
|
+
ref.timerRef = this.options.setTimeout(onTimeout, ref.delay, ...ref.args);
|
|
51
48
|
}
|
|
52
|
-
|
|
49
|
+
return ref;
|
|
50
|
+
function onTimeout(...rargs) {
|
|
53
51
|
const idx = executing.indexOf(ref);
|
|
54
|
-
if (idx > -1)
|
|
55
|
-
|
|
56
|
-
return options.clearTimeout.call(null, ref.timerRef);
|
|
57
|
-
}
|
|
58
|
-
return options.clearTimeout.call(null, ref);
|
|
52
|
+
if (idx > -1) executing.splice(idx, 1);
|
|
53
|
+
return callback(...rargs);
|
|
59
54
|
}
|
|
55
|
+
};
|
|
56
|
+
Timers.prototype._getReference = function getReference(owner, callback, delay, args) {
|
|
57
|
+
return new Timer(owner, `timer_${this.count++}`, callback, delay, args);
|
|
58
|
+
};
|
|
59
|
+
function RegisteredTimers(timersApi, owner) {
|
|
60
|
+
this[kTimerApi] = timersApi;
|
|
61
|
+
this.owner = owner;
|
|
62
|
+
this.setTimeout = this.setTimeout.bind(this);
|
|
63
|
+
this.clearTimeout = this.clearTimeout.bind(this);
|
|
64
|
+
}
|
|
65
|
+
RegisteredTimers.prototype.setTimeout = function registeredSetTimeout(callback, delay, ...args) {
|
|
66
|
+
const timersApi = this[kTimerApi];
|
|
67
|
+
return timersApi._setTimeout(this.owner, callback, delay, ...args);
|
|
68
|
+
};
|
|
69
|
+
RegisteredTimers.prototype.clearTimeout = function registeredClearTimeout(ref) {
|
|
70
|
+
this[kTimerApi].clearTimeout(ref);
|
|
71
|
+
};
|
|
72
|
+
function Timer(owner, timerId, callback, delay, args) {
|
|
73
|
+
this.callback = callback;
|
|
74
|
+
this.delay = delay;
|
|
75
|
+
this.args = args;
|
|
76
|
+
this.owner = owner;
|
|
77
|
+
this.timerId = timerId;
|
|
78
|
+
this.expireAt = new Date(Date.now() + delay);
|
|
79
|
+
this.timerRef = null;
|
|
60
80
|
}
|
|
@@ -5,13 +5,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = TimerEventDefinition;
|
|
7
7
|
var _messageHelper = require("../messageHelper.js");
|
|
8
|
-
var
|
|
8
|
+
var _isoDuration = require("../iso-duration.js");
|
|
9
9
|
const kStopped = Symbol.for('stopped');
|
|
10
10
|
const kTimerContent = Symbol.for('timerContent');
|
|
11
11
|
const kTimer = Symbol.for('timer');
|
|
12
|
-
const repeatPattern = /^\s*R(\d+)\//;
|
|
13
12
|
function TimerEventDefinition(activity, eventDefinition) {
|
|
14
|
-
const type = this.type = eventDefinition.type || 'TimerEventDefinition
|
|
13
|
+
const type = this.type = eventDefinition.type || 'TimerEventDefinition';
|
|
15
14
|
this.activity = activity;
|
|
16
15
|
const environment = this.environment = activity.environment;
|
|
17
16
|
this.eventDefinition = eventDefinition;
|
|
@@ -85,12 +84,14 @@ TimerEventDefinition.prototype.execute = function execute(executeMessage) {
|
|
|
85
84
|
if (timerContent.timeout === undefined) return this._debug(`waiting for ${timerContent.timerType || 'signal'}`);
|
|
86
85
|
if (timerContent.timeout <= 0) return this._completed();
|
|
87
86
|
const timers = this.environment.timers.register(timerContent);
|
|
88
|
-
|
|
87
|
+
const delay = timerContent.timeout;
|
|
88
|
+
this[kTimer] = timers.setTimeout(this._completed.bind(this), delay, {
|
|
89
89
|
id: content.id,
|
|
90
90
|
type: this.type,
|
|
91
91
|
executionId,
|
|
92
92
|
state: 'timeout'
|
|
93
93
|
});
|
|
94
|
+
this._debug(`set timeout with delay ${delay}`);
|
|
94
95
|
};
|
|
95
96
|
TimerEventDefinition.prototype.stop = function stopTimer() {
|
|
96
97
|
const timer = this[kTimer];
|
|
@@ -188,75 +189,84 @@ TimerEventDefinition.prototype._stop = function stop() {
|
|
|
188
189
|
broker.cancel(`_api-${this.executionId}`);
|
|
189
190
|
broker.cancel(`_api-delegated-${this.executionId}`);
|
|
190
191
|
};
|
|
192
|
+
TimerEventDefinition.prototype.parse = function parse(timerType, value) {
|
|
193
|
+
let repeat, delay, expireAt;
|
|
194
|
+
switch (timerType) {
|
|
195
|
+
case 'timeCycle':
|
|
196
|
+
case 'timeDuration':
|
|
197
|
+
{
|
|
198
|
+
const parsed = (0, _isoDuration.parse)(value);
|
|
199
|
+
if (parsed.repeat) repeat = parsed.repeat;
|
|
200
|
+
delay = (0, _isoDuration.toSeconds)(parsed) * 1000;
|
|
201
|
+
expireAt = new Date(Date.now() + delay);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case 'timeDate':
|
|
205
|
+
{
|
|
206
|
+
const ms = Date.parse(value);
|
|
207
|
+
if (!isNaN(ms)) {
|
|
208
|
+
expireAt = new Date(ms);
|
|
209
|
+
delay = Date.now() - expireAt;
|
|
210
|
+
} else {
|
|
211
|
+
throw new TypeError(`invalid timeDate >${value}<`);
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
expireAt,
|
|
218
|
+
repeat,
|
|
219
|
+
delay
|
|
220
|
+
};
|
|
221
|
+
};
|
|
191
222
|
TimerEventDefinition.prototype._getTimers = function getTimers(executeMessage) {
|
|
192
223
|
const content = executeMessage.content;
|
|
193
|
-
const now = Date.now();
|
|
194
224
|
const result = {
|
|
195
225
|
...('expireAt' in content && {
|
|
196
226
|
expireAt: new Date(content.expireAt)
|
|
197
227
|
})
|
|
198
228
|
};
|
|
229
|
+
let parseErr;
|
|
199
230
|
for (const t of ['timeDuration', 'timeDate', 'timeCycle']) {
|
|
200
231
|
if (t in content) result[t] = content[t];else if (t in this) result[t] = this.environment.resolveExpression(this[t], executeMessage);else continue;
|
|
201
232
|
let expireAtDate, repeat;
|
|
202
233
|
const timerStr = result[t];
|
|
203
234
|
if (timerStr) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (delay !== undefined) expireAtDate = new Date(now + delay);
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
case 'timeDate':
|
|
217
|
-
{
|
|
218
|
-
const dateStr = result[t];
|
|
219
|
-
const ms = Date.parse(dateStr);
|
|
220
|
-
if (!isNaN(ms)) {
|
|
221
|
-
expireAtDate = new Date(ms);
|
|
222
|
-
} else {
|
|
223
|
-
this._warn(`invalid timeDate >${dateStr}<`);
|
|
224
|
-
}
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
235
|
+
try {
|
|
236
|
+
const {
|
|
237
|
+
repeat: parsedRepeat,
|
|
238
|
+
expireAt: parsedExpireAt
|
|
239
|
+
} = this.parse(t, timerStr);
|
|
240
|
+
repeat = parsedRepeat;
|
|
241
|
+
expireAtDate = parsedExpireAt;
|
|
242
|
+
} catch (err) {
|
|
243
|
+
parseErr = err;
|
|
227
244
|
}
|
|
228
245
|
} else {
|
|
229
|
-
expireAtDate = new Date(
|
|
246
|
+
expireAtDate = new Date();
|
|
230
247
|
}
|
|
231
248
|
if (!expireAtDate) continue;
|
|
232
249
|
if (!('expireAt' in result) || result.expireAt > expireAtDate) {
|
|
233
250
|
result.timerType = t;
|
|
234
251
|
result.expireAt = expireAtDate;
|
|
235
|
-
|
|
252
|
+
result.repeat = repeat;
|
|
236
253
|
}
|
|
237
254
|
}
|
|
238
255
|
if ('expireAt' in result) {
|
|
239
|
-
result.timeout = result.expireAt - now;
|
|
256
|
+
result.timeout = result.expireAt - Date.now();
|
|
240
257
|
} else if ('timeout' in content) {
|
|
241
258
|
result.timeout = content.timeout;
|
|
242
259
|
} else if (!Object.keys(result).length) {
|
|
243
260
|
result.timeout = 0;
|
|
244
261
|
}
|
|
262
|
+
if (!('timeout' in result) && parseErr) {
|
|
263
|
+
this.logger.warn(`<${this.activity.id}> failed to parse timer: ${parseErr.message}`);
|
|
264
|
+
}
|
|
245
265
|
if (content.inbound && 'repeat' in content.inbound[0]) {
|
|
246
266
|
result.repeat = content.inbound[0].repeat;
|
|
247
267
|
}
|
|
248
268
|
return result;
|
|
249
269
|
};
|
|
250
|
-
TimerEventDefinition.prototype._getDurationInMilliseconds = function getDurationInMilliseconds(duration) {
|
|
251
|
-
try {
|
|
252
|
-
return (0, _iso8601Duration.toSeconds)((0, _iso8601Duration.parse)(duration)) * 1000;
|
|
253
|
-
} catch (err) {
|
|
254
|
-
this._warn(`failed to parse ${this.timerType} >${duration}<: ${err.message}`);
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
270
|
TimerEventDefinition.prototype._debug = function debug(msg) {
|
|
258
271
|
this.logger.debug(`<${this.executionId} (${this.activity.id})> ${msg}`);
|
|
259
|
-
};
|
|
260
|
-
TimerEventDefinition.prototype._warn = function debug(msg) {
|
|
261
|
-
this.logger.warn(`<${this.executionId} (${this.activity.id})> ${msg}`);
|
|
262
272
|
};
|
package/dist/index.js
CHANGED
|
@@ -147,6 +147,7 @@ Object.defineProperty(exports, "Group", {
|
|
|
147
147
|
return _Dummy.default;
|
|
148
148
|
}
|
|
149
149
|
});
|
|
150
|
+
exports.ISODuration = void 0;
|
|
150
151
|
Object.defineProperty(exports, "InclusiveGateway", {
|
|
151
152
|
enumerable: true,
|
|
152
153
|
get: function () {
|
|
@@ -321,6 +322,12 @@ Object.defineProperty(exports, "TimerEventDefinition", {
|
|
|
321
322
|
return _TimerEventDefinition.default;
|
|
322
323
|
}
|
|
323
324
|
});
|
|
325
|
+
Object.defineProperty(exports, "Timers", {
|
|
326
|
+
enumerable: true,
|
|
327
|
+
get: function () {
|
|
328
|
+
return _Timers.Timers;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
324
331
|
Object.defineProperty(exports, "Transaction", {
|
|
325
332
|
enumerable: true,
|
|
326
333
|
get: function () {
|
|
@@ -381,4 +388,9 @@ var _Task = _interopRequireDefault(require("./tasks/Task.js"));
|
|
|
381
388
|
var _TerminateEventDefinition = _interopRequireDefault(require("./eventDefinitions/TerminateEventDefinition.js"));
|
|
382
389
|
var _TimerEventDefinition = _interopRequireDefault(require("./eventDefinitions/TimerEventDefinition.js"));
|
|
383
390
|
var _Transaction = _interopRequireDefault(require("./tasks/Transaction.js"));
|
|
391
|
+
var _Timers = require("./Timers.js");
|
|
392
|
+
var ISODuration = _interopRequireWildcard(require("./iso-duration.js"));
|
|
393
|
+
exports.ISODuration = ISODuration;
|
|
394
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
395
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
384
396
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.end = end;
|
|
7
|
+
exports.parse = parse;
|
|
8
|
+
exports.toSeconds = toSeconds;
|
|
9
|
+
// License MIT @ https://tolu.mit-license.org/
|
|
10
|
+
|
|
11
|
+
const numbers = '\\d+';
|
|
12
|
+
const fractionalNumbers = ''.concat(numbers, '(?:[\\.,]').concat(numbers, ')?');
|
|
13
|
+
const datePattern = '('.concat(numbers, 'Y)?(').concat(numbers, 'M)?(').concat(numbers, 'W)?(').concat(fractionalNumbers, 'D)?');
|
|
14
|
+
const timePattern = 'T('.concat(fractionalNumbers, 'H)?(').concat(fractionalNumbers, 'M)?(').concat(fractionalNumbers, 'S)?');
|
|
15
|
+
const rPattern = '(?:R('.concat(numbers).concat(')/)?');
|
|
16
|
+
const iso8601 = rPattern.concat('P(?:').concat(datePattern, '(?:').concat(timePattern, ')?)');
|
|
17
|
+
const objMap = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'];
|
|
18
|
+
const defaultDuration = Object.freeze({
|
|
19
|
+
years: 0,
|
|
20
|
+
months: 0,
|
|
21
|
+
weeks: 0,
|
|
22
|
+
days: 0,
|
|
23
|
+
hours: 0,
|
|
24
|
+
minutes: 0,
|
|
25
|
+
seconds: 0
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The ISO8601 regex for matching / testing durations
|
|
30
|
+
*/
|
|
31
|
+
const pattern = new RegExp(iso8601);
|
|
32
|
+
|
|
33
|
+
/** Parse PnYnMnDTnHnMnS format to object */
|
|
34
|
+
function parse(durationString) {
|
|
35
|
+
const matches = durationString.replace(/,/g, '.').match(pattern);
|
|
36
|
+
if (!matches) {
|
|
37
|
+
throw new RangeError('invalid duration: ' + durationString);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Slice away repeat and first entry in match-array (the input string)
|
|
41
|
+
const slicedMatches = matches.slice(2);
|
|
42
|
+
if (slicedMatches.filter(Boolean).length === 0) {
|
|
43
|
+
throw new RangeError('invalid duration: ' + durationString);
|
|
44
|
+
}
|
|
45
|
+
// Check only one fraction is used
|
|
46
|
+
if (slicedMatches.filter(v => {
|
|
47
|
+
return /\./.test(v || '');
|
|
48
|
+
}).length > 1) {
|
|
49
|
+
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);
|
|
50
|
+
}
|
|
51
|
+
const result = {};
|
|
52
|
+
if (matches[1]) result.repeat = Number(matches[1]);
|
|
53
|
+
return slicedMatches.reduce((prev, next, idx) => {
|
|
54
|
+
prev[objMap[idx]] = parseFloat(next || '0') || 0;
|
|
55
|
+
return prev;
|
|
56
|
+
}, result);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Convert ISO8601 duration object to an end Date. */
|
|
60
|
+
function end(durationInput, startDate) {
|
|
61
|
+
const duration = Object.assign({}, defaultDuration, durationInput);
|
|
62
|
+
// Create two equal timestamps, add duration to 'then' and return time difference
|
|
63
|
+
const timestamp = startDate.getTime();
|
|
64
|
+
const then = new Date(timestamp);
|
|
65
|
+
then.setFullYear(then.getFullYear() + duration.years);
|
|
66
|
+
then.setMonth(then.getMonth() + duration.months);
|
|
67
|
+
then.setDate(then.getDate() + duration.days);
|
|
68
|
+
// set time as milliseconds to get fractions working for minutes/hours
|
|
69
|
+
const hoursInMs = duration.hours * 3600 * 1000;
|
|
70
|
+
const minutesInMs = duration.minutes * 60 * 1000;
|
|
71
|
+
then.setMilliseconds(then.getMilliseconds() + duration.seconds * 1000 + hoursInMs + minutesInMs);
|
|
72
|
+
// Special case weeks
|
|
73
|
+
then.setDate(then.getDate() + duration.weeks * 7);
|
|
74
|
+
return then;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Convert ISO8601 duration object to seconds */
|
|
78
|
+
function toSeconds(durationInput, startDate) {
|
|
79
|
+
if (startDate === void 0) {
|
|
80
|
+
startDate = new Date();
|
|
81
|
+
}
|
|
82
|
+
const duration = Object.assign({}, defaultDuration, durationInput);
|
|
83
|
+
const timestamp = startDate.getTime();
|
|
84
|
+
const now = new Date(timestamp);
|
|
85
|
+
const then = end(duration, now);
|
|
86
|
+
const seconds = (then.getTime() - now.getTime()) / 1000;
|
|
87
|
+
return seconds;
|
|
88
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bpmn-elements",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
4
4
|
"description": "Executable workflow elements based on BPMN 2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
],
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@aircall/expression-parser": "^1.0.4",
|
|
48
|
-
"@babel/cli": "^7.21.
|
|
49
|
-
"@babel/core": "^7.21.
|
|
50
|
-
"@babel/preset-env": "^7.21.
|
|
48
|
+
"@babel/cli": "^7.21.5",
|
|
49
|
+
"@babel/core": "^7.21.8",
|
|
50
|
+
"@babel/preset-env": "^7.21.5",
|
|
51
51
|
"@babel/register": "^7.21.0",
|
|
52
52
|
"bpmn-moddle": "^8.0.1",
|
|
53
53
|
"c8": "^7.13.0",
|
|
@@ -55,16 +55,15 @@
|
|
|
55
55
|
"chai": "^4.3.7",
|
|
56
56
|
"chronokinesis": "^5.0.2",
|
|
57
57
|
"debug": "^4.3.4",
|
|
58
|
-
"eslint": "^8.
|
|
58
|
+
"eslint": "^8.41.0",
|
|
59
59
|
"eslint-plugin-import": "^2.27.5",
|
|
60
60
|
"got": "^12.6.0",
|
|
61
61
|
"mocha": "^10.1.0",
|
|
62
62
|
"mocha-cakes-2": "^3.3.0",
|
|
63
63
|
"moddle-context-serializer": "^3.2.2",
|
|
64
|
-
"nock": "^13.
|
|
64
|
+
"nock": "^13.3.1"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"iso8601-duration": "^2.1.1",
|
|
68
67
|
"smqp": "^7.1.4"
|
|
69
68
|
}
|
|
70
69
|
}
|
package/src/Environment.js
CHANGED
|
@@ -24,7 +24,7 @@ export default function Environment(options = {}) {
|
|
|
24
24
|
this.extensions = options.extensions;
|
|
25
25
|
this.output = options.output || {};
|
|
26
26
|
this.scripts = options.scripts || IScripts();
|
|
27
|
-
this.timers = options.timers || Timers();
|
|
27
|
+
this.timers = options.timers || new Timers();
|
|
28
28
|
this.settings = {...options.settings};
|
|
29
29
|
this.Logger = options.Logger || DummyLogger;
|
|
30
30
|
this[kServices] = options.services || {};
|
package/src/Timers.js
CHANGED
|
@@ -1,56 +1,87 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const kExecuting = Symbol.for('executing');
|
|
2
|
+
const kTimerApi = Symbol.for('timers api');
|
|
3
|
+
|
|
4
|
+
const MAX_DELAY = 2147483647;
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
export function Timers(options) {
|
|
7
|
+
this.count = 0;
|
|
8
|
+
this.options = {
|
|
6
9
|
setTimeout,
|
|
7
10
|
clearTimeout,
|
|
8
11
|
...options,
|
|
9
12
|
};
|
|
13
|
+
this[kExecuting] = [];
|
|
14
|
+
this.setTimeout = this.setTimeout.bind(this);
|
|
15
|
+
this.clearTimeout = this.clearTimeout.bind(this);
|
|
16
|
+
}
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
setTimeout: wrappedSetTimeout,
|
|
17
|
-
clearTimeout: wrappedClearTimeout,
|
|
18
|
-
};
|
|
18
|
+
Object.defineProperty(Timers.prototype, 'executing', {
|
|
19
|
+
get() {
|
|
20
|
+
return this[kExecuting].slice();
|
|
21
|
+
},
|
|
22
|
+
});
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
Timers.prototype.register = function register(owner) {
|
|
25
|
+
return new RegisteredTimers(this, owner);
|
|
26
|
+
};
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
clearTimeout: timersApi.clearTimeout,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
+
Timers.prototype.setTimeout = function wrappedSetTimeout(callback, delay, ...args) {
|
|
29
|
+
return this._setTimeout(null, callback, delay, ...args);
|
|
30
|
+
};
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
Timers.prototype.clearTimeout = function wrappedClearTimeout(ref) {
|
|
33
|
+
const executing = this[kExecuting];
|
|
34
|
+
const idx = executing.indexOf(ref);
|
|
35
|
+
if (idx > -1) {
|
|
36
|
+
executing.splice(idx, 1);
|
|
37
|
+
ref.timerRef = this.options.clearTimeout(ref.timerRef);
|
|
38
|
+
return;
|
|
33
39
|
}
|
|
40
|
+
return this.options.clearTimeout(ref);
|
|
41
|
+
};
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
function onTimeout(...rargs) {
|
|
42
|
-
const idx = executing.indexOf(ref);
|
|
43
|
-
if (idx > -1) executing.splice(idx, 1);
|
|
44
|
-
return callback(...rargs);
|
|
45
|
-
}
|
|
43
|
+
Timers.prototype._setTimeout = function setTimeout(owner, callback, delay, ...args) {
|
|
44
|
+
const executing = this[kExecuting];
|
|
45
|
+
const ref = this._getReference(owner, callback, delay, args);
|
|
46
|
+
executing.push(ref);
|
|
47
|
+
if (delay < MAX_DELAY) {
|
|
48
|
+
ref.timerRef = this.options.setTimeout(onTimeout, ref.delay, ...ref.args);
|
|
46
49
|
}
|
|
50
|
+
return ref;
|
|
47
51
|
|
|
48
|
-
function
|
|
52
|
+
function onTimeout(...rargs) {
|
|
49
53
|
const idx = executing.indexOf(ref);
|
|
50
|
-
if (idx > -1)
|
|
51
|
-
|
|
52
|
-
return options.clearTimeout.call(null, ref.timerRef);
|
|
53
|
-
}
|
|
54
|
-
return options.clearTimeout.call(null, ref);
|
|
54
|
+
if (idx > -1) executing.splice(idx, 1);
|
|
55
|
+
return callback(...rargs);
|
|
55
56
|
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
Timers.prototype._getReference = function getReference(owner, callback, delay, args) {
|
|
60
|
+
return new Timer(owner, `timer_${this.count++}`, callback, delay, args);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
function RegisteredTimers(timersApi, owner) {
|
|
64
|
+
this[kTimerApi] = timersApi;
|
|
65
|
+
this.owner = owner;
|
|
66
|
+
this.setTimeout = this.setTimeout.bind(this);
|
|
67
|
+
this.clearTimeout = this.clearTimeout.bind(this);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
RegisteredTimers.prototype.setTimeout = function registeredSetTimeout(callback, delay, ...args) {
|
|
71
|
+
const timersApi = this[kTimerApi];
|
|
72
|
+
return timersApi._setTimeout(this.owner, callback, delay, ...args);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
RegisteredTimers.prototype.clearTimeout = function registeredClearTimeout(ref) {
|
|
76
|
+
this[kTimerApi].clearTimeout(ref);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
function Timer(owner, timerId, callback, delay, args) {
|
|
80
|
+
this.callback = callback;
|
|
81
|
+
this.delay = delay;
|
|
82
|
+
this.args = args;
|
|
83
|
+
this.owner = owner;
|
|
84
|
+
this.timerId = timerId;
|
|
85
|
+
this.expireAt = new Date(Date.now() + delay);
|
|
86
|
+
this.timerRef = null;
|
|
56
87
|
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {cloneContent} from '../messageHelper.js';
|
|
2
|
-
import {toSeconds, parse} from '
|
|
2
|
+
import {toSeconds, parse as parseIsoDuration} from '../iso-duration.js';
|
|
3
3
|
|
|
4
4
|
const kStopped = Symbol.for('stopped');
|
|
5
5
|
const kTimerContent = Symbol.for('timerContent');
|
|
6
6
|
const kTimer = Symbol.for('timer');
|
|
7
|
-
const repeatPattern = /^\s*R(\d+)\//;
|
|
8
7
|
|
|
9
8
|
export default function TimerEventDefinition(activity, eventDefinition) {
|
|
10
|
-
const type = this.type = eventDefinition.type || 'TimerEventDefinition
|
|
9
|
+
const type = this.type = eventDefinition.type || 'TimerEventDefinition';
|
|
11
10
|
this.activity = activity;
|
|
12
11
|
const environment = this.environment = activity.environment;
|
|
13
12
|
this.eventDefinition = eventDefinition;
|
|
@@ -85,12 +84,14 @@ TimerEventDefinition.prototype.execute = function execute(executeMessage) {
|
|
|
85
84
|
if (timerContent.timeout <= 0) return this._completed();
|
|
86
85
|
|
|
87
86
|
const timers = this.environment.timers.register(timerContent);
|
|
88
|
-
|
|
87
|
+
const delay = timerContent.timeout;
|
|
88
|
+
this[kTimer] = timers.setTimeout(this._completed.bind(this), delay, {
|
|
89
89
|
id: content.id,
|
|
90
90
|
type: this.type,
|
|
91
91
|
executionId,
|
|
92
92
|
state: 'timeout',
|
|
93
93
|
});
|
|
94
|
+
this._debug(`set timeout with delay ${delay}`);
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
TimerEventDefinition.prototype.stop = function stopTimer() {
|
|
@@ -175,14 +176,44 @@ TimerEventDefinition.prototype._stop = function stop() {
|
|
|
175
176
|
broker.cancel(`_api-delegated-${this.executionId}`);
|
|
176
177
|
};
|
|
177
178
|
|
|
179
|
+
TimerEventDefinition.prototype.parse = function parse(timerType, value) {
|
|
180
|
+
let repeat, delay, expireAt;
|
|
181
|
+
switch (timerType) {
|
|
182
|
+
case 'timeCycle':
|
|
183
|
+
case 'timeDuration': {
|
|
184
|
+
const parsed = parseIsoDuration(value);
|
|
185
|
+
if (parsed.repeat) repeat = parsed.repeat;
|
|
186
|
+
delay = toSeconds(parsed) * 1000;
|
|
187
|
+
expireAt = new Date(Date.now() + delay);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
case 'timeDate': {
|
|
191
|
+
const ms = Date.parse(value);
|
|
192
|
+
if (!isNaN(ms)) {
|
|
193
|
+
expireAt = new Date(ms);
|
|
194
|
+
delay = Date.now() - expireAt;
|
|
195
|
+
} else {
|
|
196
|
+
throw new TypeError(`invalid timeDate >${value}<`);
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
expireAt,
|
|
204
|
+
repeat,
|
|
205
|
+
delay,
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
|
|
178
209
|
TimerEventDefinition.prototype._getTimers = function getTimers(executeMessage) {
|
|
179
210
|
const content = executeMessage.content;
|
|
180
211
|
|
|
181
|
-
const now = Date.now();
|
|
182
212
|
const result = {
|
|
183
213
|
...('expireAt' in content && {expireAt: new Date(content.expireAt)}),
|
|
184
214
|
};
|
|
185
215
|
|
|
216
|
+
let parseErr;
|
|
186
217
|
for (const t of ['timeDuration', 'timeDate', 'timeCycle']) {
|
|
187
218
|
if (t in content) result[t] = content[t];
|
|
188
219
|
else if (t in this) result[t] = this.environment.resolveExpression(this[t], executeMessage);
|
|
@@ -191,47 +222,37 @@ TimerEventDefinition.prototype._getTimers = function getTimers(executeMessage) {
|
|
|
191
222
|
let expireAtDate, repeat;
|
|
192
223
|
const timerStr = result[t];
|
|
193
224
|
if (timerStr) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const delay = this._getDurationInMilliseconds(timerStr);
|
|
201
|
-
if (delay !== undefined) expireAtDate = new Date(now + delay);
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
case 'timeDate': {
|
|
205
|
-
const dateStr = result[t];
|
|
206
|
-
const ms = Date.parse(dateStr);
|
|
207
|
-
if (!isNaN(ms)) {
|
|
208
|
-
expireAtDate = new Date(ms);
|
|
209
|
-
} else {
|
|
210
|
-
this._warn(`invalid timeDate >${dateStr}<`);
|
|
211
|
-
}
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
225
|
+
try {
|
|
226
|
+
const {repeat: parsedRepeat, expireAt: parsedExpireAt} = this.parse(t, timerStr);
|
|
227
|
+
repeat = parsedRepeat;
|
|
228
|
+
expireAtDate = parsedExpireAt;
|
|
229
|
+
} catch (err) {
|
|
230
|
+
parseErr = err;
|
|
214
231
|
}
|
|
215
232
|
} else {
|
|
216
|
-
expireAtDate = new Date(
|
|
233
|
+
expireAtDate = new Date();
|
|
217
234
|
}
|
|
218
235
|
|
|
219
236
|
if (!expireAtDate) continue;
|
|
220
237
|
if (!('expireAt' in result) || result.expireAt > expireAtDate) {
|
|
221
238
|
result.timerType = t;
|
|
222
239
|
result.expireAt = expireAtDate;
|
|
223
|
-
|
|
240
|
+
result.repeat = repeat;
|
|
224
241
|
}
|
|
225
242
|
}
|
|
226
243
|
|
|
227
244
|
if ('expireAt' in result) {
|
|
228
|
-
result.timeout = result.expireAt - now;
|
|
245
|
+
result.timeout = result.expireAt - Date.now();
|
|
229
246
|
} else if ('timeout' in content) {
|
|
230
247
|
result.timeout = content.timeout;
|
|
231
248
|
} else if (!Object.keys(result).length) {
|
|
232
249
|
result.timeout = 0;
|
|
233
250
|
}
|
|
234
251
|
|
|
252
|
+
if (!('timeout' in result) && parseErr) {
|
|
253
|
+
this.logger.warn(`<${this.activity.id}> failed to parse timer: ${parseErr.message}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
235
256
|
if (content.inbound && 'repeat' in content.inbound[0]) {
|
|
236
257
|
result.repeat = content.inbound[0].repeat;
|
|
237
258
|
}
|
|
@@ -239,18 +260,6 @@ TimerEventDefinition.prototype._getTimers = function getTimers(executeMessage) {
|
|
|
239
260
|
return result;
|
|
240
261
|
};
|
|
241
262
|
|
|
242
|
-
TimerEventDefinition.prototype._getDurationInMilliseconds = function getDurationInMilliseconds(duration) {
|
|
243
|
-
try {
|
|
244
|
-
return toSeconds(parse(duration)) * 1000;
|
|
245
|
-
} catch (err) {
|
|
246
|
-
this._warn(`failed to parse ${this.timerType} >${duration}<: ${err.message}`);
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
|
|
250
263
|
TimerEventDefinition.prototype._debug = function debug(msg) {
|
|
251
264
|
this.logger.debug(`<${this.executionId} (${this.activity.id})> ${msg}`);
|
|
252
265
|
};
|
|
253
|
-
|
|
254
|
-
TimerEventDefinition.prototype._warn = function debug(msg) {
|
|
255
|
-
this.logger.warn(`<${this.executionId} (${this.activity.id})> ${msg}`);
|
|
256
|
-
};
|
package/src/index.js
CHANGED
|
@@ -46,6 +46,8 @@ import Task from './tasks/Task.js';
|
|
|
46
46
|
import TerminateEventDefinition from './eventDefinitions/TerminateEventDefinition.js';
|
|
47
47
|
import TimerEventDefinition from './eventDefinitions/TimerEventDefinition.js';
|
|
48
48
|
import Transaction from './tasks/Transaction.js';
|
|
49
|
+
import {Timers} from './Timers.js';
|
|
50
|
+
import * as ISODuration from './iso-duration.js';
|
|
49
51
|
|
|
50
52
|
export {
|
|
51
53
|
Association,
|
|
@@ -103,4 +105,6 @@ export {
|
|
|
103
105
|
TerminateEventDefinition,
|
|
104
106
|
TimerEventDefinition,
|
|
105
107
|
Transaction,
|
|
108
|
+
Timers,
|
|
109
|
+
ISODuration,
|
|
106
110
|
};
|
|
@@ -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
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -37,7 +37,8 @@ declare module 'bpmn-elements' {
|
|
|
37
37
|
content: ElementMessageContent,
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
class EventDefinition {
|
|
41
|
+
constructor(activity: Activity, eventDefinitionElement: SerializableElement)
|
|
41
42
|
get id(): string;
|
|
42
43
|
get type(): string;
|
|
43
44
|
get executionId(): string;
|
|
@@ -521,15 +522,53 @@ declare module 'bpmn-elements' {
|
|
|
521
522
|
[x: string]: any,
|
|
522
523
|
}
|
|
523
524
|
|
|
524
|
-
type wrappedSetTimeout = (handler:
|
|
525
|
-
type wrappedClearTimeout = (
|
|
525
|
+
type wrappedSetTimeout = (handler: TimerHandler, delay: number, ...args: any[]) => Timer;
|
|
526
|
+
type wrappedClearTimeout = (ref: any) => void;
|
|
527
|
+
|
|
528
|
+
interface Timer {
|
|
529
|
+
/** The function to call when the timer elapses */
|
|
530
|
+
readonly callback: TimerHandler;
|
|
531
|
+
/** The number of milliseconds to wait before calling the callback */
|
|
532
|
+
readonly delay: number;
|
|
533
|
+
/** Optional arguments to pass when the callback is called */
|
|
534
|
+
readonly args?: any[];
|
|
535
|
+
/** Timer owner if any */
|
|
536
|
+
readonly owner?: any;
|
|
537
|
+
/** Timer Id */
|
|
538
|
+
readonly timerId: string;
|
|
539
|
+
/** Timeout, return from setTimeout */
|
|
540
|
+
readonly timerRef: any;
|
|
541
|
+
[x: string]: any;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
interface RegisteredTimer {
|
|
545
|
+
owner?: any;
|
|
546
|
+
get setTimeout(): wrappedSetTimeout;
|
|
547
|
+
get clearTimeout(): wrappedClearTimeout;
|
|
548
|
+
}
|
|
526
549
|
|
|
527
550
|
interface ITimers {
|
|
528
|
-
get executing(): any[];
|
|
529
551
|
get setTimeout(): wrappedSetTimeout;
|
|
530
552
|
get clearTimeout(): wrappedClearTimeout;
|
|
531
|
-
register(owner?: any):
|
|
532
|
-
[x: string]: any
|
|
553
|
+
register(owner?: any): RegisteredTimer;
|
|
554
|
+
[x: string]: any;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
interface TimersOptions {
|
|
558
|
+
/** Defaults to builtin setTimeout */
|
|
559
|
+
setTimeout?: typeof setTimeout;
|
|
560
|
+
/** Defaults to builtin clearTimeout */
|
|
561
|
+
clearTimeout?: typeof clearTimeout;
|
|
562
|
+
[x: string]: any;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
class Timers implements ITimers {
|
|
566
|
+
options: TimersOptions;
|
|
567
|
+
constructor(options?: TimersOptions);
|
|
568
|
+
get executing(): Timer[];
|
|
569
|
+
get setTimeout(): wrappedSetTimeout;
|
|
570
|
+
get clearTimeout(): wrappedClearTimeout;
|
|
571
|
+
register(owner?: any): RegisteredTimer;
|
|
533
572
|
}
|
|
534
573
|
|
|
535
574
|
interface IScripts {
|
|
@@ -602,7 +641,30 @@ declare module 'bpmn-elements' {
|
|
|
602
641
|
var MessageEventDefinition: EventDefinition;
|
|
603
642
|
var SignalEventDefinition: EventDefinition;
|
|
604
643
|
var TerminateEventDefinition: EventDefinition;
|
|
605
|
-
|
|
644
|
+
|
|
645
|
+
const enum TimerType {
|
|
646
|
+
TimeCycle = 'timeCycle',
|
|
647
|
+
TimeDuration = 'timeDuration',
|
|
648
|
+
TimeDate = 'timeDate',
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
type parsedTimer = {
|
|
652
|
+
/** Expires at date time */
|
|
653
|
+
expireAt?: Date,
|
|
654
|
+
/** Repeat number of times */
|
|
655
|
+
repeat?: number,
|
|
656
|
+
/** Delay in milliseconds */
|
|
657
|
+
delay?: number,
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
class TimerEventDefinition extends EventDefinition {
|
|
661
|
+
/**
|
|
662
|
+
* Parse timer type
|
|
663
|
+
* @param timerType type of timer
|
|
664
|
+
* @param timerValue resolved expression timer string
|
|
665
|
+
*/
|
|
666
|
+
parse(timerType: TimerType, timerValue: string): parsedTimer;
|
|
667
|
+
}
|
|
606
668
|
|
|
607
669
|
class BpmnError {
|
|
608
670
|
get id(): string;
|
|
@@ -641,6 +703,28 @@ declare module 'bpmn-elements' {
|
|
|
641
703
|
code?: string;
|
|
642
704
|
constructor(description: string, sourceMessage: MessageMessage, inner?: Error);
|
|
643
705
|
}
|
|
706
|
+
|
|
707
|
+
interface Duration {
|
|
708
|
+
years?: number;
|
|
709
|
+
months?: number;
|
|
710
|
+
weeks?: number;
|
|
711
|
+
days?: number;
|
|
712
|
+
hours?: number;
|
|
713
|
+
minutes?: number;
|
|
714
|
+
seconds?: number;
|
|
715
|
+
repeat?: number;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
type ISODurationApi = {
|
|
719
|
+
/** Parse PnYnMnDTnHnMnS format to object */
|
|
720
|
+
parse: (durationString: string) => Duration,
|
|
721
|
+
/** Convert ISO8601 duration object to an end Date. */
|
|
722
|
+
end: (durationInput: Duration, startDate?: Date) => Date,
|
|
723
|
+
/** Convert ISO8601 duration object to seconds */
|
|
724
|
+
toSeconds: (durationInput: Duration, startDate?: Date) => number,
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const ISODuration: ISODurationApi;
|
|
644
728
|
}
|
|
645
729
|
|
|
646
730
|
/**
|