@camunda/linting 3.24.0 → 3.25.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.
@@ -1,655 +1,671 @@
1
- import {
2
- isArray,
3
- isString
4
- } from 'min-dash';
5
-
6
- import { is } from 'bpmnlint-utils';
7
-
8
- import { ERROR_TYPES } from 'bpmnlint-plugin-camunda-compat/rules/utils/error-types';
9
-
10
- import { greaterOrEqual } from './version';
11
-
12
- const TIMER_PROPERTIES = [
13
- 'timeDate',
14
- 'timeDuration',
15
- 'timeCycle'
16
- ];
17
-
18
- /**
19
- * Get errors for a given element.
20
- *
21
- * @param {Object[]} reports
22
- * @param {Object} element
23
- *
24
- * @returns {Object}
25
- */
26
- export function getErrors(reports, element) {
27
- return reports.reduce((errors, report) => {
28
- const { category } = report;
29
-
30
- if (!element
31
- || getBusinessObject(element).get('id') !== report.id
32
- || category !== 'error') {
33
- return errors;
34
- }
35
-
36
- const ids = getEntryIds(report);
37
-
38
- if (!ids.length) {
39
- return errors;
40
- }
41
-
42
- let { message } = report;
43
-
44
- return {
45
- ...errors,
46
- ...ids.reduce((errors, id) => {
47
- return {
48
- ...errors,
49
- [ id ]: getErrorMessage(id, report) || message
50
- };
51
- }, {})
52
- };
53
- }, {});
54
- }
55
-
56
- export function getEntryIds(report) {
57
- const {
58
- data = {},
59
- id,
60
- path,
61
- propertiesPanel = {}
62
- } = report;
63
-
64
- if (propertiesPanel.entryIds) {
65
- return propertiesPanel.entryIds;
66
- }
67
-
68
- if (isPropertyError(data, 'isExecutable')) {
69
- return [ 'isExecutable' ];
70
- }
71
-
72
- if (isExtensionElementRequiredError(data, 'zeebe:CalledDecision', 'bpmn:BusinessRuleTask')) {
73
- return [ 'businessRuleImplementation' ];
74
- }
75
-
76
- // script task
77
- if (isExtensionElementRequiredError(data, 'zeebe:Script', 'bpmn:ScriptTask')) {
78
- return [ 'scriptImplementation' ];
79
- }
80
-
81
- if (isPropertyError(data, 'errorRef')) {
82
- return [ 'errorRef' ];
83
- }
84
-
85
- if (isPropertyError(data, 'escalationRef')) {
86
- return [ 'escalationRef' ];
87
- }
88
-
89
- if (isPropertyError(data, 'messageRef')) {
90
- return [ 'messageRef' ];
91
- }
92
-
93
- if (isPropertyError(data, 'signalRef')) {
94
- return [ 'signalRef' ];
95
- }
96
-
97
- if (isPropertyError(data, 'historyTimeToLive')) {
98
- return [ 'historyTimeToLive' ];
99
- }
100
-
101
- if (isPropertyError(data, 'decisionId', 'zeebe:CalledDecision')) {
102
- return [ 'decisionId' ];
103
- }
104
-
105
- if (isPropertyError(data, 'resultVariable')) {
106
- return [ 'resultVariable' ];
107
- }
108
-
109
- if (isPropertyError(data, 'expression', 'zeebe:Script')) {
110
- return [ 'scriptExpression' ];
111
- }
112
-
113
- if (isPropertyError(data, 'errorCode', 'bpmn:Error')) {
114
- return [ 'errorCode' ];
115
- }
116
-
117
- if (isPropertyError(data, 'escalationCode', 'bpmn:Escalation')) {
118
- return [ 'escalationCode' ];
119
- }
120
-
121
- if (isPropertyError(data, 'name', 'bpmn:Message')) {
122
- return [ 'messageName' ];
123
- }
124
-
125
- if (isPropertyError(data, 'name', 'bpmn:Signal')) {
126
- return [ 'signalName' ];
127
- }
128
-
129
- if (isExtensionElementRequiredError(data, 'zeebe:LoopCharacteristics', 'bpmn:MultiInstanceLoopCharacteristics')
130
- || isPropertyError(data, 'inputCollection', 'zeebe:LoopCharacteristics')) {
131
- return [ 'multiInstance-inputCollection' ];
132
- }
133
-
134
- if (isPropertyDependentRequiredError(data, 'outputCollection', 'zeebe:LoopCharacteristics')) {
135
- return [ 'multiInstance-outputCollection' ];
136
- }
137
-
138
- if (isPropertyDependentRequiredError(data, 'outputElement', 'zeebe:LoopCharacteristics')) {
139
- return [ 'multiInstance-outputElement' ];
140
- }
141
-
142
- if (isExtensionElementRequiredError(data, 'zeebe:CalledElement', 'bpmn:CallActivity')
143
- || isPropertyError(data, 'processId', 'zeebe:CalledElement')) {
144
- return [ 'targetProcessId' ];
145
- }
146
-
147
- if (isExtensionElementRequiredError(data, 'zeebe:TaskDefinition')
148
- || isPropertyError(data, 'type', 'zeebe:TaskDefinition')) {
149
- return [ 'taskDefinitionType' ];
150
- }
151
-
152
- if (isPropertyError(data, 'retries', 'zeebe:TaskDefinition')) {
153
- return [ 'taskDefinitionRetries' ];
154
- }
155
-
156
- if (isExtensionElementRequiredError(data, 'zeebe:Subscription')
157
- || isPropertyError(data, 'correlationKey', 'zeebe:Subscription')) {
158
- return [ 'messageSubscriptionCorrelationKey' ];
159
- }
160
-
161
- if (isPropertyError(data, 'formKey', 'zeebe:FormDefinition')) {
162
- return [ 'customFormKey' ];
163
- }
164
-
165
- if (isType(data, 'zeebe:FormDefinition')) {
166
- const {
167
- node,
168
- requiredProperty
169
- } = data;
170
-
171
- if (isArray(requiredProperty)) {
172
- if (requiredProperty.includes('formKey') && isEmptyString(node.get('formKey'))) {
173
- return [ 'customFormKey' ];
174
- } else if (requiredProperty.includes('formId') && isEmptyString(node.get('formId'))) {
175
- return [ 'formId' ];
176
- } else if (requiredProperty.includes('externalReference') && isEmptyString(node.get('externalReference'))) {
177
- return [ 'externalReference' ];
178
- }
179
- }
180
- }
181
-
182
- if (isPropertyError(data, 'formId', 'zeebe:FormDefinition')) {
183
- return [ 'formId' ];
184
- }
185
-
186
- if (isPropertyError(data, 'body', 'zeebe:UserTaskForm')) {
187
- return [ 'formConfiguration' ];
188
- }
189
-
190
- if (isPropertyValueDuplicatedError(data, 'values', 'key', 'zeebe:TaskHeaders')) {
191
- const {
192
- node,
193
- properties,
194
- propertiesName
195
- } = data;
196
-
197
- return properties.map(property => {
198
- const index = node.get(propertiesName).indexOf(property);
199
-
200
- return `${ id }-header-${ index }-key`;
201
- });
202
- }
203
-
204
- if (isExtensionElementNotAllowedError(data, 'zeebe:Properties')) {
205
- const { extensionElement } = data;
206
-
207
- return extensionElement.get('zeebe:properties').map((zeebeProperty, index) => {
208
- return `${ id }-extensionProperty-${ index }-name`;
209
- });
210
- }
211
-
212
- if (isExtensionElementNotAllowedError(data, 'zeebe:UserTask')) {
213
- return [ 'userTaskImplementation' ];
214
- }
215
-
216
- if (isExtensionElementNotAllowedError(data, 'zeebe:FormDefinition', 'bpmn:StartEvent')) {
217
- return [ 'formType' ];
218
- }
219
-
220
-
221
- if (isPropertyError(data, 'conditionExpression', 'bpmn:SequenceFlow')) {
222
- return [ 'conditionExpression' ];
223
- }
224
-
225
- if (isPropertyError(data, 'completionCondition', 'bpmn:MultiInstanceLoopCharacteristics')) {
226
- return [ 'multiInstance-completionCondition' ];
227
- }
228
-
229
- if (TIMER_PROPERTIES.some(property =>
230
- isOneOfPropertiesRequiredError(data, property, 'bpmn:TimerEventDefinition'))
231
- ) {
232
- return [ 'timerEventDefinitionType' ];
233
- }
234
-
235
- if (isExpressionRequiredError(data, 'timeCycle', 'bpmn:FormalExpression')
236
- || isExpressionRequiredError(data, 'timeDate', 'bpmn:FormalExpression')
237
- || isExpressionRequiredError(data, 'timeDuration', 'bpmn:FormalExpression')) {
238
- return [ 'timerEventDefinitionValue' ];
239
- }
240
-
241
- if (isExpressionValueNotAllowedError(data, 'timeCycle', 'bpmn:FormalExpression')
242
- || isExpressionValueNotAllowedError(data, 'timeDate', 'bpmn:FormalExpression')
243
- || isExpressionValueNotAllowedError(data, 'timeDuration', 'bpmn:FormalExpression')) {
244
- return [ 'timerEventDefinitionValue' ];
245
- }
246
-
247
- if (isPropertyError(data, 'timeCycle', 'bpmn:TimerEventDefinition')
248
- || isPropertyError(data, 'timeDate', 'bpmn:TimerEventDefinition')
249
- || isPropertyError(data, 'timeDuration', 'bpmn:TimerEventDefinition')) {
250
- return [ 'timerEventDefinitionType' ];
251
- }
252
-
253
- const LIST_PROPERTIES = [
254
- [ 'zeebe:Input', 'input' ],
255
- [ 'zeebe:Output', 'output' ],
256
- [ 'zeebe:Property', 'extensionProperty' ],
257
- [ 'zeebe:Header', 'header' ]
258
- ];
259
-
260
- for (const [ type, prefix ] of LIST_PROPERTIES) {
261
- if (isType(data, type)
262
- && getPropertyName(data)) {
263
-
264
- const index = path[ path.length - 2 ];
265
-
266
- return [ `${ id }-${ prefix }-${ index }-${ getPropertyName(data) }` ];
267
- }
268
- }
269
-
270
- if (isType(data, 'zeebe:LoopCharacteristics')) {
271
- return [ `multiInstance-${getPropertyName(data)}` ];
272
- }
273
-
274
- if (isPropertyError(data, 'candidateUsers', 'zeebe:AssignmentDefinition')) {
275
- return [ 'assignmentDefinitionCandidateUsers' ];
276
- }
277
-
278
- if (isPropertyError(data, 'historyTimeToLive', 'bpmn:Process')) {
279
- return [ 'historyTimeToLive' ];
280
- }
281
-
282
- if (isExpressionValueNotAllowedError(data, 'dueDate', 'zeebe:TaskSchedule')) {
283
- return [ 'taskScheduleDueDate' ];
284
- }
285
-
286
- if (isExpressionValueNotAllowedError(data, 'followUpDate', 'zeebe:TaskSchedule')) {
287
- return [ 'taskScheduleFollowUpDate' ];
288
- }
289
-
290
- if (isExtensionElementNotAllowedError(data, 'zeebe:TaskSchedule', 'bpmn:UserTask')) {
291
- const { extensionElement: taskSchedule } = data;
292
-
293
- let ids = [];
294
-
295
- if (taskSchedule.get('dueDate')) {
296
- ids = [ ...ids, 'taskScheduleDueDate' ];
297
- }
298
-
299
- if (taskSchedule.get('followUpDate')) {
300
- ids = [ ...ids, 'taskScheduleFollowUpDate' ];
301
- }
302
-
303
- return ids;
304
- }
305
-
306
- if (isPropertyError(data, 'propagateAllParentVariables', 'zeebe:CalledElement')) {
307
- return [ 'propagateAllParentVariables' ];
308
- }
309
-
310
- if (isPropertyError(data, 'name', 'bpmn:LinkEventDefinition')
311
- || isElementPropertyValueDuplicated(data, 'name', 'bpmn:LinkEventDefinition')) {
312
- return [ 'linkName' ];
313
- }
314
-
315
- if (isPropertyError(data, 'waitForCompletion', 'bpmn:CompensateEventDefinition')) {
316
- return [ 'waitForCompletion' ];
317
- }
318
-
319
- if (isPropertyError(data, 'type', 'zeebe:ExecutionListener')) {
320
- const index = path[ path.length - 2 ];
321
-
322
- return [ `${id}-executionListener-${index}-listenerType` ];
323
- }
324
-
325
- if (isPropertyValuesDuplicatedError(data, 'zeebe:ExecutionListeners')) {
326
- const { properties, propertiesName } = data;
327
-
328
- return properties.map(property => {
329
- const index = data.node.get(propertiesName).indexOf(property);
330
-
331
- return `${ id }-executionListener-${ index }-listenerType`;
332
- });
333
- }
334
-
335
- if (isPropertyError(data, 'bindingType')) {
336
- return [ 'bindingType' ];
337
- }
338
-
339
- return [];
340
- }
341
-
342
- export function getErrorMessage(id, report) {
343
- const {
344
- data = {},
345
- executionPlatformVersion
346
- } = report;
347
-
348
- const {
349
- type,
350
- allowedVersion
351
- } = data;
352
-
353
- // adjust FEEL message
354
- if (type === ERROR_TYPES.FEEL_EXPRESSION_INVALID) {
355
- return 'Unparsable FEEL expression.';
356
- }
357
-
358
- if (type === ERROR_TYPES.EXPRESSION_NOT_ALLOWED) {
359
- return 'Cannot be an expression.';
360
- }
361
-
362
- if (id === 'isExecutable') {
363
- const { parentNode } = data;
364
-
365
- if (parentNode && is(parentNode, 'bpmn:Participant')) {
366
- return 'One process must be executable.';
367
- } else {
368
- return 'Process must be executable.';
369
- }
370
- }
371
-
372
- if ([ 'businessRuleImplementation', 'scriptImplementation' ].includes(id)) {
373
- return 'Implementation must be defined.';
374
- }
375
-
376
- if (id === 'errorRef') {
377
- return 'Global error reference must be defined.';
378
- }
379
-
380
- if (id === 'escalationRef') {
381
- return 'Global escalation reference must be defined.';
382
- }
383
-
384
- if (id === 'messageRef') {
385
- return 'Global message reference must be defined.';
386
- }
387
-
388
- if (id === 'signalRef') {
389
- return 'Global signal reference must be defined.';
390
- }
391
-
392
- if (id === 'decisionId') {
393
- return 'Decision ID must be defined.';
394
- }
395
-
396
- if (id === 'scriptExpression') {
397
- return 'FEEL expression must be defined.';
398
- }
399
-
400
- if (id === 'resultVariable') {
401
- return 'Result variable must be defined.';
402
- }
403
-
404
- if (id === 'errorCode' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
405
- return 'Code must be defined.';
406
- }
407
-
408
- if (id === 'escalationCode' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
409
- return 'Code must be defined.';
410
- }
411
-
412
- if (id === 'messageName') {
413
- return 'Name must be defined.';
414
- }
415
-
416
- if (id === 'signalName') {
417
- return 'Name must be defined.';
418
- }
419
-
420
- if (id === 'multiInstance-inputCollection') {
421
- return 'Input collection must be defined.';
422
- }
423
-
424
- if (id === 'multiInstance-outputCollection') {
425
- return 'Output collection must be defined.';
426
- }
427
-
428
- if (id === 'multiInstance-outputElement') {
429
- return 'Output element must be defined.';
430
- }
431
-
432
- if (id === 'targetProcessId') {
433
- return 'Process ID must be defined.';
434
- }
435
-
436
- if (id === 'taskDefinitionType') {
437
- return 'Type must be defined.';
438
- }
439
-
440
- if (id === 'timerEventDefinitionType' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
441
- return 'Type must be defined.';
442
- }
443
-
444
- if (id === 'messageSubscriptionCorrelationKey'
445
- && [
446
- ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
447
- ERROR_TYPES.PROPERTY_REQUIRED
448
- ].includes(type)) {
449
- return 'Subscription correlation key must be defined.';
450
- }
451
-
452
- if (id === 'customFormKey') {
453
- return 'Form key must be defined.';
454
- }
455
-
456
- if (id === 'formId') {
457
- if (type === ERROR_TYPES.PROPERTY_REQUIRED) {
458
- return 'Form ID must be defined.';
459
- } else if (type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
460
- return getNotSupportedMessage('Form ID', allowedVersion);
461
- }
462
- }
463
-
464
- if (id === 'externalReference') {
465
- return 'External reference must be defined.';
466
- }
467
-
468
- if (id === 'formConfiguration') {
469
- return 'Form JSON configuration must be defined.';
470
- }
471
-
472
- if (/^.+-header-[0-9]+-key$/.test(id)) {
473
- return 'Must be unique.';
474
- }
475
-
476
- if (/^.+-extensionProperty-[0-9]+-name$/.test(id)) {
477
- return getNotSupportedMessage('', allowedVersion);
478
- }
479
-
480
- if (id === 'userTaskImplementation') {
481
- return 'Supported only in Camunda 8.5 or newer.';
482
- }
483
-
484
- if (id === 'conditionExpression') {
485
- return 'Condition expression must be defined.';
486
- }
487
-
488
- if (id === 'timerEventDefinitionType' && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
489
- return getNotSupportedMessage('Type', allowedVersion);
490
- }
491
-
492
- if (id === 'timerEventDefinitionValue') {
493
- if (type === ERROR_TYPES.EXPRESSION_REQUIRED) {
494
- return 'Value must be defined.';
495
- }
496
-
497
- const { property } = data;
498
-
499
- if (property === 'timeCycle') {
500
- if (!greaterOrEqual(executionPlatformVersion, '8.1')) {
501
- return 'Must be an expression, an ISO 8601 repeating interval, or a cron expression (cron only supported by Camunda 8.1 or newer).';
502
- }
503
-
504
- return 'Must be an expression, an ISO 8601 repeating interval, or a cron expression.';
505
- }
506
-
507
- if (property === 'timeDate') {
508
- return 'Must be an expression, or an ISO 8601 date.';
509
- }
510
-
511
- if (property === 'timeDuration') {
512
- return 'Must be an expression, or an ISO 8601 interval.';
513
- }
514
- }
515
-
516
- if (id === 'assignmentDefinitionCandidateUsers') {
517
- return getNotSupportedMessage('', allowedVersion);
518
- }
519
-
520
- if (id === 'taskScheduleDueDate') {
521
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
522
- return getNotSupportedMessage('', allowedVersion);
523
- } else {
524
- return 'Must be an ISO 8601 date.';
525
- }
526
- }
527
-
528
- if (id === 'taskScheduleFollowUpDate') {
529
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
530
- return getNotSupportedMessage('', allowedVersion);
531
- } else {
532
- return 'Must be an ISO 8601 date.';
533
- }
534
- }
535
-
536
- if (id === 'propagateAllParentVariables') {
537
- return getNotSupportedMessage('', allowedVersion);
538
- }
539
-
540
- if (id === 'linkName') {
541
- if (type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED) {
542
- return 'Must be unique.';
543
- } else {
544
- return 'Must be defined.';
545
- }
546
- }
547
-
548
- if (id === 'waitForCompletion') {
549
- return 'Must wait for completion.';
550
- }
551
-
552
- if (/^.+-executionListener-[0-9]+-listenerType$/.test(id)) {
553
- if (type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED) {
554
- return 'Must be unique.';
555
- } else {
556
- return 'Must be defined.';
557
- }
558
- }
559
-
560
- if (id === 'bindingType') {
561
- return getNotSupportedMessage('', allowedVersion);
562
- }
563
- }
564
-
565
- function isExtensionElementNotAllowedError(data, extensionElement, type) {
566
- return data.type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED
567
- && is(data.extensionElement, extensionElement)
568
- && (!type || is(data.node, type));
569
- }
570
-
571
- function isExtensionElementRequiredError(data, requiredExtensionElement, type) {
572
- return data.type === ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED
573
- && (isArray(data.requiredExtensionElement) && data.requiredExtensionElement.includes(requiredExtensionElement)
574
- || data.requiredExtensionElement === requiredExtensionElement)
575
- && (!type || is(data.node, type));
576
- }
577
-
578
- function isPropertyDependentRequiredError(data, dependentRequiredProperty, type) {
579
- return data.type === ERROR_TYPES.PROPERTY_DEPENDENT_REQUIRED
580
- && data.dependentRequiredProperty === dependentRequiredProperty
581
- && (!type || is(data.node, type));
582
- }
583
-
584
-
585
- function isPropertyError(data, property, type) {
586
- return getPropertyName(data) === property
587
- && (!type || is(data.node, type));
588
- }
589
-
590
- function getPropertyName(data) {
591
- if (data.type === ERROR_TYPES.PROPERTY_REQUIRED) {
592
- return data.requiredProperty;
593
- }
594
-
595
- return data.property;
596
- }
597
-
598
- function isType(data, type) {
599
- return data.node && is(data.node, type);
600
- }
601
-
602
- function isOneOfPropertiesRequiredError(data, requiredProperty, type) {
603
- return data.type === ERROR_TYPES.PROPERTY_REQUIRED
604
- && (isArray(data.requiredProperty) && data.requiredProperty.includes(requiredProperty))
605
- && (!type || is(data.node, type));
606
- }
607
-
608
- function isPropertyValueDuplicatedError(data, propertiesName, duplicatedProperty, type) {
609
- return data.type === ERROR_TYPES.PROPERTY_VALUE_DUPLICATED
610
- && data.propertiesName === propertiesName
611
- && data.duplicatedProperty === duplicatedProperty
612
- && (!type || is(data.node, type));
613
- }
614
-
615
- function isPropertyValuesDuplicatedError(data, type) {
616
- return data.type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED
617
- && (!type || is(data.node, type));
618
- }
619
-
620
- function isExpressionRequiredError(data, propertyName, type) {
621
- return data.type === ERROR_TYPES.EXPRESSION_REQUIRED
622
- && data.property === propertyName
623
- && (!type || is(data.node, type));
624
- }
625
-
626
- function isExpressionValueNotAllowedError(data, propertyName, type) {
627
- return data.type === ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED
628
- && data.property === propertyName
629
- && (!type || is(data.node, type));
630
- }
631
-
632
- function isElementPropertyValueDuplicated(data, propertyName, type) {
633
- return data.type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED
634
- && data.duplicatedProperty === propertyName
635
- && (!type || is(data.node, type));
636
- }
637
-
638
- function getBusinessObject(element) {
639
- return element.businessObject || element;
640
- }
641
-
642
- function isEmptyString(value) {
643
- return isString(value) && value.trim() === '';
644
- }
645
-
646
- function getNotSupportedMessage(property, allowedVersion) {
647
-
648
- if (allowedVersion) {
649
- return property ?
650
- `${ property } is only supported by Camunda ${ allowedVersion } or newer.` :
651
- `Only supported by Camunda ${ allowedVersion } or newer.`;
652
- }
653
-
654
- return property ? `${ property } is not supported.` : 'Not supported.';
1
+ import {
2
+ isArray,
3
+ isString
4
+ } from 'min-dash';
5
+
6
+ import { is } from 'bpmnlint-utils';
7
+
8
+ import { ERROR_TYPES } from 'bpmnlint-plugin-camunda-compat/rules/utils/error-types';
9
+
10
+ import { greaterOrEqual } from './version';
11
+
12
+ const TIMER_PROPERTIES = [
13
+ 'timeDate',
14
+ 'timeDuration',
15
+ 'timeCycle'
16
+ ];
17
+
18
+ /**
19
+ * Get errors for a given element.
20
+ *
21
+ * @param {Object[]} reports
22
+ * @param {Object} element
23
+ *
24
+ * @returns {Object}
25
+ */
26
+ export function getErrors(reports, element) {
27
+ return reports.reduce((errors, report) => {
28
+ const { category } = report;
29
+
30
+ if (!element
31
+ || getBusinessObject(element).get('id') !== report.id
32
+ || category !== 'error') {
33
+ return errors;
34
+ }
35
+
36
+ const ids = getEntryIds(report);
37
+
38
+ if (!ids.length) {
39
+ return errors;
40
+ }
41
+
42
+ let { message } = report;
43
+
44
+ return {
45
+ ...errors,
46
+ ...ids.reduce((errors, id) => {
47
+ return {
48
+ ...errors,
49
+ [ id ]: getErrorMessage(id, report) || message
50
+ };
51
+ }, {})
52
+ };
53
+ }, {});
54
+ }
55
+
56
+ export function getEntryIds(report) {
57
+ const {
58
+ data = {},
59
+ id,
60
+ path,
61
+ propertiesPanel = {}
62
+ } = report;
63
+
64
+ if (propertiesPanel.entryIds) {
65
+ return propertiesPanel.entryIds;
66
+ }
67
+
68
+ if (isPropertyError(data, 'isExecutable')) {
69
+ return [ 'isExecutable' ];
70
+ }
71
+
72
+ if (isExtensionElementRequiredError(data, 'zeebe:CalledDecision', 'bpmn:BusinessRuleTask')) {
73
+ return [ 'businessRuleImplementation' ];
74
+ }
75
+
76
+ // script task
77
+ if (isExtensionElementRequiredError(data, 'zeebe:Script', 'bpmn:ScriptTask')) {
78
+ return [ 'scriptImplementation' ];
79
+ }
80
+
81
+ if (isPropertyError(data, 'errorRef')) {
82
+ return [ 'errorRef' ];
83
+ }
84
+
85
+ if (isPropertyError(data, 'escalationRef')) {
86
+ return [ 'escalationRef' ];
87
+ }
88
+
89
+ if (isPropertyError(data, 'messageRef')) {
90
+ return [ 'messageRef' ];
91
+ }
92
+
93
+ if (isPropertyError(data, 'signalRef')) {
94
+ return [ 'signalRef' ];
95
+ }
96
+
97
+ if (isPropertyError(data, 'historyTimeToLive')) {
98
+ return [ 'historyTimeToLive' ];
99
+ }
100
+
101
+ if (isPropertyError(data, 'decisionId', 'zeebe:CalledDecision')) {
102
+ return [ 'decisionId' ];
103
+ }
104
+
105
+ if (isPropertyError(data, 'resultVariable')) {
106
+ return [ 'resultVariable' ];
107
+ }
108
+
109
+ if (isPropertyError(data, 'expression', 'zeebe:Script')) {
110
+ return [ 'scriptExpression' ];
111
+ }
112
+
113
+ if (isPropertyError(data, 'errorCode', 'bpmn:Error')) {
114
+ return [ 'errorCode' ];
115
+ }
116
+
117
+ if (isPropertyError(data, 'escalationCode', 'bpmn:Escalation')) {
118
+ return [ 'escalationCode' ];
119
+ }
120
+
121
+ if (isPropertyError(data, 'name', 'bpmn:Message')) {
122
+ return [ 'messageName' ];
123
+ }
124
+
125
+ if (isPropertyError(data, 'name', 'bpmn:Signal')) {
126
+ return [ 'signalName' ];
127
+ }
128
+
129
+ if (isExtensionElementRequiredError(data, 'zeebe:LoopCharacteristics', 'bpmn:MultiInstanceLoopCharacteristics')
130
+ || isPropertyError(data, 'inputCollection', 'zeebe:LoopCharacteristics')) {
131
+ return [ 'multiInstance-inputCollection' ];
132
+ }
133
+
134
+ if (isPropertyDependentRequiredError(data, 'outputCollection', 'zeebe:LoopCharacteristics')) {
135
+ return [ 'multiInstance-outputCollection' ];
136
+ }
137
+
138
+ if (isPropertyDependentRequiredError(data, 'outputElement', 'zeebe:LoopCharacteristics')) {
139
+ return [ 'multiInstance-outputElement' ];
140
+ }
141
+
142
+ if (isExtensionElementRequiredError(data, 'zeebe:CalledElement', 'bpmn:CallActivity')
143
+ || isPropertyError(data, 'processId', 'zeebe:CalledElement')) {
144
+ return [ 'targetProcessId' ];
145
+ }
146
+
147
+ if (isExtensionElementRequiredError(data, 'zeebe:TaskDefinition')
148
+ || isPropertyError(data, 'type', 'zeebe:TaskDefinition')) {
149
+ return [ 'taskDefinitionType' ];
150
+ }
151
+
152
+ if (isPropertyError(data, 'retries', 'zeebe:TaskDefinition')) {
153
+ return [ 'taskDefinitionRetries' ];
154
+ }
155
+
156
+ if (isExtensionElementRequiredError(data, 'zeebe:Subscription')
157
+ || isPropertyError(data, 'correlationKey', 'zeebe:Subscription')) {
158
+ return [ 'messageSubscriptionCorrelationKey' ];
159
+ }
160
+
161
+ if (isPropertyError(data, 'formKey', 'zeebe:FormDefinition')) {
162
+ return [ 'customFormKey' ];
163
+ }
164
+
165
+ if (isType(data, 'zeebe:FormDefinition')) {
166
+ const {
167
+ node,
168
+ requiredProperty
169
+ } = data;
170
+
171
+ if (isArray(requiredProperty)) {
172
+ if (requiredProperty.includes('formKey') && isEmptyString(node.get('formKey'))) {
173
+ return [ 'customFormKey' ];
174
+ } else if (requiredProperty.includes('formId') && isEmptyString(node.get('formId'))) {
175
+ return [ 'formId' ];
176
+ } else if (requiredProperty.includes('externalReference') && isEmptyString(node.get('externalReference'))) {
177
+ return [ 'externalReference' ];
178
+ }
179
+ }
180
+ }
181
+
182
+ if (isPropertyError(data, 'formId', 'zeebe:FormDefinition')) {
183
+ return [ 'formId' ];
184
+ }
185
+
186
+ if (isPropertyError(data, 'body', 'zeebe:UserTaskForm')) {
187
+ return [ 'formConfiguration' ];
188
+ }
189
+
190
+ if (isPropertyValueDuplicatedError(data, 'values', 'key', 'zeebe:TaskHeaders')) {
191
+ const {
192
+ node,
193
+ properties,
194
+ propertiesName
195
+ } = data;
196
+
197
+ return properties.map(property => {
198
+ const index = node.get(propertiesName).indexOf(property);
199
+
200
+ return `${ id }-header-${ index }-key`;
201
+ });
202
+ }
203
+
204
+ if (isExtensionElementNotAllowedError(data, 'zeebe:Properties')) {
205
+ const { extensionElement } = data;
206
+
207
+ return extensionElement.get('zeebe:properties').map((zeebeProperty, index) => {
208
+ return `${ id }-extensionProperty-${ index }-name`;
209
+ });
210
+ }
211
+
212
+ if (isExtensionElementNotAllowedError(data, 'zeebe:UserTask')) {
213
+ return [ 'userTaskImplementation' ];
214
+ }
215
+
216
+ if (isExtensionElementNotAllowedError(data, 'zeebe:FormDefinition', 'bpmn:StartEvent')) {
217
+ return [ 'formType' ];
218
+ }
219
+
220
+
221
+ if (isPropertyError(data, 'conditionExpression', 'bpmn:SequenceFlow')) {
222
+ return [ 'conditionExpression' ];
223
+ }
224
+
225
+ if (isPropertyError(data, 'completionCondition', 'bpmn:MultiInstanceLoopCharacteristics')) {
226
+ return [ 'multiInstance-completionCondition' ];
227
+ }
228
+
229
+ if (TIMER_PROPERTIES.some(property =>
230
+ isOneOfPropertiesRequiredError(data, property, 'bpmn:TimerEventDefinition'))
231
+ ) {
232
+ return [ 'timerEventDefinitionType' ];
233
+ }
234
+
235
+ if (isExpressionRequiredError(data, 'timeCycle', 'bpmn:FormalExpression')
236
+ || isExpressionRequiredError(data, 'timeDate', 'bpmn:FormalExpression')
237
+ || isExpressionRequiredError(data, 'timeDuration', 'bpmn:FormalExpression')) {
238
+ return [ 'timerEventDefinitionValue' ];
239
+ }
240
+
241
+ if (isExpressionValueNotAllowedError(data, 'timeCycle', 'bpmn:FormalExpression')
242
+ || isExpressionValueNotAllowedError(data, 'timeDate', 'bpmn:FormalExpression')
243
+ || isExpressionValueNotAllowedError(data, 'timeDuration', 'bpmn:FormalExpression')) {
244
+ return [ 'timerEventDefinitionValue' ];
245
+ }
246
+
247
+ if (isPropertyError(data, 'timeCycle', 'bpmn:TimerEventDefinition')
248
+ || isPropertyError(data, 'timeDate', 'bpmn:TimerEventDefinition')
249
+ || isPropertyError(data, 'timeDuration', 'bpmn:TimerEventDefinition')) {
250
+ return [ 'timerEventDefinitionType' ];
251
+ }
252
+
253
+ const LIST_PROPERTIES = [
254
+ [ 'zeebe:Input', 'input' ],
255
+ [ 'zeebe:Output', 'output' ],
256
+ [ 'zeebe:Property', 'extensionProperty' ],
257
+ [ 'zeebe:Header', 'header' ]
258
+ ];
259
+
260
+ for (const [ type, prefix ] of LIST_PROPERTIES) {
261
+ if (isType(data, type)
262
+ && getPropertyName(data)) {
263
+
264
+ const index = path[ path.length - 2 ];
265
+
266
+ return [ `${ id }-${ prefix }-${ index }-${ getPropertyName(data) }` ];
267
+ }
268
+ }
269
+
270
+ if (isType(data, 'zeebe:LoopCharacteristics')) {
271
+ return [ `multiInstance-${getPropertyName(data)}` ];
272
+ }
273
+
274
+ if (isPropertyError(data, 'candidateUsers', 'zeebe:AssignmentDefinition')) {
275
+ return [ 'assignmentDefinitionCandidateUsers' ];
276
+ }
277
+
278
+ if (isPropertyError(data, 'historyTimeToLive', 'bpmn:Process')) {
279
+ return [ 'historyTimeToLive' ];
280
+ }
281
+
282
+ if (isExpressionValueNotAllowedError(data, 'dueDate', 'zeebe:TaskSchedule')) {
283
+ return [ 'taskScheduleDueDate' ];
284
+ }
285
+
286
+ if (isExpressionValueNotAllowedError(data, 'followUpDate', 'zeebe:TaskSchedule')) {
287
+ return [ 'taskScheduleFollowUpDate' ];
288
+ }
289
+
290
+ if (isExtensionElementNotAllowedError(data, 'zeebe:TaskSchedule', 'bpmn:UserTask')) {
291
+ const { extensionElement: taskSchedule } = data;
292
+
293
+ let ids = [];
294
+
295
+ if (taskSchedule.get('dueDate')) {
296
+ ids = [ ...ids, 'taskScheduleDueDate' ];
297
+ }
298
+
299
+ if (taskSchedule.get('followUpDate')) {
300
+ ids = [ ...ids, 'taskScheduleFollowUpDate' ];
301
+ }
302
+
303
+ return ids;
304
+ }
305
+
306
+ if (isExpressionValueNotAllowedError(data, 'priority', 'zeebe:PriorityDefinition')) {
307
+ return [ 'priorityDefinitionPriority' ];
308
+ }
309
+
310
+ if (isExtensionElementNotAllowedError(data, 'zeebe:PriorityDefinition', 'bpmn:UserTask')) {
311
+ return [ 'priorityDefinition' ];
312
+ }
313
+
314
+ if (isPropertyError(data, 'propagateAllParentVariables', 'zeebe:CalledElement')) {
315
+ return [ 'propagateAllParentVariables' ];
316
+ }
317
+
318
+ if (isPropertyError(data, 'name', 'bpmn:LinkEventDefinition')
319
+ || isElementPropertyValueDuplicated(data, 'name', 'bpmn:LinkEventDefinition')) {
320
+ return [ 'linkName' ];
321
+ }
322
+
323
+ if (isPropertyError(data, 'waitForCompletion', 'bpmn:CompensateEventDefinition')) {
324
+ return [ 'waitForCompletion' ];
325
+ }
326
+
327
+ if (isPropertyError(data, 'type', 'zeebe:ExecutionListener')) {
328
+ const index = path[ path.length - 2 ];
329
+
330
+ return [ `${id}-executionListener-${index}-listenerType` ];
331
+ }
332
+
333
+ if (isPropertyValuesDuplicatedError(data, 'zeebe:ExecutionListeners')) {
334
+ const { properties, propertiesName } = data;
335
+
336
+ return properties.map(property => {
337
+ const index = data.node.get(propertiesName).indexOf(property);
338
+
339
+ return `${ id }-executionListener-${ index }-listenerType`;
340
+ });
341
+ }
342
+
343
+ if (isPropertyError(data, 'bindingType')) {
344
+ return [ 'bindingType' ];
345
+ }
346
+
347
+ return [];
348
+ }
349
+
350
+ export function getErrorMessage(id, report) {
351
+ const {
352
+ data = {},
353
+ executionPlatformVersion
354
+ } = report;
355
+
356
+ const {
357
+ type,
358
+ allowedVersion
359
+ } = data;
360
+
361
+ // adjust FEEL message
362
+ if (type === ERROR_TYPES.FEEL_EXPRESSION_INVALID) {
363
+ return 'Unparsable FEEL expression.';
364
+ }
365
+
366
+ if (type === ERROR_TYPES.EXPRESSION_NOT_ALLOWED) {
367
+ return 'Cannot be an expression.';
368
+ }
369
+
370
+ if (id === 'isExecutable') {
371
+ const { parentNode } = data;
372
+
373
+ if (parentNode && is(parentNode, 'bpmn:Participant')) {
374
+ return 'One process must be executable.';
375
+ } else {
376
+ return 'Process must be executable.';
377
+ }
378
+ }
379
+
380
+ if ([ 'businessRuleImplementation', 'scriptImplementation' ].includes(id)) {
381
+ return 'Implementation must be defined.';
382
+ }
383
+
384
+ if (id === 'errorRef') {
385
+ return 'Global error reference must be defined.';
386
+ }
387
+
388
+ if (id === 'escalationRef') {
389
+ return 'Global escalation reference must be defined.';
390
+ }
391
+
392
+ if (id === 'messageRef') {
393
+ return 'Global message reference must be defined.';
394
+ }
395
+
396
+ if (id === 'signalRef') {
397
+ return 'Global signal reference must be defined.';
398
+ }
399
+
400
+ if (id === 'decisionId') {
401
+ return 'Decision ID must be defined.';
402
+ }
403
+
404
+ if (id === 'scriptExpression') {
405
+ return 'FEEL expression must be defined.';
406
+ }
407
+
408
+ if (id === 'resultVariable') {
409
+ return 'Result variable must be defined.';
410
+ }
411
+
412
+ if (id === 'errorCode' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
413
+ return 'Code must be defined.';
414
+ }
415
+
416
+ if (id === 'escalationCode' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
417
+ return 'Code must be defined.';
418
+ }
419
+
420
+ if (id === 'messageName') {
421
+ return 'Name must be defined.';
422
+ }
423
+
424
+ if (id === 'signalName') {
425
+ return 'Name must be defined.';
426
+ }
427
+
428
+ if (id === 'multiInstance-inputCollection') {
429
+ return 'Input collection must be defined.';
430
+ }
431
+
432
+ if (id === 'multiInstance-outputCollection') {
433
+ return 'Output collection must be defined.';
434
+ }
435
+
436
+ if (id === 'multiInstance-outputElement') {
437
+ return 'Output element must be defined.';
438
+ }
439
+
440
+ if (id === 'targetProcessId') {
441
+ return 'Process ID must be defined.';
442
+ }
443
+
444
+ if (id === 'taskDefinitionType') {
445
+ return 'Type must be defined.';
446
+ }
447
+
448
+ if (id === 'timerEventDefinitionType' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
449
+ return 'Type must be defined.';
450
+ }
451
+
452
+ if (id === 'messageSubscriptionCorrelationKey'
453
+ && [
454
+ ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
455
+ ERROR_TYPES.PROPERTY_REQUIRED
456
+ ].includes(type)) {
457
+ return 'Subscription correlation key must be defined.';
458
+ }
459
+
460
+ if (id === 'customFormKey') {
461
+ return 'Form key must be defined.';
462
+ }
463
+
464
+ if (id === 'formId') {
465
+ if (type === ERROR_TYPES.PROPERTY_REQUIRED) {
466
+ return 'Form ID must be defined.';
467
+ } else if (type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
468
+ return getNotSupportedMessage('Form ID', allowedVersion);
469
+ }
470
+ }
471
+
472
+ if (id === 'externalReference') {
473
+ return 'External reference must be defined.';
474
+ }
475
+
476
+ if (id === 'formConfiguration') {
477
+ return 'Form JSON configuration must be defined.';
478
+ }
479
+
480
+ if (/^.+-header-[0-9]+-key$/.test(id)) {
481
+ return 'Must be unique.';
482
+ }
483
+
484
+ if (/^.+-extensionProperty-[0-9]+-name$/.test(id)) {
485
+ return getNotSupportedMessage('', allowedVersion);
486
+ }
487
+
488
+ if (id === 'userTaskImplementation') {
489
+ return 'Supported only in Camunda 8.5 or newer.';
490
+ }
491
+
492
+ if (id === 'conditionExpression') {
493
+ return 'Condition expression must be defined.';
494
+ }
495
+
496
+ if (id === 'timerEventDefinitionType' && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
497
+ return getNotSupportedMessage('Type', allowedVersion);
498
+ }
499
+
500
+ if (id === 'timerEventDefinitionValue') {
501
+ if (type === ERROR_TYPES.EXPRESSION_REQUIRED) {
502
+ return 'Value must be defined.';
503
+ }
504
+
505
+ const { property } = data;
506
+
507
+ if (property === 'timeCycle') {
508
+ if (!greaterOrEqual(executionPlatformVersion, '8.1')) {
509
+ return 'Must be an expression, an ISO 8601 repeating interval, or a cron expression (cron only supported by Camunda 8.1 or newer).';
510
+ }
511
+
512
+ return 'Must be an expression, an ISO 8601 repeating interval, or a cron expression.';
513
+ }
514
+
515
+ if (property === 'timeDate') {
516
+ return 'Must be an expression, or an ISO 8601 date.';
517
+ }
518
+
519
+ if (property === 'timeDuration') {
520
+ return 'Must be an expression, or an ISO 8601 interval.';
521
+ }
522
+ }
523
+
524
+ if (id === 'assignmentDefinitionCandidateUsers') {
525
+ return getNotSupportedMessage('', allowedVersion);
526
+ }
527
+
528
+ if (id === 'taskScheduleDueDate') {
529
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
530
+ return getNotSupportedMessage('', allowedVersion);
531
+ } else {
532
+ return 'Must be an ISO 8601 date.';
533
+ }
534
+ }
535
+
536
+ if (id === 'taskScheduleFollowUpDate') {
537
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
538
+ return getNotSupportedMessage('', allowedVersion);
539
+ } else {
540
+ return 'Must be an ISO 8601 date.';
541
+ }
542
+ }
543
+
544
+ if (id === 'priorityDefinitionPriority') {
545
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
546
+ return getNotSupportedMessage('', allowedVersion);
547
+ } else {
548
+ return 'Must be an expression, or an integer between 0 and 100.';
549
+ }
550
+ }
551
+
552
+ if (id === 'propagateAllParentVariables') {
553
+ return getNotSupportedMessage('', allowedVersion);
554
+ }
555
+
556
+ if (id === 'linkName') {
557
+ if (type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED) {
558
+ return 'Must be unique.';
559
+ } else {
560
+ return 'Must be defined.';
561
+ }
562
+ }
563
+
564
+ if (id === 'waitForCompletion') {
565
+ return 'Must wait for completion.';
566
+ }
567
+
568
+ if (/^.+-executionListener-[0-9]+-listenerType$/.test(id)) {
569
+ if (type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED) {
570
+ return 'Must be unique.';
571
+ } else {
572
+ return 'Must be defined.';
573
+ }
574
+ }
575
+
576
+ if (id === 'bindingType') {
577
+ return getNotSupportedMessage('', allowedVersion);
578
+ }
579
+ }
580
+
581
+ function isExtensionElementNotAllowedError(data, extensionElement, type) {
582
+ return data.type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED
583
+ && is(data.extensionElement, extensionElement)
584
+ && (!type || is(data.node, type));
585
+ }
586
+
587
+ function isExtensionElementRequiredError(data, requiredExtensionElement, type) {
588
+ return data.type === ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED
589
+ && (isArray(data.requiredExtensionElement) && data.requiredExtensionElement.includes(requiredExtensionElement)
590
+ || data.requiredExtensionElement === requiredExtensionElement)
591
+ && (!type || is(data.node, type));
592
+ }
593
+
594
+ function isPropertyDependentRequiredError(data, dependentRequiredProperty, type) {
595
+ return data.type === ERROR_TYPES.PROPERTY_DEPENDENT_REQUIRED
596
+ && data.dependentRequiredProperty === dependentRequiredProperty
597
+ && (!type || is(data.node, type));
598
+ }
599
+
600
+
601
+ function isPropertyError(data, property, type) {
602
+ return getPropertyName(data) === property
603
+ && (!type || is(data.node, type));
604
+ }
605
+
606
+ function getPropertyName(data) {
607
+ if (data.type === ERROR_TYPES.PROPERTY_REQUIRED) {
608
+ return data.requiredProperty;
609
+ }
610
+
611
+ return data.property;
612
+ }
613
+
614
+ function isType(data, type) {
615
+ return data.node && is(data.node, type);
616
+ }
617
+
618
+ function isOneOfPropertiesRequiredError(data, requiredProperty, type) {
619
+ return data.type === ERROR_TYPES.PROPERTY_REQUIRED
620
+ && (isArray(data.requiredProperty) && data.requiredProperty.includes(requiredProperty))
621
+ && (!type || is(data.node, type));
622
+ }
623
+
624
+ function isPropertyValueDuplicatedError(data, propertiesName, duplicatedProperty, type) {
625
+ return data.type === ERROR_TYPES.PROPERTY_VALUE_DUPLICATED
626
+ && data.propertiesName === propertiesName
627
+ && data.duplicatedProperty === duplicatedProperty
628
+ && (!type || is(data.node, type));
629
+ }
630
+
631
+ function isPropertyValuesDuplicatedError(data, type) {
632
+ return data.type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED
633
+ && (!type || is(data.node, type));
634
+ }
635
+
636
+ function isExpressionRequiredError(data, propertyName, type) {
637
+ return data.type === ERROR_TYPES.EXPRESSION_REQUIRED
638
+ && data.property === propertyName
639
+ && (!type || is(data.node, type));
640
+ }
641
+
642
+ function isExpressionValueNotAllowedError(data, propertyName, type) {
643
+ return data.type === ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED
644
+ && data.property === propertyName
645
+ && (!type || is(data.node, type));
646
+ }
647
+
648
+ function isElementPropertyValueDuplicated(data, propertyName, type) {
649
+ return data.type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED
650
+ && data.duplicatedProperty === propertyName
651
+ && (!type || is(data.node, type));
652
+ }
653
+
654
+ function getBusinessObject(element) {
655
+ return element.businessObject || element;
656
+ }
657
+
658
+ function isEmptyString(value) {
659
+ return isString(value) && value.trim() === '';
660
+ }
661
+
662
+ function getNotSupportedMessage(property, allowedVersion) {
663
+
664
+ if (allowedVersion) {
665
+ return property ?
666
+ `${ property } is only supported by Camunda ${ allowedVersion } or newer.` :
667
+ `Only supported by Camunda ${ allowedVersion } or newer.`;
668
+ }
669
+
670
+ return property ? `${ property } is not supported.` : 'Not supported.';
655
671
  }