@onify/flow-extensions 1.0.0 → 2.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/dist/index.js CHANGED
@@ -5,21 +5,14 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.extendFn = extendFn;
7
7
  exports.extensions = extensions;
8
-
9
8
  var _cronParser = _interopRequireDefault(require("cron-parser"));
10
-
11
9
  var _IOProperties = _interopRequireDefault(require("./src/IOProperties"));
12
-
13
10
  var _IOForm = _interopRequireDefault(require("./src/IOForm"));
14
-
15
11
  var _Connector = _interopRequireDefault(require("./src/Connector"));
16
-
17
12
  var _ServiceExpression = _interopRequireDefault(require("./src/ServiceExpression"));
18
-
19
13
  var _IO = require("./src/IO");
20
-
21
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
-
15
+ const iso8601cycle = /^\s*(R\d+\/)?P\w+/i;
23
16
  class FormatError extends Error {
24
17
  constructor(elementId, err) {
25
18
  super(`<${elementId}> ${err.message}`);
@@ -28,33 +21,28 @@ class FormatError extends Error {
28
21
  statusCode: 500
29
22
  };
30
23
  }
31
-
32
24
  }
33
-
34
25
  function extensions(element, context) {
35
26
  if (element.type === 'bpmn:Process') return new OnifyProcessExtensions(element, context);
36
27
  return new OnifyElementExtensions(element, context);
37
28
  }
