@camunda/linting 3.41.0 → 3.42.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,758 +1,758 @@
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 (
213
- isExtensionElementNotAllowedError(data, 'zeebe:UserTask') ||
214
- isExtensionElementRequiredError(data, 'zeebe:UserTask')
215
- ) {
216
- return [ 'userTaskImplementation' ];
217
- }
218
-
219
- if (isExtensionElementNotAllowedError(data, 'zeebe:FormDefinition', 'bpmn:StartEvent')) {
220
- return [ 'formType' ];
221
- }
222
-
223
-
224
- if (isPropertyError(data, 'conditionExpression', 'bpmn:SequenceFlow')) {
225
- return [ 'conditionExpression' ];
226
- }
227
-
228
- if (isPropertyError(data, 'completionCondition', 'bpmn:MultiInstanceLoopCharacteristics')) {
229
- return [ 'multiInstance-completionCondition' ];
230
- }
231
-
232
- if (isPropertyError(data, 'completionCondition', 'bpmn:AdHocSubProcess')) {
233
- return [ 'completionCondition' ];
234
- }
235
-
236
- if (isPropertyError(data, 'cancelRemainingInstances', 'bpmn:AdHocSubProcess')) {
237
- return [ 'cancelRemainingInstances' ];
238
- }
239
-
240
- if (TIMER_PROPERTIES.some(property =>
241
- isOneOfPropertiesRequiredError(data, property, 'bpmn:TimerEventDefinition'))
242
- ) {
243
- return [ 'timerEventDefinitionType' ];
244
- }
245
-
246
- if (isExpressionRequiredError(data, 'timeCycle', 'bpmn:FormalExpression')
247
- || isExpressionRequiredError(data, 'timeDate', 'bpmn:FormalExpression')
248
- || isExpressionRequiredError(data, 'timeDuration', 'bpmn:FormalExpression')) {
249
- return [ 'timerEventDefinitionValue' ];
250
- }
251
-
252
- if (isExpressionValueNotAllowedError(data, 'timeCycle', 'bpmn:FormalExpression')
253
- || isExpressionValueNotAllowedError(data, 'timeDate', 'bpmn:FormalExpression')
254
- || isExpressionValueNotAllowedError(data, 'timeDuration', 'bpmn:FormalExpression')) {
255
- return [ 'timerEventDefinitionValue' ];
256
- }
257
-
258
- if (isPropertyError(data, 'timeCycle', 'bpmn:TimerEventDefinition')
259
- || isPropertyError(data, 'timeDate', 'bpmn:TimerEventDefinition')
260
- || isPropertyError(data, 'timeDuration', 'bpmn:TimerEventDefinition')) {
261
- return [ 'timerEventDefinitionType' ];
262
- }
263
-
264
- const LIST_PROPERTIES = [
265
- [ 'zeebe:Input', 'input' ],
266
- [ 'zeebe:Output', 'output' ],
267
- [ 'zeebe:Property', 'extensionProperty' ],
268
- [ 'zeebe:Header', 'header' ]
269
- ];
270
-
271
- for (const [ type, prefix ] of LIST_PROPERTIES) {
272
- if (isType(data, type)
273
- && getPropertyName(data)) {
274
-
275
- const index = path[ path.length - 2 ];
276
-
277
- return [ `${ id }-${ prefix }-${ index }-${ getPropertyName(data) }` ];
278
- }
279
- }
280
-
281
- if (isType(data, 'zeebe:LoopCharacteristics')) {
282
- return [ `multiInstance-${getPropertyName(data)}` ];
283
- }
284
-
285
- if (isPropertyError(data, 'candidateUsers', 'zeebe:AssignmentDefinition')) {
286
- return [ 'assignmentDefinitionCandidateUsers' ];
287
- }
288
-
289
- if (isPropertyError(data, 'historyTimeToLive', 'bpmn:Process')) {
290
- return [ 'historyTimeToLive' ];
291
- }
292
-
293
- if (isExpressionValueNotAllowedError(data, 'dueDate', 'zeebe:TaskSchedule')) {
294
- return [ 'taskScheduleDueDate' ];
295
- }
296
-
297
- if (isExpressionValueNotAllowedError(data, 'followUpDate', 'zeebe:TaskSchedule')) {
298
- return [ 'taskScheduleFollowUpDate' ];
299
- }
300
-
301
- if (isExtensionElementNotAllowedError(data, 'zeebe:TaskSchedule', 'bpmn:UserTask')) {
302
- const { extensionElement: taskSchedule } = data;
303
-
304
- let ids = [];
305
-
306
- if (taskSchedule.get('dueDate')) {
307
- ids = [ ...ids, 'taskScheduleDueDate' ];
308
- }
309
-
310
- if (taskSchedule.get('followUpDate')) {
311
- ids = [ ...ids, 'taskScheduleFollowUpDate' ];
312
- }
313
-
314
- return ids;
315
- }
316
-
317
- if (isExpressionValueNotAllowedError(data, 'priority', 'zeebe:PriorityDefinition')
318
- || isExtensionElementNotAllowedError(data, 'zeebe:PriorityDefinition', 'bpmn:UserTask')) {
319
- return [ 'priorityDefinitionPriority' ];
320
- }
321
-
322
- if (isPropertyError(data, 'propagateAllParentVariables', 'zeebe:CalledElement')) {
323
- return [ 'propagateAllParentVariables' ];
324
- }
325
-
326
- if (isPropertyError(data, 'name', 'bpmn:LinkEventDefinition')
327
- || isElementPropertyValueDuplicated(data, 'name', 'bpmn:LinkEventDefinition')) {
328
- return [ 'linkName' ];
329
- }
330
-
331
- if (isPropertyError(data, 'waitForCompletion', 'bpmn:CompensateEventDefinition')) {
332
- return [ 'waitForCompletion' ];
333
- }
334
-
335
- if (isPropertyError(data, 'type', 'zeebe:ExecutionListener')) {
336
- const index = path[ path.length - 2 ];
337
-
338
- return [ `${id}-executionListener-${index}-listenerType` ];
339
- }
340
-
341
- if (isPropertyValuesDuplicatedError(data, 'zeebe:ExecutionListeners')) {
342
- const { properties, propertiesName } = data;
343
-
344
- return properties.map(property => {
345
- const index = data.node.get(propertiesName).indexOf(property);
346
-
347
- return `${ id }-executionListener-${ index }-listenerType`;
348
- });
349
- }
350
-
351
- if (isPropertyError(data, 'type', 'zeebe:TaskListener')) {
352
- const index = path[ path.length - 2 ];
353
-
354
- return [ `${id}-taskListener-${index}-listenerType` ];
355
- }
356
-
357
- if (isPropertyError(data, 'bindingType')) {
358
- return [ 'bindingType' ];
359
- }
360
-
361
- if (isPropertyError(data, 'versionTag') || isExtensionElementNotAllowedError(data, 'zeebe:VersionTag')) {
362
- return [ 'versionTag' ];
363
- }
364
-
365
- // (1) match dependent property errors first
366
- if (isPropertyDependentRequiredError(data, 'outputCollection', 'zeebe:AdHoc')) {
367
- return [ 'adHocOutputCollection' ];
368
- }
369
-
370
- if (isPropertyDependentRequiredError(data, 'outputElement', 'zeebe:AdHoc')) {
371
- return [ 'adHocOutputElement' ];
372
- }
373
-
374
- // (2) match property errors second
375
- if (isPropertyError(data, 'outputCollection', 'zeebe:AdHoc')) {
376
- return [ 'adHocOutputCollection' ];
377
- }
378
-
379
- if (isPropertyError(data, 'outputElement', 'zeebe:AdHoc')) {
380
- return [ 'adHocOutputElement' ];
381
- }
382
-
383
- return [];
384
- }
385
-
386
- export function getErrorMessage(id, report) {
387
- const {
388
- data = {},
389
- executionPlatformVersion
390
- } = report;
391
-
392
- const {
393
- type,
394
- allowedVersion
395
- } = data;
396
-
397
- // adjust FEEL message
398
- if (type === ERROR_TYPES.FEEL_EXPRESSION_INVALID) {
399
- return 'Unparsable FEEL expression.';
400
- }
401
-
402
- if (type === ERROR_TYPES.EXPRESSION_NOT_ALLOWED) {
403
- return 'Cannot be an expression.';
404
- }
405
-
406
- if (id === 'isExecutable') {
407
- const { parentNode } = data;
408
-
409
- if (parentNode && is(parentNode, 'bpmn:Participant')) {
410
- return 'One process must be executable.';
411
- } else {
412
- return 'Process must be executable.';
413
- }
414
- }
415
-
416
- if ([ 'businessRuleImplementation', 'scriptImplementation' ].includes(id)) {
417
- return 'Implementation must be defined.';
418
- }
419
-
420
- if (id === 'errorRef') {
421
- return 'Global error reference must be defined.';
422
- }
423
-
424
- if (id === 'escalationRef') {
425
- return 'Global escalation reference must be defined.';
426
- }
427
-
428
- if (id === 'messageRef') {
429
- return 'Global message reference must be defined.';
430
- }
431
-
432
- if (id === 'signalRef') {
433
- return 'Global signal reference must be defined.';
434
- }
435
-
436
- if (id === 'decisionId') {
437
- return 'Decision ID must be defined.';
438
- }
439
-
440
- if (id === 'scriptExpression') {
441
- return 'FEEL expression must be defined.';
442
- }
443
-
444
- if (id === 'resultVariable') {
445
- return 'Result variable must be defined.';
446
- }
447
-
448
- if (id === 'errorCode' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
449
- return 'Code must be defined.';
450
- }
451
-
452
- if (id === 'escalationCode' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
453
- return 'Code must be defined.';
454
- }
455
-
456
- if (id === 'messageName') {
457
- return 'Name must be defined.';
458
- }
459
-
460
- if (id === 'signalName') {
461
- return 'Name must be defined.';
462
- }
463
-
464
- if (id === 'multiInstance-inputCollection') {
465
- return 'Input collection must be defined.';
466
- }
467
-
468
- if (id === 'multiInstance-outputCollection') {
469
- return 'Output collection must be defined.';
470
- }
471
-
472
- if (id === 'multiInstance-outputElement') {
473
- return 'Output element must be defined.';
474
- }
475
-
476
- if (id === 'completionCondition' && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
477
- return getNotSupportedMessage('', allowedVersion);
478
- }
479
-
480
- if (id === 'cancelRemainingInstances' && type === ERROR_TYPES.PROPERTY_VALUE_NOT_ALLOWED) {
481
- return 'Must be checked.';
482
- }
483
-
484
- if (id === 'targetProcessId') {
485
- return 'Process ID must be defined.';
486
- }
487
-
488
- if (id === 'taskDefinitionType') {
489
- return 'Type must be defined.';
490
- }
491
-
492
- if (id === 'timerEventDefinitionType' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
493
- return 'Type must be defined.';
494
- }
495
-
496
- if (id === 'messageSubscriptionCorrelationKey'
497
- && [
498
- ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
499
- ERROR_TYPES.PROPERTY_REQUIRED
500
- ].includes(type)) {
501
- return 'Subscription correlation key must be defined.';
502
- }
503
-
504
- if (id === 'customFormKey') {
505
- return 'Form key must be defined.';
506
- }
507
-
508
- if (id === 'formId') {
509
- if (type === ERROR_TYPES.PROPERTY_REQUIRED) {
510
- return 'Form ID must be defined.';
511
- } else if (type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
512
- return getNotSupportedMessage('Form ID', allowedVersion);
513
- }
514
- }
515
-
516
- if (id === 'externalReference') {
517
- return 'External reference must be defined.';
518
- }
519
-
520
- if (id === 'formConfiguration') {
521
- return 'Form JSON configuration must be defined.';
522
- }
523
-
524
- if (/^.+-header-[0-9]+-key$/.test(id)) {
525
- return 'Must be unique.';
526
- }
527
-
528
- if (/^.+-extensionProperty-[0-9]+-name$/.test(id)) {
529
- return getNotSupportedMessage('', allowedVersion);
530
- }
531
-
532
- if (id === 'userTaskImplementation') {
533
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
534
- return getNotSupportedMessage('', allowedVersion);
535
- } else if (type === ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED) {
536
- return getNotSupportedMessage('');
537
- }
538
- }
539
-
540
- if (id === 'conditionExpression') {
541
- return 'Condition expression must be defined.';
542
- }
543
-
544
- if (id === 'timerEventDefinitionType' && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
545
- return getNotSupportedMessage('Type', allowedVersion);
546
- }
547
-
548
- if (id === 'timerEventDefinitionValue') {
549
- if (type === ERROR_TYPES.EXPRESSION_REQUIRED) {
550
- return 'Value must be defined.';
551
- }
552
-
553
- const { property } = data;
554
-
555
- if (property === 'timeCycle') {
556
- if (!greaterOrEqual(executionPlatformVersion, '8.1')) {
557
- return 'Must be an expression, an ISO 8601 repeating interval, or a cron expression (cron only supported by Camunda 8.1 or newer).';
558
- }
559
-
560
- return 'Must be an expression, an ISO 8601 repeating interval, or a cron expression.';
561
- }
562
-
563
- if (property === 'timeDate') {
564
- return 'Must be an expression, or an ISO 8601 date.';
565
- }
566
-
567
- if (property === 'timeDuration') {
568
- return 'Must be an expression, or an ISO 8601 interval.';
569
- }
570
- }
571
-
572
- if (id === 'assignmentDefinitionCandidateUsers') {
573
- return getNotSupportedMessage('', allowedVersion);
574
- }
575
-
576
- if (id === 'taskScheduleDueDate') {
577
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
578
- return getNotSupportedMessage('', allowedVersion);
579
- } else {
580
- return 'Must be an ISO 8601 date.';
581
- }
582
- }
583
-
584
- if (id === 'taskScheduleFollowUpDate') {
585
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
586
- return getNotSupportedMessage('', allowedVersion);
587
- } else {
588
- return 'Must be an ISO 8601 date.';
589
- }
590
- }
591
-
592
- if (id === 'priorityDefinitionPriority') {
593
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
594
- return getNotSupportedMessage('', allowedVersion);
595
- } else {
596
- return 'Must be an expression, or an integer between 0 and 100.';
597
- }
598
- }
599
-
600
- if (id === 'propagateAllParentVariables') {
601
- return getNotSupportedMessage('', allowedVersion);
602
- }
603
-
604
- if (id === 'linkName') {
605
- if (type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED) {
606
- return 'Must be unique.';
607
- } else {
608
- return 'Must be defined.';
609
- }
610
- }
611
-
612
- if (id === 'waitForCompletion') {
613
- return 'Must wait for completion.';
614
- }
615
-
616
- if (/^.+-executionListener-[0-9]+-listenerType$/.test(id)) {
617
- if (type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED) {
618
- return 'Must be unique.';
619
- } else {
620
- return 'Must be defined.';
621
- }
622
- }
623
-
624
- if (/^.+-taskListener-[0-9]+-listenerType$/.test(id)) {
625
- return 'Must be defined.';
626
- }
627
-
628
- if (/^.+-(?:input|output)-[0-9]+-source$/.test(id) && type === ERROR_TYPES.PROPERTY_REQUIRED) {
629
- if (allowedVersion) {
630
- return `Empty variable assignment is only supported by Camunda ${allowedVersion} or newer.`;
631
- }
632
- return 'Variable assignment must be defined.';
633
- }
634
-
635
- if (/^.+-(?:input|output)-[0-9]+-target$/.test(id) && type === ERROR_TYPES.PROPERTY_REQUIRED) {
636
- return 'Variable name must be defined.';
637
- }
638
-
639
- if (id === 'bindingType') {
640
- return getNotSupportedMessage('', allowedVersion);
641
- }
642
-
643
- if (id === 'versionTag') {
644
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
645
- return getNotSupportedMessage('', allowedVersion);
646
- } else {
647
- return 'Version tag must be defined.';
648
- }
649
- }
650
-
651
- if (isPropertyDependentRequiredError(data, 'outputCollection', 'zeebe:AdHoc')) {
652
- return 'Output collection must be defined.';
653
- }
654
-
655
- if (isPropertyDependentRequiredError(data, 'outputElement', 'zeebe:AdHoc')) {
656
- return 'Output element must be defined.';
657
- }
658
-
659
- if (isPropertyError(data, 'outputCollection', 'zeebe:AdHoc') && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
660
- return getNotSupportedMessage('Output collection', allowedVersion);
661
- }
662
-
663
- if (isPropertyError(data, 'outputElement', 'zeebe:AdHoc') && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
664
- return getNotSupportedMessage('Output element', allowedVersion);
665
- }
666
- }
667
-
668
- function isExtensionElementNotAllowedError(data, extensionElement, type) {
669
- return data.type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED
670
- && is(data.extensionElement, extensionElement)
671
- && (!type || is(data.node, type));
672
- }
673
-
674
- function isExtensionElementRequiredError(data, requiredExtensionElement, type) {
675
- return data.type === ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED
676
- && (isArray(data.requiredExtensionElement) && data.requiredExtensionElement.includes(requiredExtensionElement)
677
- || data.requiredExtensionElement === requiredExtensionElement)
678
- && (!type || is(data.node, type));
679
- }
680
-
681
- function isPropertyDependentRequiredError(data, dependentRequiredProperty, type) {
682
- return data.type === ERROR_TYPES.PROPERTY_DEPENDENT_REQUIRED
683
- && data.dependentRequiredProperty === dependentRequiredProperty
684
- && (!type || is(data.node, type));
685
- }
686
-
687
-
688
- function isPropertyError(data, property, type) {
689
- return getPropertyName(data) === property
690
- && (!type || is(data.node, type));
691
- }
692
-
693
- function getPropertyName(data) {
694
- if (data.type === ERROR_TYPES.PROPERTY_REQUIRED) {
695
- return data.requiredProperty;
696
- }
697
-
698
- return data.property;
699
- }
700
-
701
- function isType(data, type) {
702
- return data.node && is(data.node, type);
703
- }
704
-
705
- function isOneOfPropertiesRequiredError(data, requiredProperty, type) {
706
- return data.type === ERROR_TYPES.PROPERTY_REQUIRED
707
- && (isArray(data.requiredProperty) && data.requiredProperty.includes(requiredProperty))
708
- && (!type || is(data.node, type));
709
- }
710
-
711
- function isPropertyValueDuplicatedError(data, propertiesName, duplicatedProperty, type) {
712
- return data.type === ERROR_TYPES.PROPERTY_VALUE_DUPLICATED
713
- && data.propertiesName === propertiesName
714
- && data.duplicatedProperty === duplicatedProperty
715
- && (!type || is(data.node, type));
716
- }
717
-
718
- function isPropertyValuesDuplicatedError(data, type) {
719
- return data.type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED
720
- && (!type || is(data.node, type));
721
- }
722
-
723
- function isExpressionRequiredError(data, propertyName, type) {
724
- return data.type === ERROR_TYPES.EXPRESSION_REQUIRED
725
- && data.property === propertyName
726
- && (!type || is(data.node, type));
727
- }
728
-
729
- function isExpressionValueNotAllowedError(data, propertyName, type) {
730
- return data.type === ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED
731
- && data.property === propertyName
732
- && (!type || is(data.node, type));
733
- }
734
-
735
- function isElementPropertyValueDuplicated(data, propertyName, type) {
736
- return data.type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED
737
- && data.duplicatedProperty === propertyName
738
- && (!type || is(data.node, type));
739
- }
740
-
741
- function getBusinessObject(element) {
742
- return element.businessObject || element;
743
- }
744
-
745
- function isEmptyString(value) {
746
- return isString(value) && value.trim() === '';
747
- }
748
-
749
- function getNotSupportedMessage(property, allowedVersion) {
750
-
751
- if (allowedVersion) {
752
- return property ?
753
- `${ property } is only supported by Camunda ${ allowedVersion } or newer.` :
754
- `Only supported by Camunda ${ allowedVersion } or newer.`;
755
- }
756
-
757
- 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 (
213
+ isExtensionElementNotAllowedError(data, 'zeebe:UserTask') ||
214
+ isExtensionElementRequiredError(data, 'zeebe:UserTask')
215
+ ) {
216
+ return [ 'userTaskImplementation' ];
217
+ }
218
+
219
+ if (isExtensionElementNotAllowedError(data, 'zeebe:FormDefinition', 'bpmn:StartEvent')) {
220
+ return [ 'formType' ];
221
+ }
222
+
223
+
224
+ if (isPropertyError(data, 'conditionExpression', 'bpmn:SequenceFlow')) {
225
+ return [ 'conditionExpression' ];
226
+ }
227
+
228
+ if (isPropertyError(data, 'completionCondition', 'bpmn:MultiInstanceLoopCharacteristics')) {
229
+ return [ 'multiInstance-completionCondition' ];
230
+ }
231
+
232
+ if (isPropertyError(data, 'completionCondition', 'bpmn:AdHocSubProcess')) {
233
+ return [ 'completionCondition' ];
234
+ }
235
+
236
+ if (isPropertyError(data, 'cancelRemainingInstances', 'bpmn:AdHocSubProcess')) {
237
+ return [ 'cancelRemainingInstances' ];
238
+ }
239
+
240
+ if (TIMER_PROPERTIES.some(property =>
241
+ isOneOfPropertiesRequiredError(data, property, 'bpmn:TimerEventDefinition'))
242
+ ) {
243
+ return [ 'timerEventDefinitionType' ];
244
+ }
245
+
246
+ if (isExpressionRequiredError(data, 'timeCycle', 'bpmn:FormalExpression')
247
+ || isExpressionRequiredError(data, 'timeDate', 'bpmn:FormalExpression')
248
+ || isExpressionRequiredError(data, 'timeDuration', 'bpmn:FormalExpression')) {
249
+ return [ 'timerEventDefinitionValue' ];
250
+ }
251
+
252
+ if (isExpressionValueNotAllowedError(data, 'timeCycle', 'bpmn:FormalExpression')
253
+ || isExpressionValueNotAllowedError(data, 'timeDate', 'bpmn:FormalExpression')
254
+ || isExpressionValueNotAllowedError(data, 'timeDuration', 'bpmn:FormalExpression')) {
255
+ return [ 'timerEventDefinitionValue' ];
256
+ }
257
+
258
+ if (isPropertyError(data, 'timeCycle', 'bpmn:TimerEventDefinition')
259
+ || isPropertyError(data, 'timeDate', 'bpmn:TimerEventDefinition')
260
+ || isPropertyError(data, 'timeDuration', 'bpmn:TimerEventDefinition')) {
261
+ return [ 'timerEventDefinitionType' ];
262
+ }
263
+
264
+ const LIST_PROPERTIES = [
265
+ [ 'zeebe:Input', 'input' ],
266
+ [ 'zeebe:Output', 'output' ],
267
+ [ 'zeebe:Property', 'extensionProperty' ],
268
+ [ 'zeebe:Header', 'header' ]
269
+ ];
270
+
271
+ for (const [ type, prefix ] of LIST_PROPERTIES) {
272
+ if (isType(data, type)
273
+ && getPropertyName(data)) {
274
+
275
+ const index = path[ path.length - 2 ];
276
+
277
+ return [ `${ id }-${ prefix }-${ index }-${ getPropertyName(data) }` ];
278
+ }
279
+ }
280
+
281
+ if (isType(data, 'zeebe:LoopCharacteristics')) {
282
+ return [ `multiInstance-${getPropertyName(data)}` ];
283
+ }
284
+
285
+ if (isPropertyError(data, 'candidateUsers', 'zeebe:AssignmentDefinition')) {
286
+ return [ 'assignmentDefinitionCandidateUsers' ];
287
+ }
288
+
289
+ if (isPropertyError(data, 'historyTimeToLive', 'bpmn:Process')) {
290
+ return [ 'historyTimeToLive' ];
291
+ }
292
+
293
+ if (isExpressionValueNotAllowedError(data, 'dueDate', 'zeebe:TaskSchedule')) {
294
+ return [ 'taskScheduleDueDate' ];
295
+ }
296
+
297
+ if (isExpressionValueNotAllowedError(data, 'followUpDate', 'zeebe:TaskSchedule')) {
298
+ return [ 'taskScheduleFollowUpDate' ];
299
+ }
300
+
301
+ if (isExtensionElementNotAllowedError(data, 'zeebe:TaskSchedule', 'bpmn:UserTask')) {
302
+ const { extensionElement: taskSchedule } = data;
303
+
304
+ let ids = [];
305
+
306
+ if (taskSchedule.get('dueDate')) {
307
+ ids = [ ...ids, 'taskScheduleDueDate' ];
308
+ }
309
+
310
+ if (taskSchedule.get('followUpDate')) {
311
+ ids = [ ...ids, 'taskScheduleFollowUpDate' ];
312
+ }
313
+
314
+ return ids;
315
+ }
316
+
317
+ if (isExpressionValueNotAllowedError(data, 'priority', 'zeebe:PriorityDefinition')
318
+ || isExtensionElementNotAllowedError(data, 'zeebe:PriorityDefinition', 'bpmn:UserTask')) {
319
+ return [ 'priorityDefinitionPriority' ];
320
+ }
321
+
322
+ if (isPropertyError(data, 'propagateAllParentVariables', 'zeebe:CalledElement')) {
323
+ return [ 'propagateAllParentVariables' ];
324
+ }
325
+
326
+ if (isPropertyError(data, 'name', 'bpmn:LinkEventDefinition')
327
+ || isElementPropertyValueDuplicated(data, 'name', 'bpmn:LinkEventDefinition')) {
328
+ return [ 'linkName' ];
329
+ }
330
+
331
+ if (isPropertyError(data, 'waitForCompletion', 'bpmn:CompensateEventDefinition')) {
332
+ return [ 'waitForCompletion' ];
333
+ }
334
+
335
+ if (isPropertyError(data, 'type', 'zeebe:ExecutionListener')) {
336
+ const index = path[ path.length - 2 ];
337
+
338
+ return [ `${id}-executionListener-${index}-listenerType` ];
339
+ }
340
+
341
+ if (isPropertyValuesDuplicatedError(data, 'zeebe:ExecutionListeners')) {
342
+ const { properties, propertiesName } = data;
343
+
344
+ return properties.map(property => {
345
+ const index = data.node.get(propertiesName).indexOf(property);
346
+
347
+ return `${ id }-executionListener-${ index }-listenerType`;
348
+ });
349
+ }
350
+
351
+ if (isPropertyError(data, 'type', 'zeebe:TaskListener')) {
352
+ const index = path[ path.length - 2 ];
353
+
354
+ return [ `${id}-taskListener-${index}-listenerType` ];
355
+ }
356
+
357
+ if (isPropertyError(data, 'bindingType')) {
358
+ return [ 'bindingType' ];
359
+ }
360
+
361
+ if (isPropertyError(data, 'versionTag') || isExtensionElementNotAllowedError(data, 'zeebe:VersionTag')) {
362
+ return [ 'versionTag' ];
363
+ }
364
+
365
+ // (1) match dependent property errors first
366
+ if (isPropertyDependentRequiredError(data, 'outputCollection', 'zeebe:AdHoc')) {
367
+ return [ 'adHocOutputCollection' ];
368
+ }
369
+
370
+ if (isPropertyDependentRequiredError(data, 'outputElement', 'zeebe:AdHoc')) {
371
+ return [ 'adHocOutputElement' ];
372
+ }
373
+
374
+ // (2) match property errors second
375
+ if (isPropertyError(data, 'outputCollection', 'zeebe:AdHoc')) {
376
+ return [ 'adHocOutputCollection' ];
377
+ }
378
+
379
+ if (isPropertyError(data, 'outputElement', 'zeebe:AdHoc')) {
380
+ return [ 'adHocOutputElement' ];
381
+ }
382
+
383
+ return [];
384
+ }
385
+
386
+ export function getErrorMessage(id, report) {
387
+ const {
388
+ data = {},
389
+ executionPlatformVersion
390
+ } = report;
391
+
392
+ const {
393
+ type,
394
+ allowedVersion
395
+ } = data;
396
+
397
+ // adjust FEEL message
398
+ if (type === ERROR_TYPES.FEEL_EXPRESSION_INVALID) {
399
+ return 'Unparsable FEEL expression.';
400
+ }
401
+
402
+ if (type === ERROR_TYPES.EXPRESSION_NOT_ALLOWED) {
403
+ return 'Cannot be an expression.';
404
+ }
405
+
406
+ if (id === 'isExecutable') {
407
+ const { parentNode } = data;
408
+
409
+ if (parentNode && is(parentNode, 'bpmn:Participant')) {
410
+ return 'One process must be executable.';
411
+ } else {
412
+ return 'Process must be executable.';
413
+ }
414
+ }
415
+
416
+ if ([ 'businessRuleImplementation', 'scriptImplementation' ].includes(id)) {
417
+ return 'Implementation must be defined.';
418
+ }
419
+
420
+ if (id === 'errorRef') {
421
+ return 'Global error reference must be defined.';
422
+ }
423
+
424
+ if (id === 'escalationRef') {
425
+ return 'Global escalation reference must be defined.';
426
+ }
427
+
428
+ if (id === 'messageRef') {
429
+ return 'Global message reference must be defined.';
430
+ }
431
+
432
+ if (id === 'signalRef') {
433
+ return 'Global signal reference must be defined.';
434
+ }
435
+
436
+ if (id === 'decisionId') {
437
+ return 'Decision ID must be defined.';
438
+ }
439
+
440
+ if (id === 'scriptExpression') {
441
+ return 'FEEL expression must be defined.';
442
+ }
443
+
444
+ if (id === 'resultVariable') {
445
+ return 'Result variable must be defined.';
446
+ }
447
+
448
+ if (id === 'errorCode' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
449
+ return 'Code must be defined.';
450
+ }
451
+
452
+ if (id === 'escalationCode' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
453
+ return 'Code must be defined.';
454
+ }
455
+
456
+ if (id === 'messageName') {
457
+ return 'Name must be defined.';
458
+ }
459
+
460
+ if (id === 'signalName') {
461
+ return 'Name must be defined.';
462
+ }
463
+
464
+ if (id === 'multiInstance-inputCollection') {
465
+ return 'Input collection must be defined.';
466
+ }
467
+
468
+ if (id === 'multiInstance-outputCollection') {
469
+ return 'Output collection must be defined.';
470
+ }
471
+
472
+ if (id === 'multiInstance-outputElement') {
473
+ return 'Output element must be defined.';
474
+ }
475
+
476
+ if (id === 'completionCondition' && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
477
+ return getNotSupportedMessage('', allowedVersion);
478
+ }
479
+
480
+ if (id === 'cancelRemainingInstances' && type === ERROR_TYPES.PROPERTY_VALUE_NOT_ALLOWED) {
481
+ return 'Must be checked.';
482
+ }
483
+
484
+ if (id === 'targetProcessId') {
485
+ return 'Process ID must be defined.';
486
+ }
487
+
488
+ if (id === 'taskDefinitionType') {
489
+ return 'Type must be defined.';
490
+ }
491
+
492
+ if (id === 'timerEventDefinitionType' && type === ERROR_TYPES.PROPERTY_REQUIRED) {
493
+ return 'Type must be defined.';
494
+ }
495
+
496
+ if (id === 'messageSubscriptionCorrelationKey'
497
+ && [
498
+ ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
499
+ ERROR_TYPES.PROPERTY_REQUIRED
500
+ ].includes(type)) {
501
+ return 'Subscription correlation key must be defined.';
502
+ }
503
+
504
+ if (id === 'customFormKey') {
505
+ return 'Form key must be defined.';
506
+ }
507
+
508
+ if (id === 'formId') {
509
+ if (type === ERROR_TYPES.PROPERTY_REQUIRED) {
510
+ return 'Form ID must be defined.';
511
+ } else if (type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
512
+ return getNotSupportedMessage('Form ID', allowedVersion);
513
+ }
514
+ }
515
+
516
+ if (id === 'externalReference') {
517
+ return 'External reference must be defined.';
518
+ }
519
+
520
+ if (id === 'formConfiguration') {
521
+ return 'Form JSON configuration must be defined.';
522
+ }
523
+
524
+ if (/^.+-header-[0-9]+-key$/.test(id)) {
525
+ return 'Must be unique.';
526
+ }
527
+
528
+ if (/^.+-extensionProperty-[0-9]+-name$/.test(id)) {
529
+ return getNotSupportedMessage('', allowedVersion);
530
+ }
531
+
532
+ if (id === 'userTaskImplementation') {
533
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
534
+ return getNotSupportedMessage('', allowedVersion);
535
+ } else if (type === ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED) {
536
+ return getNotSupportedMessage('');
537
+ }
538
+ }
539
+
540
+ if (id === 'conditionExpression') {
541
+ return 'Condition expression must be defined.';
542
+ }
543
+
544
+ if (id === 'timerEventDefinitionType' && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
545
+ return getNotSupportedMessage('Type', allowedVersion);
546
+ }
547
+
548
+ if (id === 'timerEventDefinitionValue') {
549
+ if (type === ERROR_TYPES.EXPRESSION_REQUIRED) {
550
+ return 'Value must be defined.';
551
+ }
552
+
553
+ const { property } = data;
554
+
555
+ if (property === 'timeCycle') {
556
+ if (!greaterOrEqual(executionPlatformVersion, '8.1')) {
557
+ return 'Must be an expression, an ISO 8601 repeating interval, or a cron expression (cron only supported by Camunda 8.1 or newer).';
558
+ }
559
+
560
+ return 'Must be an expression, an ISO 8601 repeating interval, or a cron expression.';
561
+ }
562
+
563
+ if (property === 'timeDate') {
564
+ return 'Must be an expression, or an ISO 8601 date.';
565
+ }
566
+
567
+ if (property === 'timeDuration') {
568
+ return 'Must be an expression, or an ISO 8601 interval.';
569
+ }
570
+ }
571
+
572
+ if (id === 'assignmentDefinitionCandidateUsers') {
573
+ return getNotSupportedMessage('', allowedVersion);
574
+ }
575
+
576
+ if (id === 'taskScheduleDueDate') {
577
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
578
+ return getNotSupportedMessage('', allowedVersion);
579
+ } else {
580
+ return 'Must be an ISO 8601 date.';
581
+ }
582
+ }
583
+
584
+ if (id === 'taskScheduleFollowUpDate') {
585
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
586
+ return getNotSupportedMessage('', allowedVersion);
587
+ } else {
588
+ return 'Must be an ISO 8601 date.';
589
+ }
590
+ }
591
+
592
+ if (id === 'priorityDefinitionPriority') {
593
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
594
+ return getNotSupportedMessage('', allowedVersion);
595
+ } else {
596
+ return 'Must be an expression, or an integer between 0 and 100.';
597
+ }
598
+ }
599
+
600
+ if (id === 'propagateAllParentVariables') {
601
+ return getNotSupportedMessage('', allowedVersion);
602
+ }
603
+
604
+ if (id === 'linkName') {
605
+ if (type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED) {
606
+ return 'Must be unique.';
607
+ } else {
608
+ return 'Must be defined.';
609
+ }
610
+ }
611
+
612
+ if (id === 'waitForCompletion') {
613
+ return 'Must wait for completion.';
614
+ }
615
+
616
+ if (/^.+-executionListener-[0-9]+-listenerType$/.test(id)) {
617
+ if (type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED) {
618
+ return 'Must be unique.';
619
+ } else {
620
+ return 'Must be defined.';
621
+ }
622
+ }
623
+
624
+ if (/^.+-taskListener-[0-9]+-listenerType$/.test(id)) {
625
+ return 'Must be defined.';
626
+ }
627
+
628
+ if (/^.+-(?:input|output)-[0-9]+-source$/.test(id) && type === ERROR_TYPES.PROPERTY_REQUIRED) {
629
+ if (allowedVersion) {
630
+ return `Empty variable assignment is only supported by Camunda ${allowedVersion} or newer.`;
631
+ }
632
+ return 'Variable assignment must be defined.';
633
+ }
634
+
635
+ if (/^.+-(?:input|output)-[0-9]+-target$/.test(id) && type === ERROR_TYPES.PROPERTY_REQUIRED) {
636
+ return 'Variable name must be defined.';
637
+ }
638
+
639
+ if (id === 'bindingType') {
640
+ return getNotSupportedMessage('', allowedVersion);
641
+ }
642
+
643
+ if (id === 'versionTag') {
644
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
645
+ return getNotSupportedMessage('', allowedVersion);
646
+ } else {
647
+ return 'Version tag must be defined.';
648
+ }
649
+ }
650
+
651
+ if (isPropertyDependentRequiredError(data, 'outputCollection', 'zeebe:AdHoc')) {
652
+ return 'Output collection must be defined.';
653
+ }
654
+
655
+ if (isPropertyDependentRequiredError(data, 'outputElement', 'zeebe:AdHoc')) {
656
+ return 'Output element must be defined.';
657
+ }
658
+
659
+ if (isPropertyError(data, 'outputCollection', 'zeebe:AdHoc') && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
660
+ return getNotSupportedMessage('Output collection', allowedVersion);
661
+ }
662
+
663
+ if (isPropertyError(data, 'outputElement', 'zeebe:AdHoc') && type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
664
+ return getNotSupportedMessage('Output element', allowedVersion);
665
+ }
666
+ }
667
+
668
+ function isExtensionElementNotAllowedError(data, extensionElement, type) {
669
+ return data.type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED
670
+ && is(data.extensionElement, extensionElement)
671
+ && (!type || is(data.node, type));
672
+ }
673
+
674
+ function isExtensionElementRequiredError(data, requiredExtensionElement, type) {
675
+ return data.type === ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED
676
+ && (isArray(data.requiredExtensionElement) && data.requiredExtensionElement.includes(requiredExtensionElement)
677
+ || data.requiredExtensionElement === requiredExtensionElement)
678
+ && (!type || is(data.node, type));
679
+ }
680
+
681
+ function isPropertyDependentRequiredError(data, dependentRequiredProperty, type) {
682
+ return data.type === ERROR_TYPES.PROPERTY_DEPENDENT_REQUIRED
683
+ && data.dependentRequiredProperty === dependentRequiredProperty
684
+ && (!type || is(data.node, type));
685
+ }
686
+
687
+
688
+ function isPropertyError(data, property, type) {
689
+ return getPropertyName(data) === property
690
+ && (!type || is(data.node, type));
691
+ }
692
+
693
+ function getPropertyName(data) {
694
+ if (data.type === ERROR_TYPES.PROPERTY_REQUIRED) {
695
+ return data.requiredProperty;
696
+ }
697
+
698
+ return data.property;
699
+ }
700
+
701
+ function isType(data, type) {
702
+ return data.node && is(data.node, type);
703
+ }
704
+
705
+ function isOneOfPropertiesRequiredError(data, requiredProperty, type) {
706
+ return data.type === ERROR_TYPES.PROPERTY_REQUIRED
707
+ && (isArray(data.requiredProperty) && data.requiredProperty.includes(requiredProperty))
708
+ && (!type || is(data.node, type));
709
+ }
710
+
711
+ function isPropertyValueDuplicatedError(data, propertiesName, duplicatedProperty, type) {
712
+ return data.type === ERROR_TYPES.PROPERTY_VALUE_DUPLICATED
713
+ && data.propertiesName === propertiesName
714
+ && data.duplicatedProperty === duplicatedProperty
715
+ && (!type || is(data.node, type));
716
+ }
717
+
718
+ function isPropertyValuesDuplicatedError(data, type) {
719
+ return data.type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED
720
+ && (!type || is(data.node, type));
721
+ }
722
+
723
+ function isExpressionRequiredError(data, propertyName, type) {
724
+ return data.type === ERROR_TYPES.EXPRESSION_REQUIRED
725
+ && data.property === propertyName
726
+ && (!type || is(data.node, type));
727
+ }
728
+
729
+ function isExpressionValueNotAllowedError(data, propertyName, type) {
730
+ return data.type === ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED
731
+ && data.property === propertyName
732
+ && (!type || is(data.node, type));
733
+ }
734
+
735
+ function isElementPropertyValueDuplicated(data, propertyName, type) {
736
+ return data.type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED
737
+ && data.duplicatedProperty === propertyName
738
+ && (!type || is(data.node, type));
739
+ }
740
+
741
+ function getBusinessObject(element) {
742
+ return element.businessObject || element;
743
+ }
744
+
745
+ function isEmptyString(value) {
746
+ return isString(value) && value.trim() === '';
747
+ }
748
+
749
+ function getNotSupportedMessage(property, allowedVersion) {
750
+
751
+ if (allowedVersion) {
752
+ return property ?
753
+ `${ property } is only supported by Camunda ${ allowedVersion } or newer.` :
754
+ `Only supported by Camunda ${ allowedVersion } or newer.`;
755
+ }
756
+
757
+ return property ? `${ property } is not supported.` : 'Not supported.';
758
758
  }