@onify/flow-extensions 3.0.0 → 4.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 CHANGED
@@ -1,6 +1,13 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ # 4.0.0
5
+
6
+ - make sure sub-process extensions are only triggered once. Sub process activities unintentionally trigger formatting since events bubble
7
+ - add script element type to registered scripts
8
+ - restructure and split up index.js to separate files
9
+ - abide to new lint rules
10
+
4
11
  # 3.0.0
5
12
 
6
13
  - Support activity script and expression execution listeners
package/dist/index.js CHANGED
@@ -5,421 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.extendFn = extendFn;
7
7
  exports.extensions = extensions;
8
- var _cronParser = _interopRequireDefault(require("cron-parser"));
9
- var _IOProperties = _interopRequireDefault(require("./src/IOProperties.js"));
10
- var _IOForm = _interopRequireDefault(require("./src/IOForm.js"));
11
- var _Connector = _interopRequireDefault(require("./src/Connector.js"));
12
- var _ServiceExpression = _interopRequireDefault(require("./src/ServiceExpression.js"));
13
- var _IO = require("./src/IO.js");
14
- var _ExecutionListeners = _interopRequireDefault(require("./src/ExecutionListeners.js"));
15
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
- const iso8601cycle = /^\s*(R\d+\/)?P\w+/i;
17
- class FormatError extends Error {
18
- constructor(elementId, err) {
19
- super(`<${elementId}> ${err.message}`);
20
- this.code = 'EFLOW_FORMAT';
21
- this.output = {
22
- statusCode: 500
23
- };
24
- }
25
- }
8
+ var _OnifyProcessExtensions = require("./src/OnifyProcessExtensions.js");
9
+ var _OnifyElementExtensions = require("./src/OnifyElementExtensions.js");
26
10
  function extensions(element, context) {
27
- if (element.type === 'bpmn:Process') return new OnifyProcessExtensions(element, context);
28
- return new OnifyElementExtensions(element, context);
29
- }
30
- class OnifyProcessExtensions {
31
- constructor(bp, context) {
32
- this.process = bp;
33
- this.context = context;
34
- this.extensions = getExtensions(bp, context);
35
- this._activate();
36
- }
37
- _activate() {
38
- const bp = this.process;
39
- bp.on('process.enter', elementApi => {
40
- try {
41
- const result = this._onEnter(elementApi);
42
- const environment = elementApi.environment;
43
- environment.assignVariables(result);
44
- } catch (err) {
45
- elementApi.broker.publish('event', 'process.error', {
46
- ...elementApi.content,
47
- error: new FormatError(bp.id, err)
48
- }, {
49
- mandatory: true,
50
- type: 'error'
51
- });
52
- }
53
- }, {
54
- consumerTag: '_onify-extension-on-enter'
55
- });
56
- }
57
- _onEnter(elementApi) {
58
- const {
59
- format,
60
- properties
61
- } = this.extensions;
62
- const result = {};
63
- Object.assign(result, format.resolve(elementApi));
64
- Object.assign(elementApi.content, result);
65
- if (properties) {
66
- Object.assign(result, properties.resolve(elementApi));
67
- Object.assign(elementApi.content, result);
68
- }
69
- return result;
70
- }
71
- }
72
- class OnifyElementExtensions {
73
- constructor(activity, context) {
74
- this.activity = activity;
75
- this.context = context;
76
- const {
77
- Service
78
- } = this.extensions = getExtensions(activity, context);
79
- if (Service) {
80
- activity.behaviour.Service = Service;
81
- }
82
- }
83
- activate(message) {
84
- const activity = this.activity;
85
- const broker = activity.broker;
86
- const formatQ = activity.broker.getQueue('format-run-q');
87
- if (message.fields.redelivered && message.fields.routingKey === 'run.start') {
88
- activity.on('start', elementApi => {
89
- this._formatOnEnter(broker, formatQ, elementApi);
90
- }, {
91
- consumerTag: '_onify-extension-on-enter'
92
- });
93
- } else {
94
- activity.on('enter', elementApi => {
95
- this._formatOnEnter(broker, formatQ, elementApi);
96
- }, {
97
- consumerTag: '_onify-extension-on-enter'
98
- });
99
- }
100
- activity.on('activity.execution.completed', async elementApi => {
101
- formatQ.queueMessage({
102
- routingKey: 'run.end.format'
103
- }, {
104
- endRoutingKey: 'run.end.complete'
105
- }, {
106
- persistent: false
107
- });
108
- try {
109
- var format = await this._onExecuted(elementApi);
110
- } catch (err) {
111
- return broker.publish('format', 'run.end.error', {
112
- error: err
113
- }, {
114
- persistent: false
115
- });
116
- }
117
- broker.publish('format', 'run.end.complete', {
118
- ...format
119
- }, {
120
- persistent: false
121
- });
122
- }, {
123
- consumerTag: '_onify-extension-on-executed'
124
- });
125
- const executionListeners = this.extensions.listeners;
126
- if (executionListeners !== null && executionListeners !== void 0 && executionListeners.onStart) {
127
- activity.on('start', async elementApi => {
128
- formatQ.queueMessage({
129
- routingKey: 'run.listener.start'
130
- }, {
131
- endRoutingKey: 'run.listener.start.complete'
132
- }, {
133
- persistent: false
134
- });
135
- try {
136
- var format = await executionListeners.execute('start', elementApi);
137
- } catch (err) {
138
- return broker.publish('format', 'run.listener.start.error', {
139
- error: err
140
- }, {
141
- persistent: false
142
- });
143
- }
144
- broker.publish('format', 'run.listener.start.complete', {
145
- ...format
146
- }, {
147
- persistent: false
148
- });
149
- }, {
150
- consumerTag: '_onify-extension-on-listenerstart'
151
- });
152
- }
153
- if (executionListeners !== null && executionListeners !== void 0 && executionListeners.onEnd) {
154
- activity.on('end', async elementApi => {
155
- formatQ.queueMessage({
156
- routingKey: 'run.listener.end'
157
- }, {
158
- endRoutingKey: 'run.listener.end.complete'
159
- }, {
160
- persistent: false
161
- });
162
- try {
163
- var format = await executionListeners.execute('end', elementApi);
164
- } catch (err) {
165
- return broker.publish('format', 'run.listener.end.error', {
166
- error: err
167
- }, {
168
- persistent: false
169
- });
170
- }
171
- broker.publish('format', 'run.listener.end.complete', {
172
- ...format
173
- }, {
174
- persistent: false
175
- });
176
- }, {
177
- consumerTag: '_onify-extension-on-listenerend'
178
- });
179
- }
180
- }
181
- deactivate() {
182
- const broker = this.activity.broker;
183
- broker.cancel('_onify-extension-on-enter');
184
- broker.cancel('_onify-extension-on-executed');
185
- broker.cancel('_onify-extension-on-listenerstart');
186
- broker.cancel('_onify-extension-on-listenerend');
187
- }
188
- async _formatOnEnter(broker, formatQ, elementApi) {
189
- formatQ.queueMessage({
190
- routingKey: 'run.enter.format'
191
- }, {
192
- endRoutingKey: 'run.enter.complete'
193
- }, {
194
- persistent: false
195
- });
196
- try {
197
- var format = await this._onEnter(elementApi);
198
- } catch (err) {
199
- return broker.publish('format', 'run.enter.error', {
200
- error: err
201
- }, {
202
- persistent: false
203
- });
204
- }
205
- broker.publish('format', 'run.enter.complete', format, {
206
- persistent: false
207
- });
208
- }
209
- async _onEnter(elementApi) {
210
- const {
211
- format,
212
- properties,
213
- io,
214
- form
215
- } = this.extensions;
216
- const result = {};
217
- Object.assign(result, format.resolve(elementApi));
218
- Object.assign(elementApi.content, result);
219
- if (properties) {
220
- Object.assign(result, {
221
- properties: properties.resolve(elementApi)
222
- });
223
- Object.assign(elementApi.content, result);
224
- }
225
- if (io) {
226
- var _io$input, _io$output;
227
- if ((_io$input = io.input) !== null && _io$input !== void 0 && _io$input.length) {
228
- const input = await io.getInput(this.activity, elementApi);
229
- Object.assign(result, {
230
- input
231
- });
232
- Object.assign(elementApi.content, result);
233
- }
234
- if ((_io$output = io.output) !== null && _io$output !== void 0 && _io$output.length) {
235
- result.assignToOutput = true;
236
- }
237
- }
238
- if (form) {
239
- Object.assign(result, {
240
- form: form.resolve(elementApi)
241
- });
242
- }
243
- return result;
244
- }
245
- async _onExecuted(elementApi) {
246
- const {
247
- properties,
248
- io
249
- } = this.extensions;
250
- const result = {};
251
- if (io !== null && io !== void 0 && io.output.length) {
252
- const output = await io.getOutput(this.activity, elementApi);
253
- Object.assign(result, {
254
- output
255
- });
256
- Object.assign(elementApi.content, {
257
- output
258
- });
259
- }
260
- if (properties) {
261
- const props = properties.resolve(elementApi);
262
- Object.assign(result, {
263
- properties: props
264
- });
265
- Object.assign(elementApi.content, {
266
- properties: props
267
- });
268
- }
269
- const {
270
- output,
271
- assignToOutput,
272
- resultVariable
273
- } = elementApi.content;
274
- if (output === undefined || output === null) return result;
275
- if (assignToOutput && typeof output === 'object') {
276
- Object.assign(this.activity.environment.output, output);
277
- } else if (resultVariable) {
278
- elementApi.environment.output[resultVariable] = output;
279
- }
280
- return result;
281
- }
282
- }
283
- function getExtensions(element, context) {
284
- var _element$behaviour$ex, _ext$values, _ext$fields;
285
- const result = {
286
- format: element.type === 'bpmn:Process' ? new FormatProcess(element) : new FormatActivity(element)
287
- };
288
- const expression = element.behaviour.expression;
289
- if (expression) result.Service = _ServiceExpression.default;
290
- const extensions = (_element$behaviour$ex = element.behaviour.extensionElements) === null || _element$behaviour$ex === void 0 ? void 0 : _element$behaviour$ex.values;
291
- if (!extensions) return result;
292
- const listeners = new _ExecutionListeners.default(element, context);
293
- let listener = 0;
294
- for (const ext of extensions) {
295
- switch (ext.$type) {
296
- case 'camunda:Properties':
297
- if ((_ext$values = ext.values) !== null && _ext$values !== void 0 && _ext$values.length) result.properties = new _IOProperties.default(element, ext);
298
- break;
299
- case 'camunda:InputOutput':
300
- result.io = new _IO.InputOutput(element.id, ext, context);
301
- break;
302
- case 'camunda:FormData':
303
- if ((_ext$fields = ext.fields) !== null && _ext$fields !== void 0 && _ext$fields.length) result.form = new _IOForm.default(element, ext);
304
- break;
305
- case 'camunda:Connector':
306
- {
307
- const {
308
- connectorId,
309
- inputOutput
310
- } = ext;
311
- const io = inputOutput && new _IO.InputOutput(`${element.id}/${ext.$type.toLowerCase()}`, inputOutput, context);
312
- result.Service = _Connector.default.bind(_Connector.default, connectorId, io);
313
- break;
314
- }
315
- case 'camunda:ExecutionListener':
316
- listeners.add(ext, listener++);
317
- break;
318
- }
319
- }
320
- if (listeners.length) result.listeners = listeners;
321
- return result;
322
- }
323
- class FormatActivity {
324
- constructor(activity) {
325
- this.activity = activity;
326
- this.resultVariable = activity.behaviour.resultVariable;
327
- let timeCycles;
328
- if (activity.eventDefinitions) {
329
- for (const ed of activity.eventDefinitions.filter(e => e.type === 'bpmn:TimerEventDefinition')) {
330
- if (!('timeCycle' in ed)) continue;
331
- timeCycles = timeCycles || [];
332
- timeCycles.push(ed.timeCycle);
333
- }
334
- }
335
- this.timeCycles = timeCycles;
336
- }
337
- resolve(elementApi) {
338
- var _documentation$, _user, _groups;
339
- let user, groups, assigneeValue, description;
340
- const activity = this.activity;
341
- const {
342
- documentation,
343
- candidateUsers,
344
- candidateGroups,
345
- scheduledStart,
346
- assignee
347
- } = activity.behaviour;
348
- if (candidateUsers) user = resolveAndSplit(elementApi, candidateUsers);
349
- if (candidateGroups) groups = resolveAndSplit(elementApi, candidateGroups);
350
- if (assignee) assigneeValue = elementApi.resolveExpression(assignee);
351
- if (documentation) description = (_documentation$ = documentation[0]) === null || _documentation$ === void 0 ? void 0 : _documentation$.text;
352
- let expireAt;
353
- let timeCycles = this.timeCycles;
354
- if (timeCycles) {
355
- for (const cycle of timeCycles) {
356
- const cron = elementApi.resolveExpression(cycle);
357
- if (!cron || iso8601cycle.test(cron)) continue;
358
- const expireAtDt = _cronParser.default.parseExpression(cron).next().toDate();
359
- if (!expireAt || expireAtDt < expireAt) expireAt = expireAtDt;
360
- }
361
- }
362
- return {
363
- ...(this.resultVariable && {
364
- resultVariable: this.resultVariable
365
- }),
366
- ...(scheduledStart && activity.parent.type === 'bpmn:Process' && {
367
- scheduledStart
368
- }),
369
- ...(((_user = user) === null || _user === void 0 ? void 0 : _user.length) && {
370
- candidateUsers: user
371
- }),
372
- ...(((_groups = groups) === null || _groups === void 0 ? void 0 : _groups.length) && {
373
- candidateGroups: groups
374
- }),
375
- ...(!elementApi.content.description && description && {
376
- description: elementApi.resolveExpression(description)
377
- }),
378
- ...(expireAt && {
379
- expireAt
380
- }),
381
- ...(assigneeValue && {
382
- assignee: assigneeValue
383
- })
384
- };
385
- }
386
- }
387
- class FormatProcess {
388
- constructor(bp) {
389
- this.process = bp;
390
- }
391
- resolve(elementApi) {
392
- var _documentation$2, _user2, _groups2;
393
- let user, groups, description;
394
- const bp = this.process;
395
- const {
396
- documentation,
397
- candidateStarterUsers,
398
- candidateStarterGroups
399
- } = bp.behaviour;
400
- if (candidateStarterUsers) user = resolveAndSplit(elementApi, candidateStarterUsers);
401
- if (candidateStarterGroups) groups = resolveAndSplit(elementApi, candidateStarterGroups);
402
- if (documentation) description = (_documentation$2 = documentation[0]) === null || _documentation$2 === void 0 ? void 0 : _documentation$2.text;
403
- return {
404
- ...(((_user2 = user) === null || _user2 === void 0 ? void 0 : _user2.length) && {
405
- candidateStarterUsers: user
406
- }),
407
- ...(((_groups2 = groups) === null || _groups2 === void 0 ? void 0 : _groups2.length) && {
408
- candidateStarterGroups: groups
409
- }),
410
- ...(!elementApi.content.description && description && {
411
- description: elementApi.resolveExpression(description)
412
- })
413
- };
414
- }
415
- }
416
- function resolveAndSplit(elementApi, str) {
417
- if (Array.isArray(str)) return str.filter(Boolean);
418
- if (typeof str !== 'string') return;
419
- const resolved = elementApi.resolveExpression(str);
420
- if (Array.isArray(resolved)) return resolved.filter(Boolean);
421
- if (typeof resolved !== 'string') return;
422
- return resolved.split(',').map(g => g.trim && g.trim().toLowerCase()).filter(Boolean);
11
+ if (element.type === 'bpmn:Process') return new _OnifyProcessExtensions.OnifyProcessExtensions(element, context);
12
+ return new _OnifyElementExtensions.OnifyElementExtensions(element, context);
423
13
  }