38
-
39
29
  class OnifyProcessExtensions {
40
30
  constructor(bp, context) {
41
31
  this.process = bp;
42
32
  this.context = context;
43
33
  this.extensions = getExtensions(bp, context);
44
-
45
34
  this._activate();
46
35
  }
47
-
48
36
  _activate() {
49
37
  const bp = this.process;
50
38
  bp.on('process.enter', elementApi => {
51
39
  try {
52
40
  const result = this._onEnter(elementApi);
53
-
54
41
  const environment = elementApi.environment;
55
42
  environment.assignVariables(result);
56
43
  } catch (err) {
57
- elementApi.broker.publish('event', 'process.error', { ...elementApi.content,
44
+ elementApi.broker.publish('event', 'process.error', {
45
+ ...elementApi.content,
58
46
  error: new FormatError(bp.id, err)
59
47
  }, {
60
48
  mandatory: true,
@@ -65,7 +53,6 @@ class OnifyProcessExtensions {
65
53
  consumerTag: '_onify-extension-on-enter'
66
54
  });
67
55
  }
68
-
69
56
  _onEnter(elementApi) {
70
57
  const {
71
58
  format,
@@ -74,17 +61,13 @@ class OnifyProcessExtensions {
74
61
  const result = {};
75
62
  Object.assign(result, format.resolve(elementApi));
76
63
  Object.assign(elementApi.content, result);
77
-
78
64
  if (properties) {
79
65
  Object.assign(result, properties.resolve(elementApi));
80
66
  Object.assign(elementApi.content, result);
81
67
  }
82
-
83
68
  return result;
84
69
  }
85
-
86
70
  }
87
-
88
71
  class OnifyElementExtensions {
89
72
  constructor(activity, context) {
90
73
  this.activity = activity;
@@ -92,43 +75,28 @@ class OnifyElementExtensions {
92
75
  const {
93
76
  Service
94
77
  } = this.extensions = getExtensions(activity, context);
95
-
96
78
  if (Service) {
97
79
  activity.behaviour.Service = Service;
98
80
  }
99
81
  }
100
-
101
- activate() {
82
+ activate(message) {
102
83
  const activity = this.activity;
103
84
  const broker = activity.broker;
104
85
  const formatQ = activity.broker.getQueue('format-run-q');
105
- activity.on('enter', async elementApi => {
106
- formatQ.queueMessage({
107
- routingKey: 'run.enter.format'
108
- }, {
109
- endRoutingKey: 'run.enter.complete'
86
+ if (message.fields.redelivered && message.fields.routingKey === 'run.start') {
87
+ activity.on('start', elementApi => {
88
+ this._formatOnEnter(broker, formatQ, elementApi);
110
89
  }, {
111
- persistent: false
90
+ consumerTag: '_onify-extension-on-enter'
112
91
  });
113
-
114
- try {
115
- var format = await this._onEnter(elementApi);
116
- } catch (err) {
117
- return broker.publish('format', 'run.enter.error', {
118
- error: err
119
- }, {
120
- persistent: false
121
- });
122
- }
123
-
124
- broker.publish('format', 'run.enter.complete', format, {
125
- persistent: false
92
+ } else {
93
+ activity.on('enter', elementApi => {
94
+ this._formatOnEnter(broker, formatQ, elementApi);
95
+ }, {
96
+ consumerTag: '_onify-extension-on-enter'
126
97
  });
127
- }, {
128
- consumerTag: '_onify-extension-on-enter'
129
- });
98
+ }
130
99
  activity.on('activity.execution.completed', async elementApi => {
131
- if (elementApi.fields.redelivered) return;
132
100
  formatQ.queueMessage({
133
101
  routingKey: 'run.end.format'
134
102
  }, {
@@ -136,7 +104,6 @@ class OnifyElementExtensions {
136
104
  }, {
137
105
  persistent: false
138
106
  });
139
-
140
107
  try {
141
108
  var format = await this._onExecuted(elementApi);
142
109
  } catch (err) {
@@ -146,8 +113,8 @@ class OnifyElementExtensions {
146
113
  persistent: false
147
114
  });
148
115
  }
149
-
150
- broker.publish('format', 'run.end.complete', { ...format
116
+ broker.publish('format', 'run.end.complete', {
117
+ ...format
151
118
  }, {
152
119
  persistent: false
153
120
  });
@@ -155,13 +122,32 @@ class OnifyElementExtensions {
155
122
  consumerTag: '_onify-extension-on-executed'
156
123
  });
157
124
  }
158
-
159
125
  deactivate() {
160
126
  const broker = this.activity.broker;
161
127
  broker.cancel('_onify-extension-on-enter');
162
128
  broker.cancel('_onify-extension-on-executed');
163
129
  }
164
-
130
+ async _formatOnEnter(broker, formatQ, elementApi) {
131
+ formatQ.queueMessage({
132
+ routingKey: 'run.enter.format'
133
+ }, {
134
+ endRoutingKey: 'run.enter.complete'
135
+ }, {
136
+ persistent: false
137
+ });
138
+ try {
139
+ var format = await this._onEnter(elementApi);
140
+ } catch (err) {
141
+ return broker.publish('format', 'run.enter.error', {
142
+ error: err
143
+ }, {
144
+ persistent: false
145
+ });
146
+ }
147
+ broker.publish('format', 'run.enter.complete', format, {
148
+ persistent: false
149
+ });
150
+ }
165
151
  async _onEnter(elementApi) {
166
152
  const {
167
153
  format,
@@ -172,47 +158,38 @@ class OnifyElementExtensions {
172
158
  const result = {};
173
159
  Object.assign(result, format.resolve(elementApi));
174
160
  Object.assign(elementApi.content, result);
175
-
176
161
  if (properties) {
177
162
  Object.assign(result, {
178
163
  properties: properties.resolve(elementApi)
179
164
  });
180
165
  Object.assign(elementApi.content, result);
181
166
  }
182
-
183
167
  if (io) {
184
- var _io$input, _io$output;
185
-
186
- if ((_io$input = io.input) !== null && _io$input !== void 0 && _io$input.length) {
168
+ if (io.input?.length) {
187
169
  const input = await io.getInput(this.activity, elementApi);
188
170
  Object.assign(result, {
189
171
  input
190
172
  });
191
173
  Object.assign(elementApi.content, result);
192
174
  }
193
-
194
- if ((_io$output = io.output) !== null && _io$output !== void 0 && _io$output.length) {
175
+ if (io.output?.length) {
195
176
  result.assignToOutput = true;
196
177
  }
197
178
  }
198
-
199
179
  if (form) {
200
180
  Object.assign(result, {
201
181
  form: form.resolve(elementApi)
202
182
  });
203
183
  }
204
-
205
184
  return result;
206
185
  }
207
-
208
186
  async _onExecuted(elementApi) {
209
187
  const {
210
188
  properties,
211
189
  io
212
190
  } = this.extensions;
213
191
  const result = {};
214
-
215
- if (io !== null && io !== void 0 && io.output.length) {
192
+ if (io?.output.length) {
216
193
  const output = await io.getOutput(this.activity, elementApi);
217
194
  Object.assign(result, {
218
195
  output
@@ -221,7 +198,6 @@ class OnifyElementExtensions {
221
198
  output
222
199
  });
223
200
  }
224
-
225
201
  if (properties) {
226
202
  const props = properties.resolve(elementApi);
227
203
  Object.assign(result, {
@@ -231,50 +207,39 @@ class OnifyElementExtensions {
231
207
  properties: props
232
208
  });
233
209
  }
234
-
235
210
  const {
236
211
  output,
237
212
  assignToOutput,
238
213
  resultVariable
239
214
  } = elementApi.content;
240
215
  if (output === undefined || output === null) return result;
241
-
242
216
  if (assignToOutput && typeof output === 'object') {
243
217
  Object.assign(this.activity.environment.output, output);
244
218
  } else if (resultVariable) {
245
219
  elementApi.environment.output[resultVariable] = output;
246
220
  }
247
-
248
221
  return result;
249
222
  }
250
-
251
223
  }
252
-
253
224
  function getExtensions(element, context) {
254
- var _element$behaviour$ex, _ext$values, _ext$fields;
255
-
256
225
  const result = {
257
226
  format: element.type === 'bpmn:Process' ? new FormatProcess(element) : new FormatActivity(element)
258
227
  };
259
228
  const expression = element.behaviour.expression;
260
229
  if (expression) result.Service = _ServiceExpression.default;
261
- const extensions = (_element$behaviour$ex = element.behaviour.extensionElements) === null || _element$behaviour$ex === void 0 ? void 0 : _element$behaviour$ex.values;
230
+ const extensions = element.behaviour.extensionElements?.values;
262
231
  if (!extensions) return result;
263
-
264
232
  for (const ext of extensions) {
265
233
  switch (ext.$type) {
266
234
  case 'camunda:Properties':
267
- if ((_ext$values = ext.values) !== null && _ext$values !== void 0 && _ext$values.length) result.properties = new _IOProperties.default(element, ext);
235
+ if (ext.values?.length) result.properties = new _IOProperties.default(element, ext);
268
236
  break;
269
-
270
237
  case 'camunda:InputOutput':
271
238
  result.io = new _IO.InputOutput(element.id, ext, context);
272
239
  break;
273
-
274
240
  case 'camunda:FormData':
275
- if ((_ext$fields = ext.fields) !== null && _ext$fields !== void 0 && _ext$fields.length) result.form = new _IOForm.default(element, ext);
241
+ if (ext.fields?.length) result.form = new _IOForm.default(element, ext);
276
242
  break;
277
-
278
243
  case 'camunda:Connector':
279
244
  {
280
245
  const {
@@ -287,16 +252,13 @@ function getExtensions(element, context) {
287
252
  }
288
253
  }
289
254
  }
290
-
291
255
  return result;
292
256
  }
293
-
294
257
  class FormatActivity {
295
258
  constructor(activity) {
296
259
  this.activity = activity;
297
260
  this.resultVariable = activity.behaviour.resultVariable || '_' + activity.id;
298
261
  let timeCycles;
299
-
300
262
  if (activity.eventDefinitions) {
301
263
  for (const ed of activity.eventDefinitions.filter(e => e.type === 'bpmn:TimerEventDefinition')) {
302
264
  if (!('timeCycle' in ed)) continue;
@@ -304,13 +266,9 @@ class FormatActivity {
304
266
  timeCycles.push(ed.timeCycle);
305
267
  }
306
268
  }
307
-
308
269
  this.timeCycles = timeCycles;
309
270
  }
310
-
311
271
  resolve(elementApi) {
312
- var _documentation$, _user, _groups;
313
-
314
272
  let user, groups, assigneeValue, description;
315
273
  const activity = this.activity;
316
274
  const {
@@ -323,30 +281,26 @@ class FormatActivity {
323
281
  if (candidateUsers) user = resolveAndSplit(elementApi, candidateUsers);
324
282
  if (candidateGroups) groups = resolveAndSplit(elementApi, candidateGroups);
325
283
  if (assignee) assigneeValue = elementApi.resolveExpression(assignee);
326
- if (documentation) description = (_documentation$ = documentation[0]) === null || _documentation$ === void 0 ? void 0 : _documentation$.text;
284
+ if (documentation) description = documentation[0]?.text;
327
285
  let expireAt;
328
286
  let timeCycles = this.timeCycles;
329
-
330
287
  if (timeCycles) {
331
288
  for (const cycle of timeCycles) {
332
289
  const cron = elementApi.resolveExpression(cycle);
333
- if (!cron) continue;
334
-
290
+ if (!cron || iso8601cycle.test(cron)) continue;
335
291
  const expireAtDt = _cronParser.default.parseExpression(cron).next().toDate();
336
-
337
292
  if (!expireAt || expireAtDt < expireAt) expireAt = expireAtDt;
338
293
  }
339
294
  }
340
-
341
295
  return {
342
296
  resultVariable: this.resultVariable,
343
- ...(scheduledStart && activity.parent.type === 'bpmn:Process' ? {
297
+ ...(scheduledStart && activity.parent.type === 'bpmn:Process' && {
344
298
  scheduledStart
345
- } : undefined),
346
- ...(((_user = user) === null || _user === void 0 ? void 0 : _user.length) && {
299
+ }),
300
+ ...(user?.length && {
347
301
  candidateUsers: user
348
302
  }),
349
- ...(((_groups = groups) === null || _groups === void 0 ? void 0 : _groups.length) && {
303
+ ...(groups?.length && {
350
304
  candidateGroups: groups
351
305
  }),
352
306
  ...(!elementApi.content.description && description && {
@@ -360,17 +314,12 @@ class FormatActivity {
360
314
  })
361
315
  };
362
316
  }
363
-
364
317
  }
365
-
366
318
  class FormatProcess {
367
319
  constructor(bp) {
368
320
  this.process = bp;
369
321
  }
370
-
371
322
  resolve(elementApi) {
372
- var _documentation$2, _user2, _groups2;
373
-
374
323
  let user, groups, description;
375
324
  const bp = this.process;
376
325
  const {
@@ -380,13 +329,13 @@ class FormatProcess {
380
329
  } = bp.behaviour;
381
330
  if (candidateStarterUsers) user = resolveAndSplit(elementApi, candidateStarterUsers);
382
331
  if (candidateStarterGroups) groups = resolveAndSplit(elementApi, candidateStarterGroups);
383
- if (documentation) description = (_documentation$2 = documentation[0]) === null || _documentation$2 === void 0 ? void 0 : _documentation$2.text;
332
+ if (documentation) description = documentation[0]?.text;
384
333
  return {
385
334
  resultVariable: this.resultVariable,
386
- ...(((_user2 = user) === null || _user2 === void 0 ? void 0 : _user2.length) && {
335
+ ...(user?.length && {
387
336
  candidateStarterUsers: user
388
337
  }),
389
- ...(((_groups2 = groups) === null || _groups2 === void 0 ? void 0 : _groups2.length) && {
338
+ ...(groups?.length && {
390
339
  candidateStarterGroups: groups
391
340
  }),
392
341
  ...(!elementApi.content.description && description && {
@@ -394,9 +343,7 @@ class FormatProcess {
394
343
  })
395
344
  };
396
345
  }
397
-
398
346
  }
399
-
400
347
  function resolveAndSplit(elementApi, str) {
401
348
  if (Array.isArray(str)) return str.filter(Boolean);
402
349
  if (typeof str !== 'string') return;
@@ -405,10 +352,7 @@ function resolveAndSplit(elementApi, str) {
405
352
  if (typeof resolved !== 'string') return;
406
353
  return resolved.split(',').map(g => g.trim && g.trim().toLowerCase()).filter(Boolean);
407
354
  }
408
-
409
355
  function extendFn(behaviour, context) {
410
- var _behaviour$extensionE;
411
-
412
356
  if (behaviour.$type === 'bpmn:StartEvent' && behaviour.eventDefinitions) {
413
357
  const timer = behaviour.eventDefinitions.find(({
414
358
  type,
@@ -418,21 +362,18 @@ function extendFn(behaviour, context) {
418
362
  scheduledStart: timer.behaviour.timeCycle
419
363
  });
420
364
  }
421
-
422
- if (!Array.isArray((_behaviour$extensionE = behaviour.extensionElements) === null || _behaviour$extensionE === void 0 ? void 0 : _behaviour$extensionE.values)) return;
365
+ if (!Array.isArray(behaviour.extensionElements?.values)) return;
423
366
  const inputOutput = behaviour.extensionElements.values.find(el => el.$type === 'camunda:InputOutput');
424
367
  const connector = behaviour.extensionElements.values.find(el => el.$type === 'camunda:Connector');
425
368
  if (inputOutput) registerIOScripts(behaviour.id, context, inputOutput.$type, inputOutput);
426
369
  if (connector) registerIOScripts(behaviour.id, context, connector.$type, connector.inputOutput);
427
370
  }
428
-
429
371
  function registerIOScripts(parentId, context, type, ioBehaviour) {
430
372
  if (!ioBehaviour) return;
431
373
  const {
432
374
  inputParameters = [],
433
375
  outputParameters = []
434
376
  } = ioBehaviour;
435
-
436
377
  for (const {
437
378
  $type,
438
379
  name,
@@ -444,12 +385,12 @@ function registerIOScripts(parentId, context, type, ioBehaviour) {
444
385
  context.addScript(filename, {
445
386
  id: filename,
446
387
  scriptFormat: definition.scriptFormat,
447
- ...(definition.value ? {
388
+ ...(definition.value && {
448
389
  body: definition.value
449
- } : undefined),
450
- ...(definition.resource ? {
390
+ }),
391
+ ...(definition.resource && {
451
392
  resource: definition.resource
452
- } : undefined)
393
+ })
453
394
  });
454
395
  }
455
396
  }
@@ -4,9 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = Connector;
7
-
8
7
  var _Errors = require("./Errors");
9
-
10
8
  function Connector(connectorId, io, activity, executionMessage) {
11
9
  if (!(this instanceof Connector)) return new Connector(connectorId, io, activity, executionMessage);
12
10
  this.connectorId = connectorId;
@@ -14,7 +12,6 @@ function Connector(connectorId, io, activity, executionMessage) {
14
12
  this.activity = activity;
15
13
  this.executionMessage = executionMessage;
16
14
  }
17
-
18
15
  Connector.prototype.execute = async function execute(...args) {
19
16
  const callback = args.pop();
20
17
  args.push(formatCallback);
@@ -25,20 +22,18 @@ Connector.prototype.execute = async function execute(...args) {
25
22
  const executionMessage = this.executionMessage;
26
23
  const serviceFunction = environment.services[connectorId];
27
24
  if (!serviceFunction) return callback(new _Errors.NotImplemented(connectorId));
28
-
29
25
  try {
30
26
  const input = io && (await io.getInput(activity, executionMessage));
31
27
  await serviceFunction.call(activity, input, ...args);
32
28
  } catch (err) {
33
29
  return callback(err);
34
30
  }
35
-
36
31
  async function formatCallback(serviceErr, result) {
37
32
  if (serviceErr) return callback(serviceErr);
38
- if (!(io !== null && io !== void 0 && io.output.length)) return callback(null, result);
39
-
33
+ if (!io?.output.length) return callback(null, result);
40
34
  try {
41
- const formattedResult = await io.getOutput(activity, { ...executionMessage,
35
+ const formattedResult = await io.getOutput(activity, {
36
+ ...executionMessage,
42
37
  ...result
43
38
  });
44
39
  return callback(null, formattedResult);
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.NotImplemented = void 0;
7
-
8
7
  class NotImplemented extends Error {
9
8
  constructor(serviceId) {
10
9
  super(`${serviceId} service function not found`);
@@ -13,7 +12,5 @@ class NotImplemented extends Error {
13
12
  statusCode: 501
14
13
  };
15
14
  }
16
-
17
15
  }
18
-
19
16
  exports.NotImplemented = NotImplemented;
@@ -6,16 +6,11 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.FlowScripts = FlowScripts;
7
7
  exports.JavaScript = JavaScript;
8
8
  exports.JavaScriptResource = JavaScriptResource;
9
-
10
9
  var _path = require("path");
11
-
12
10
  var _fs = require("fs");
13
-
14
11
  var _vm = require("vm");
15
-
16
12
  const kSyntaxError = Symbol.for('syntax error');
17
13
  const kResources = Symbol.for('resources base');
18
-
19
14
  class FlowScriptError extends Error {
20
15
  constructor(fromErr) {
21
16
  super(fromErr.message);
@@ -25,22 +20,17 @@ class FlowScriptError extends Error {
25
20
  get() {
26
21
  return fromErr.stack && fromErr.stack.split('\n').slice(0, 7).join('\n');
27
22
  }
28
-
29
23
  });
30
24
  Object.defineProperty(this, 'code', {
31
25
  get() {
32
26
  return 'EFLOW_SCRIPT';
33
27
  }
34
-
35
28
  });
36
29
  }
37
-
38
30
  toString() {
39
31
  return '[FlowScriptError] ' + this.message + '\n' + this.stack;
40
32
  }
41
-
42
33
  }
43
-
44
34
  class FlowSyntaxError extends Error {
45
35
  constructor(fromErr) {
46
36
  super(fromErr.message);
@@ -50,22 +40,17 @@ class FlowSyntaxError extends Error {
50
40
  get() {
51
41
  return fromErr.stack && fromErr.stack.split('\n').slice(0, 6).join('\n');
52
42
  }
53
-
54
43
  });
55
44
  Object.defineProperty(this, 'code', {
56
45
  get() {
57
46
  return 'EFLOW_SCRIPT';
58
47
  }
59
-
60
48
  });
61
49
  }
62
-
63
50
  toString() {
64
51
  return '[FlowSyntaxError] ' + this.message + '\n' + this.stack;
65
52
  }
66
-
67
53
  }
68
-
69
54
  function FlowScripts(flowName, resourceBase, runContext, timeout = 60000) {
70
55
  this._name = flowName;
71
56
  this._scripts = {};
@@ -73,14 +58,12 @@ function FlowScripts(flowName, resourceBase, runContext, timeout = 60000) {
73
58
  this._runContext = runContext;
74
59
  this[kResources] = resourceBase;
75
60
  }
76
-
77
61
  FlowScripts.prototype.register = function register({
78
62
  id,
79
63
  type,
80
64
  behaviour
81
65
  }) {
82
66
  let language, scriptBody, resource;
83
-
84
67
  switch (type) {
85
68
  case 'bpmn:SequenceFlow':
86
69
  {
@@ -90,7 +73,6 @@ FlowScripts.prototype.register = function register({
90
73
  resource = behaviour.conditionExpression.resource;
91
74
  break;
92
75
  }
93
-
94
76
  default:
95
77
  {
96
78
  language = behaviour.scriptFormat;
@@ -98,13 +80,11 @@ FlowScripts.prototype.register = function register({
98
80
  resource = behaviour.resource;
99
81
  }
100
82
  }
101
-
102
83
  if (!language) language = 'javascript';
103
84
  if (!['js', 'javascript'].includes(language.toLowerCase().trim())) return;
104
85
  language = 'javascript';
105
86
  const name = this._name;
106
87
  const filename = `${name}/${type}/${id}`;
107
-
108
88
  if (scriptBody) {
109
89
  this._scripts[id] = new JavaScript(name, scriptBody, this._runContext, {
110
90
  filename,
@@ -117,37 +97,33 @@ FlowScripts.prototype.register = function register({
117
97
  });
118
98
  }
119
99
  };
120
-
121
100
  FlowScripts.prototype.getScript = function getScript(scriptType, {
122
101
  id
123
102
  }) {
124
103
  return this._scripts[id];
125
104
  };
126
-
127
105
  function JavaScript(flowName, scriptBody, runContext, options) {
128
106
  this.flowName = flowName;
129
107
  this._runContext = runContext;
130
108
  this.timeout = options && options.timeout;
131
-
132
109
  try {
133
110
  this.script = new _vm.Script(scriptBody, options);
134
111
  } catch (err) {
135
112
  this[kSyntaxError] = new FlowSyntaxError(err);
136
113
  }
137
114
  }
138
-
139
115
  JavaScript.prototype.execute = async function execute(executionContext, callback) {
140
116
  let callbackCalled;
141
117
  const syntaxError = this[kSyntaxError];
142
118
  if (syntaxError) return next(syntaxError);
143
-
144
119
  try {
145
- await this.script.runInNewContext({ ...executionContext,
120
+ await this.script.runInNewContext({
121
+ ...executionContext,
146
122
  Date,
147
123
  console: {
148
124
  log: console.log // eslint-disable-line no-console
149
-
150
125
  },
126
+
151
127
  Buffer: {
152
128
  from: Buffer.from
153
129
  },
@@ -160,15 +136,13 @@ JavaScript.prototype.execute = async function execute(executionContext, callback
160
136
  } catch (err) {
161
137
  return next(new FlowScriptError(err));
162
138
  }
163
-
164
- async function next(err, ...args) {
139
+ function next(err, ...args) {
165
140
  if (callbackCalled) return;
166
141
  callbackCalled = true;
167
142
  if (err) return callback(err);
168
143
  callback(null, ...args);
169
144
  }
170
145
  };
171
-
172
146
  function JavaScriptResource(flowName, resource, resourceBase, runContext, options) {
173
147
  this.flowName = flowName;
174
148
  this.resource = resource;
@@ -176,7 +150,6 @@ function JavaScriptResource(flowName, resource, resourceBase, runContext, option
176
150
  this._runContext = runContext;
177
151
  this[kResources] = resourceBase;
178
152
  }
179
-
180
153
  JavaScriptResource.prototype.execute = async function execute(executionContext, callback) {
181
154
  try {
182
155
  var scriptBody = await _fs.promises.readFile((0, _path.join)(this[kResources], executionContext.resolveExpression(this.resource))); // eslint-disable-line no-var
@@ -186,8 +159,8 @@ JavaScriptResource.prototype.execute = async function execute(executionContext,
186
159
  } = this.options;
187
160
  return callback(new Error(`${filename}: script resource ${this.resource} not found`));
188
161
  }
189
-
190
- const script = new JavaScript(this.flowName, scriptBody, this._runContext, { ...this.options,
162
+ const script = new JavaScript(this.flowName, scriptBody, this._runContext, {
163
+ ...this.options,
191
164
  filename: this.resource
192
165
  });
193
166
  return script.execute(executionContext, callback);
package/dist/src/IO.js CHANGED
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.InputOutput = exports.IOScript = exports.IOMap = exports.IOList = exports.IOBase = void 0;
7
-
8
7
  class InputOutput {
9
8
  constructor(parentId, behaviour, context) {
10
9
  this.parentId = parentId;
@@ -16,40 +15,33 @@ class InputOutput {
16
15
  this.input = this._map(parentId, inputParameters, 'input', context);
17
16
  this.output = this._map(parentId, outputParameters, 'output', context);
18
17
  }
19
-
20
18
  async getInput(activity, executionMessage) {
21
19
  const input = this.input;
22
20
  const values = await Promise.all(input.map(parm => parm.getValue(activity, executionMessage)));
23
21
  return values.reduce((result, parm) => Object.assign(result, parm), {});
24
22
  }
25
-
26
23
  async getOutput(activity, executionMessage) {
27
24
  const output = this.output;
28
25
  const values = await Promise.all(output.map(parm => parm.getValue(activity, executionMessage)));
29
26
  return values.reduce((result, parm) => Object.assign(result, parm), {});
30
27
  }
31
-
32
28
  _map(parentId, list, ioType, context) {
33
29
  const mapped = [];
34
30
  if (!list) return mapped;
35
-
36
31
  for (const parm of list) {
37
32
  const definition = parm.definition;
38
33
  const type = definition && definition.$type;
39
-
40
34
  switch (type) {
41
35
  case 'camunda:Map':
42
36
  {
43
37
  mapped.push(new IOMap(parm));
44
38
  break;
45
39
  }
46
-
47
40
  case 'camunda:List':
48
41
  {
49
42
  mapped.push(new IOList(parm));
50
43
  break;
51
44
  }
52
-
53
45
  case 'camunda:Script':
54
46
  {
55
47
  const id = `${parentId}/${ioType}/${type}/${parm.name}`;
@@ -64,54 +56,44 @@ class InputOutput {
64
56
  type: parm.$type,
65
57
  behaviour: {
66
58
  scriptFormat,
67
- ...(value ? {
59
+ ...(value && {
68
60
  script: value
69
- } : undefined),
70
- ...(resource ? {
61
+ }),
62
+ ...(resource && {
71
63
  resource
72
- } : undefined)
64
+ })
73
65
  }
74
66
  });
75
67
  mapped.push(new IOScript(parm, id));
76
68
  break;
77
69
  }
78
-
79
70
  default:
80
71
  {
81
72
  mapped.push(new IOBase(parm));
82
73
  }
83
74
  }
84
75
  }
85
-
86
76
  return mapped;
87
77
  }
88
-
89
78
  }
90
-
91
79
  exports.InputOutput = InputOutput;
92
-
93
80
  class IOBase {
94
81
  constructor(parm) {
95
82
  this.name = parm.name;
96
83
  this.type = parm.definition && parm.definition.$type || 'string';
97
84
  this.behaviour = parm;
98
85
  }
99
-
100
86
  getValue(activity, executionMessage) {
101
87
  return {
102
88
  [this.name]: activity.environment.resolveExpression(this.behaviour.value, executionMessage)
103
89
  };
104
90
  }
105
-
106
91
  }
107
-
108
92
  exports.IOBase = IOBase;
109
-
110
93
  class IOMap extends IOBase {
111
94
  constructor(parm) {
112
95
  super(parm);
113
96
  }
114
-
115
97
  getValue(activity, executionMessage) {
116
98
  const name = this.name;
117
99
  const entries = this.behaviour.definition.entries;
@@ -120,18 +102,15 @@ class IOMap extends IOBase {
120
102
  };
121
103
  const environment = activity.environment;
122
104
  const result = {};
123
-
124
105
  for (const {
125
106
  key,
126
107
  value
127
108
  } of entries) {
128
109
  if (!key) continue;
129
110
  const val = environment.resolveExpression(value, executionMessage);
130
-
131
111
  if (key in result) {
132
112
  if (val === undefined) continue;
133
113
  const current = result[key];
134
-
135
114
  if (Array.isArray(current)) {
136
115
  current.push(val);
137
116
  } else {
@@ -143,21 +122,16 @@ class IOMap extends IOBase {
143
122
  result[key] = val;
144
123
  }
145
124
  }
146
-
147
125
  return {
148
126
  [name]: result
149
127
  };
150
128
  }
151
-
152
129
  }
153
-
154
130
  exports.IOMap = IOMap;
155
-
156
131
  class IOList extends IOBase {
157
132
  constructor(parm) {
158
133
  super(parm);
159
134
  }
160
-
161
135
  getValue(activity, executionMessage) {
162
136
  const name = this.name;
163
137
  const items = this.behaviour.definition.items;
@@ -166,28 +140,22 @@ class IOList extends IOBase {
166
140
  [name]: result
167
141
  };
168
142
  const environment = activity.environment;
169
-
170
143
  for (const item of items) {
171
144
  const val = environment.resolveExpression(item.value, executionMessage);
172
145
  if (val !== undefined) result.push(val);
173
146
  }
174
-
175
147
  return {
176
148
  [name]: result
177
149
  };
178
150
  }
179
-
180
151
  }
181
-
182
152
  exports.IOList = IOList;
183
-
184
153
  class IOScript extends IOBase {
185
154
  constructor(parm, scriptId) {
186
155
  super(parm);
187
156
  this.id = scriptId;
188
157
  this.script = true;
189
158
  }
190
-
191
159
  getValue(activity, executionMessage) {
192
160
  const definition = this.behaviour.definition;
193
161
  const name = this.name;
@@ -221,12 +189,9 @@ class IOScript extends IOBase {
221
189
  });
222
190
  });
223
191
  });
224
-
225
192
  function resolveExpression(expression) {
226
193
  return environment.resolveExpression(expression, scope);
227
194
  }
228
195
  }
229
-
230
196
  }
231
-
232
197
  exports.IOScript = IOScript;
@@ -4,22 +4,18 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _IOProperties = _interopRequireDefault(require("./IOProperties.js"));
9
-
10
8
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
12
9
  class IOForm {
13
10
  constructor(activity, behaviour) {
14
11
  this.activity = activity;
15
12
  this.behaviour = behaviour;
16
13
  }
17
-
18
14
  resolve(elementApi) {
19
15
  const form = {};
20
-
21
16
  for (const field of this.behaviour.fields) {
22
- const f = form[field.id] = { ...field,
17
+ const f = form[field.id] = {
18
+ ...field,
23
19
  ...(field.label && {
24
20
  defaultValue: elementApi.resolveExpression(field.label)
25
21
  }),
@@ -27,15 +23,11 @@ class IOForm {
27
23
  defaultValue: elementApi.resolveExpression(field.defaultValue)
28
24
  })
29
25
  };
30
-
31
26
  if (f.properties) {
32
27
  f.properties = new _IOProperties.default(this.activity, f.properties).resolve(elementApi);
33
28
  }
34
29
  }
35
-
36
30
  return form;
37
31
  }
38
-
39
32
  }
40
-
41
33
  exports.default = IOForm;
@@ -4,16 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  class IOProperties {
9
8
  constructor(activity, behaviour) {
10
9
  this.activity = activity;
11
10
  this.behaviour = behaviour;
12
11
  }
13
-
14
12
  resolve(elementApi) {
15
13
  const properties = {};
16
-
17
14
  for (const {
18
15
  id,
19
16
  name,
@@ -21,10 +18,7 @@ class IOProperties {
21
18
  } of this.behaviour.values) {
22
19
  properties[id || name] = elementApi.resolveExpression(value);
23
20
  }
24
-
25
21
  return properties;
26
22
  }
27
-
28
23
  }
29
-
30
24
  exports.default = IOProperties;
@@ -4,16 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = ServiceExpression;
7
-
8
7
  var _Errors = require("./Errors");
9
-
10
8
  function ServiceExpression(activity) {
11
9
  if (!(this instanceof ServiceExpression)) return new ServiceExpression(activity);
12
10
  this.activity = activity;
13
11
  this.type = `${activity.type}:expression`;
14
12
  this.expression = activity.behaviour.expression;
15
13
  }
16
-
17
14
  ServiceExpression.prototype.execute = function execute(executionMessage, callback) {
18
15
  try {
19
16
  const expression = this.expression;
@@ -22,7 +19,6 @@ ServiceExpression.prototype.execute = function execute(executionMessage, callbac
22
19
  } catch (err) {
23
20
  return callback(err);
24
21
  }
25
-
26
22
  serviceFn.call(this.activity, executionMessage, (err, result) => {
27
23
  callback(err, result);
28
24
  });
package/index.js CHANGED
@@ -5,6 +5,8 @@ import Connector from './src/Connector';
5
5
  import ServiceExpression from './src/ServiceExpression';
6
6
  import {InputOutput} from './src/IO';
7
7
 
8
+ const iso8601cycle = /^\s*(R\d+\/)?P\w+/i;
9
+
8
10
  class FormatError extends Error {
9
11
  constructor(elementId, err) {
10
12
  super(`<${elementId}> ${err.message}`);
@@ -70,26 +72,22 @@ class OnifyElementExtensions {
70
72
  activity.behaviour.Service = Service;
71
73
  }
72
74
  }
73
- activate() {
75
+ activate(message) {
74
76
  const activity = this.activity;
75
77
  const broker = activity.broker;
76
78
  const formatQ = activity.broker.getQueue('format-run-q');
77
79
 
78
- activity.on('enter', async (elementApi) => {
79
- formatQ.queueMessage({routingKey: 'run.enter.format'}, {endRoutingKey: 'run.enter.complete'}, {persistent: false});
80
-
81
- try {
82
- var format = await this._onEnter(elementApi);
83
- } catch (err) {
84
- return broker.publish('format', 'run.enter.error', {error: err}, {persistent: false});
85
- }
86
-
87
- broker.publish('format', 'run.enter.complete', format, {persistent: false});
88
- }, {consumerTag: '_onify-extension-on-enter'});
80
+ if (message.fields.redelivered && message.fields.routingKey === 'run.start') {
81
+ activity.on('start', (elementApi) => {
82
+ this._formatOnEnter(broker, formatQ, elementApi);
83
+ }, {consumerTag: '_onify-extension-on-enter'});
84
+ } else {
85
+ activity.on('enter', (elementApi) => {
86
+ this._formatOnEnter(broker, formatQ, elementApi);
87
+ }, {consumerTag: '_onify-extension-on-enter'});
88
+ }
89
89
 
90
90
  activity.on('activity.execution.completed', async (elementApi) => {
91
- if (elementApi.fields.redelivered) return;
92
-
93
91
  formatQ.queueMessage({routingKey: 'run.end.format'}, {endRoutingKey: 'run.end.complete'}, {persistent: false});
94
92
 
95
93
  try {
@@ -106,6 +104,17 @@ class OnifyElementExtensions {
106
104
  broker.cancel('_onify-extension-on-enter');
107
105
  broker.cancel('_onify-extension-on-executed');
108
106
  }
107
+ async _formatOnEnter(broker, formatQ, elementApi) {
108
+ formatQ.queueMessage({routingKey: 'run.enter.format'}, {endRoutingKey: 'run.enter.complete'}, {persistent: false});
109
+
110
+ try {
111
+ var format = await this._onEnter(elementApi);
112
+ } catch (err) {
113
+ return broker.publish('format', 'run.enter.error', {error: err}, {persistent: false});
114
+ }
115
+
116
+ broker.publish('format', 'run.enter.complete', format, {persistent: false});
117
+ }
109
118
  async _onEnter(elementApi) {
110
119
  const {format, properties, io, form} = this.extensions;
111
120
 
@@ -176,7 +185,6 @@ function getExtensions(element, context) {
176
185
  const extensions = element.behaviour.extensionElements?.values;
177
186
  if (!extensions) return result;
178
187
 
179
-
180
188
  for (const ext of extensions) {
181
189
  switch (ext.$type) {
182
190
  case 'camunda:Properties':
@@ -236,7 +244,8 @@ class FormatActivity {
236
244
  if (timeCycles) {
237
245
  for (const cycle of timeCycles) {
238
246
  const cron = elementApi.resolveExpression(cycle);
239
- if (!cron) continue;
247
+ if (!cron || iso8601cycle.test(cron)) continue;
248
+
240
249
  const expireAtDt = cronParser.parseExpression(cron).next().toDate();
241
250
  if (!expireAt || expireAtDt < expireAt) expireAt = expireAtDt;
242
251
  }
@@ -244,7 +253,7 @@ class FormatActivity {
244
253
 
245
254
  return {
246
255
  resultVariable: this.resultVariable,
247
- ...(scheduledStart && activity.parent.type === 'bpmn:Process' ? {scheduledStart} : undefined),
256
+ ...(scheduledStart && activity.parent.type === 'bpmn:Process' && {scheduledStart}),
248
257
  ...(user?.length && {candidateUsers: user}),
249
258
  ...(groups?.length && {candidateGroups: groups}),
250
259
  ...(!elementApi.content.description && description && {description: elementApi.resolveExpression(description)}),
@@ -267,7 +276,6 @@ class FormatProcess {
267
276
  candidateStarterGroups,
268
277
  } = bp.behaviour;
269
278
 
270
-
271
279
  if (candidateStarterUsers) user = resolveAndSplit(elementApi, candidateStarterUsers);
272
280
  if (candidateStarterGroups) groups = resolveAndSplit(elementApi, candidateStarterGroups);
273
281
  if (documentation) description = documentation[0]?.text;
@@ -323,8 +331,8 @@ function registerIOScripts(parentId, context, type, ioBehaviour) {
323
331
  context.addScript(filename, {
324
332
  id: filename,
325
333
  scriptFormat: definition.scriptFormat,
326
- ...(definition.value ? {body: definition.value}: undefined),
327
- ...(definition.resource ? {resource: definition.resource}: undefined),
334
+ ...(definition.value && {body: definition.value}),
335
+ ...(definition.resource && {resource: definition.resource}),
328
336
  });
329
337
  }
330
338
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onify/flow-extensions",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Onify Flow extensions",
5
5
  "module": "index.js",
6
6
  "main": "dist/index.js",
@@ -35,26 +35,26 @@
35
35
  "license": "MIT",
36
36
  "devDependencies": {
37
37
  "@aircall/expression-parser": "^1.0.4",
38
- "@babel/cli": "^7.17.10",
39
- "@babel/core": "^7.18.5",
40
- "@babel/preset-env": "^7.18.2",
41
- "@babel/register": "^7.17.7",
42
- "bpmn-elements": "^8.0.1",
43
- "bpmn-engine": "^14.0.0",
44
- "bpmn-moddle": "^7.1.2",
45
- "c8": "^7.11.3",
46
- "camunda-bpmn-moddle": "^6.1.2",
47
- "chai": "^4.3.6",
38
+ "@babel/cli": "^7.19.3",
39
+ "@babel/core": "^7.20.2",
40
+ "@babel/preset-env": "^7.20.2",
41
+ "@babel/register": "^7.18.9",
42
+ "bpmn-elements-8-1": "npm:bpmn-elements@8.1",
43
+ "bpmn-engine": "^15.1.0",
44
+ "bpmn-engine-14": "npm:bpmn-engine@14",
45
+ "bpmn-moddle": "^7.1.3",
46
+ "c8": "^7.12.0",
47
+ "camunda-bpmn-moddle": "^7.0.1",
48
+ "chai": "^4.3.7",
48
49
  "chronokinesis": "^3.1.2",
49
50
  "debug": "^4.3.4",
50
- "eslint": "^7.32.0",
51
- "mocha": "^10.0.0",
51
+ "eslint": "^8.27.0",
52
+ "mocha": "^10.1.0",
52
53
  "mocha-cakes-2": "^3.3.0",
53
- "moddle-context-serializer": "^2.1.0",
54
- "nock": "^13.2.6"
54
+ "moddle-context-serializer": "^2.1.0"
55
55
  },
56
56
  "dependencies": {
57
- "cron-parser": "^4.4.0"
57
+ "cron-parser": "^4.6.0"
58
58
  },
59
59
  "files": [
60
60
  "src",
package/src/IO.js CHANGED
@@ -51,8 +51,8 @@ class InputOutput {
51
51
  type: parm.$type,
52
52
  behaviour: {
53
53
  scriptFormat,
54
- ...(value ? {script: value} : undefined),
55
- ...(resource ? {resource} : undefined),
54
+ ...(value && {script: value}),
55
+ ...(resource && {resource}),
56
56
  },
57
57
  });
58
58
 
package/CHANGELOG.md DELETED
@@ -1,17 +0,0 @@
1
- Changelog
2
- =========
3
-
4
- # 1.0.0
5
-
6
- - proper routing keys for end formatting
7
-
8
- # 0.1.0
9
-
10
- - catch errors when resolving service expression
11
- - test with bpmn-engine@14
12
-
13
- # 0.0.2
14
-
15
- - allow expressions in timeCycle
16
- - test with bpmn-engine@13
17
- - error message changed in node 16