424
14
  function extendFn(behaviour, context) {
425
15
  var _behaviour$extensionE;
@@ -461,10 +51,12 @@ function registerIOScripts(parentId, context, type, ioBehaviour) {
461
51
  } of inputParameters.concat(outputParameters)) {
462
52
  if (!definition) continue;
463
53
  if (definition.$type !== 'camunda:Script') continue;
464
- const filename = `${parentId}/${type}/${$type}/${name}`;
54
+ const ioType = `${type}/${$type}`;
55
+ const filename = `${parentId}/${ioType}/${name}`;
465
56
  context.addScript(filename, {
466
57
  id: filename,
467
58
  scriptFormat: definition.scriptFormat,
59
+ type: ioType,
468
60
  ...(definition.value && {
469
61
  body: definition.value
470
62
  }),
@@ -484,6 +76,7 @@ function registerListenerScript(parentId, context, type, listener, pos) {
484
76
  context.addScript(id, {
485
77
  id,
486
78
  scriptFormat: script.scriptFormat,
79
+ type,
487
80
  ...(script.value && {
488
81
  body: script.value
489
82
  }),
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = Connector;
7
- var _Errors = require("./Errors");
7
+ var _Errors = require("./Errors.js");
8
8
  function Connector(connectorId, io, activity, executionMessage) {
9
9
  if (!(this instanceof Connector)) return new Connector(connectorId, io, activity, executionMessage);
10
10
  this.connectorId = connectorId;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.NotImplemented = void 0;
6
+ exports.NotImplemented = exports.FormatError = void 0;
7
7
  class NotImplemented extends Error {
8
8
  constructor(serviceId) {
9
9
  super(`${serviceId} service function not found`);
@@ -13,4 +13,14 @@ class NotImplemented extends Error {
13
13
  };
14
14
  }
15
15
  }
16
- exports.NotImplemented = NotImplemented;
16
+ exports.NotImplemented = NotImplemented;
17
+ class FormatError extends Error {
18
+ constructor(elementId, err) {
19
+ super(`<${elementId}> ${err.message}`);
20
+ this.code = 'EFLOW_FORMAT';
21
+ this.output = {
22
+ statusCode: 500
23
+ };
24
+ }
25
+ }
26
+ exports.FormatError = FormatError;
package/dist/src/IO.js CHANGED
@@ -3,80 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.InputOutput = exports.IOScript = exports.IOMap = exports.IOList = exports.IOBase = void 0;
7
- class InputOutput {
8
- constructor(parentId, behaviour, context) {
9
- this.parentId = parentId;
10
- this.context = context;
11
- const {
12
- inputParameters,
13
- outputParameters
14
- } = behaviour;
15
- this.input = this._map(parentId, inputParameters, 'input', context);
16
- this.output = this._map(parentId, outputParameters, 'output', context);
17
- }
18
- async getInput(activity, executionMessage) {
19
- const input = this.input;
20
- const values = await Promise.all(input.map(parm => parm.getValue(activity, executionMessage)));
21
- return values.reduce((result, parm) => Object.assign(result, parm), {});
22
- }
23
- async getOutput(activity, executionMessage) {
24
- const output = this.output;
25
- const values = await Promise.all(output.map(parm => parm.getValue(activity, executionMessage)));
26
- return values.reduce((result, parm) => Object.assign(result, parm), {});
27
- }
28
- _map(parentId, list, ioType, context) {
29
- const mapped = [];
30
- if (!list) return mapped;
31
- for (const parm of list) {
32
- const definition = parm.definition;
33
- const type = definition && definition.$type;
34
- switch (type) {
35
- case 'camunda:Map':
36
- {
37
- mapped.push(new IOMap(parm));
38
- break;
39
- }
40
- case 'camunda:List':
41
- {
42
- mapped.push(new IOList(parm));
43
- break;
44
- }
45
- case 'camunda:Script':
46
- {
47
- const id = `${parentId}/${ioType}/${type}/${parm.name}`;
48
- const {
49
- scriptFormat,
50
- value,
51
- resource
52
- } = definition;
53
- if (!value && !resource) break;
54
- context.environment.scripts.register({
55
- id,
56
- type: parm.$type,
57
- behaviour: {
58
- scriptFormat,
59
- ...(value && {
60
- script: value
61
- }),
62
- ...(resource && {
63
- resource
64
- })
65
- }
66
- });
67
- mapped.push(new IOScript(parm, id));
68
- break;
69
- }
70
- default:
71
- {
72
- mapped.push(new IOBase(parm));
73
- }
74
- }
75
- }
76
- return mapped;
77
- }
78
- }
79
- exports.InputOutput = InputOutput;
6
+ exports.InputOutput = exports.IOScript = exports.IOList = exports.IOBase = void 0;
80
7
  class IOBase {
81
8
  constructor(parm) {
82
9
  this.name = parm.name;
@@ -127,7 +54,6 @@ class IOMap extends IOBase {
127
54
  };
128
55
  }
129
56
  }
130
- exports.IOMap = IOMap;
131
57
  class IOList extends IOBase {
132
58
  constructor(parm) {
133
59
  super(parm);
@@ -194,4 +120,77 @@ class IOScript extends IOBase {
194
120
  }
195
121
  }
196
122
  }
197
- exports.IOScript = IOScript;
123
+ exports.IOScript = IOScript;
124
+ class InputOutput {
125
+ constructor(parentId, behaviour, context) {
126
+ this.parentId = parentId;
127
+ this.context = context;
128
+ const {
129
+ inputParameters,
130
+ outputParameters
131
+ } = behaviour;
132
+ this.input = this._map(parentId, inputParameters, 'input', context);
133
+ this.output = this._map(parentId, outputParameters, 'output', context);
134
+ }
135
+ async getInput(activity, executionMessage) {
136
+ const input = this.input;
137
+ const values = await Promise.all(input.map(parm => parm.getValue(activity, executionMessage)));
138
+ return values.reduce((result, parm) => Object.assign(result, parm), {});
139
+ }
140
+ async getOutput(activity, executionMessage) {
141
+ const output = this.output;
142
+ const values = await Promise.all(output.map(parm => parm.getValue(activity, executionMessage)));
143
+ return values.reduce((result, parm) => Object.assign(result, parm), {});
144
+ }
145
+ _map(parentId, list, ioType, context) {
146
+ const mapped = [];
147
+ if (!list) return mapped;
148
+ for (const parm of list) {
149
+ const definition = parm.definition;
150
+ const type = definition && definition.$type;
151
+ switch (type) {
152
+ case 'camunda:Map':
153
+ {
154
+ mapped.push(new IOMap(parm));
155
+ break;
156
+ }
157
+ case 'camunda:List':
158
+ {
159
+ mapped.push(new IOList(parm));
160
+ break;
161
+ }
162
+ case 'camunda:Script':
163
+ {
164
+ const id = `${parentId}/${ioType}/${type}/${parm.name}`;
165
+ const {
166
+ scriptFormat,
167
+ value,
168
+ resource
169
+ } = definition;
170
+ if (!value && !resource) break;
171
+ context.environment.scripts.register({
172
+ id,
173
+ type: parm.$type,
174
+ behaviour: {
175
+ scriptFormat,
176
+ ...(value && {
177
+ script: value
178
+ }),
179
+ ...(resource && {
180
+ resource
181
+ })
182
+ }
183
+ });
184
+ mapped.push(new IOScript(parm, id));
185
+ break;
186
+ }
187
+ default:
188
+ {
189
+ mapped.push(new IOBase(parm));
190
+ }
191
+ }
192
+ }
193
+ return mapped;
194
+ }
195
+ }
196
+ exports.InputOutput = InputOutput;