@camunda/linting 3.28.0 → 3.29.1

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,801 +1,809 @@
1
- import { ERROR_TYPES } from 'bpmnlint-plugin-camunda-compat/rules/utils/element';
2
-
3
- import { is, isAny } from 'bpmnlint-utils';
4
-
5
- import {
6
- every,
7
- isArray,
8
- isString
9
- } from 'min-dash';
10
-
11
- import { getTypeString } from './types';
12
-
13
- import {
14
- greaterOrEqual,
15
- toSemverMinor
16
- } from './version';
17
-
18
- const TIMER_PROPERTIES = [
19
- 'timeCycle',
20
- 'timeDate',
21
- 'timeDuration'
22
- ];
23
-
24
- const TIMER_PROPERTY_LABELS = {
25
- timeCycle: 'Cycle',
26
- timeDate: 'Date',
27
- timeDuration: 'Duration'
28
- };
29
-
30
- const executionPlatformLabels = {
31
- 'Camunda Cloud': {
32
- 'default': 'Camunda',
33
- '1.0': 'Camunda 8 (Zeebe 1.0)',
34
- '1.1': 'Camunda 8 (Zeebe 1.1)',
35
- '1.2': 'Camunda 8 (Zeebe 1.2)',
36
- '1.3': 'Camunda 8 (Zeebe 1.3)'
37
- }
38
- };
39
-
40
- export function getExecutionPlatformLabel(executionPlatform, executionPlatformVersion) {
41
- const executionPlatformLabel = executionPlatformLabels[ executionPlatform ]
42
- && executionPlatformLabels[ executionPlatform ][ toSemverMinor(executionPlatformVersion) ];
43
-
44
- if (executionPlatformLabel) {
45
- return executionPlatformLabel;
46
- }
47
-
48
- if (executionPlatformLabels[ executionPlatform ]
49
- && executionPlatformLabels[ executionPlatform ][ 'default' ]) {
50
- executionPlatform = executionPlatformLabels[ executionPlatform ][ 'default' ];
51
- }
52
-
53
- return `${ executionPlatform } ${ toSemverMinor(executionPlatformVersion) }`;
54
- }
55
-
56
- function getIndefiniteArticle(type, uppercase = true) {
57
- if ([
58
- 'Ad',
59
- 'Error',
60
- 'Escalation',
61
- 'Event',
62
- 'Inclusive',
63
- 'Intermediate',
64
- 'Undefined'
65
- ].includes(type.split(' ')[ 0 ])) {
66
- return uppercase ? 'An' : 'an';
67
- }
68
-
69
- return uppercase ? 'A' : 'a';
70
- }
71
-
72
- export function getErrorMessage(report, executionPlatform, executionPlatformVersion, modeler = 'desktop') {
73
- const {
74
- data,
75
- message
76
- } = report;
77
-
78
- if (!data) {
79
- return message;
80
- }
81
-
82
- const { type } = data;
83
-
84
- if (type === ERROR_TYPES.CHILD_ELEMENT_TYPE_NOT_ALLOWED) {
85
- return getChildElementTypeNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
86
- }
87
-
88
- if (type === ERROR_TYPES.ELEMENT_COLLAPSED_NOT_ALLOWED) {
89
- return getElementCollapsedNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
90
- }
91
-
92
- if (type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED) {
93
- return getElementPropertyValueDuplicatedErrorMessage(report);
94
- }
95
-
96
- if (type === ERROR_TYPES.ELEMENT_TYPE_NOT_ALLOWED) {
97
- return getElementTypeNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
98
- }
99
-
100
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
101
- return getExtensionElementNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
102
- }
103
-
104
- if (type === ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED) {
105
- return getExtensionElementRequiredErrorMessage(report);
106
- }
107
-
108
- if (type === ERROR_TYPES.PROPERTY_DEPENDENT_REQUIRED) {
109
- return getPropertyDependentRequiredErrorMessage(report);
110
- }
111
-
112
- if (type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
113
- return getPropertyNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler);
114
- }
115
-
116
- if (type === ERROR_TYPES.PROPERTY_REQUIRED) {
117
- return getPropertyRequiredErrorMessage(report, executionPlatform, executionPlatformVersion);
118
- }
119
-
120
- if (type === ERROR_TYPES.PROPERTY_VALUE_DUPLICATED) {
121
- return getPropertyValueDuplicatedErrorMessage(report);
122
- }
123
-
124
- if (type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED) {
125
- return getPropertyValuesDuplicatedErrorMessage(report);
126
- }
127
-
128
- if (type == ERROR_TYPES.PROPERTY_VALUE_NOT_ALLOWED) {
129
- return getPropertyValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler);
130
- }
131
-
132
- if (type === ERROR_TYPES.PROPERTY_VALUE_REQUIRED) {
133
- return getPropertyValueRequiredErrorMessage(report, executionPlatform, executionPlatformVersion);
134
- }
135
-
136
- if (type === ERROR_TYPES.EXPRESSION_REQUIRED) {
137
- return getExpressionRequiredErrorMessage(report);
138
- }
139
-
140
- if (type === ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED) {
141
- return getExpressionValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
142
- }
143
-
144
- if (type === ERROR_TYPES.EXPRESSION_NOT_ALLOWED) {
145
- return getExpressionNotAllowedErrorMessage(report);
146
- }
147
-
148
- if (type === ERROR_TYPES.EVENT_BASED_GATEWAY_TARGET_NOT_ALLOWED) {
149
- return getEventBasedGatewayTargetNotAllowedErrorMessage(report);
150
- }
151
-
152
- if (type === ERROR_TYPES.SECRET_EXPRESSION_FORMAT_DEPRECATED) {
153
- return getSecretExpressionFormatDeprecatedErrorMessage(report);
154
- }
155
-
156
- if (type === ERROR_TYPES.LOOP_NOT_ALLOWED) {
157
- return getLoopNotAllowedErrorMessage(report);
158
- }
159
-
160
- return message;
161
- }
162
-
163
- function getChildElementTypeNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
164
- const { data } = report;
165
-
166
- const {
167
- allowedVersion,
168
- node,
169
- parent
170
- } = data;
171
-
172
- const typeString = getTypeString(node),
173
- parentTypeString = getTypeString(parent);
174
-
175
- return getSupportedMessage(
176
- `${ getIndefiniteArticle(typeString) } <${ typeString }> in ${ getIndefiniteArticle(parentTypeString, false) } <${ parentTypeString }>`,
177
- executionPlatform,
178
- executionPlatformVersion,
179
- allowedVersion
180
- );
181
- }
182
-
183
- function getElementCollapsedNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
184
- const {
185
- data,
186
- message
187
- } = report;
188
-
189
- const { allowedVersion, node } = data;
190
-
191
- const typeString = getTypeString(node);
192
-
193
- if (is(node, 'bpmn:SubProcess')) {
194
- return getSupportedMessage(`A collapsed <${typeString}>`, executionPlatform, executionPlatformVersion, allowedVersion);
195
- }
196
-
197
- return message;
198
- }
199
-
200
- function getElementTypeNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
201
- const { data } = report;
202
-
203
- const {
204
- allowedVersion,
205
- node
206
- } = data;
207
-
208
- const typeString = getTypeString(node);
209
-
210
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }>`, executionPlatform, executionPlatformVersion, allowedVersion);
211
- }
212
-
213
- function getPropertyValueDuplicatedErrorMessage(report) {
214
- const {
215
- data,
216
- message
217
- } = report;
218
-
219
- const {
220
- node,
221
- parentNode,
222
- duplicatedPropertyValue,
223
- properties
224
- } = data;
225
-
226
- const typeString = getTypeString(parentNode || node);
227
-
228
- if (is(node, 'zeebe:TaskHeaders') && every(properties, property => is(property, 'zeebe:Header'))) {
229
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with two or more <Headers> with the same <Key> (${ duplicatedPropertyValue }) is not supported`;
230
- }
231
-
232
- return message;
233
- }
234
-
235
- function getPropertyValuesDuplicatedErrorMessage(report) {
236
- const {
237
- data,
238
- message
239
- } = report;
240
-
241
- const {
242
- node,
243
- parentNode,
244
- duplicatedProperties,
245
- properties
246
- } = data;
247
-
248
- const {
249
- eventType,
250
- type
251
- } = duplicatedProperties;
252
-
253
- const typeString = getTypeString(parentNode || node);
254
-
255
- if (is(node, 'zeebe:ExecutionListeners') && every(properties, property => is(property, 'zeebe:ExecutionListener'))) {
256
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with two or more <Execution Listeners> with the same <Event Type> (${ eventType }) and <Type> (${ type }) is not supported`;
257
- }
258
-
259
- return message;
260
- }
261
-
262
- function getPropertyValueRequiredErrorMessage(report, executionPlatform, executionPlatformVersion) {
263
- const {
264
- data,
265
- message
266
- } = report;
267
-
268
- const {
269
- allowedVersion,
270
- node,
271
- property,
272
- parentNode
273
- } = data;
274
-
275
- if (is(node, 'bpmn:Process') && property === 'isExecutable') {
276
- if (parentNode && is(parentNode, 'bpmn:Participant')) {
277
- return 'One <Process> must be <Executable>';
278
- } else {
279
- return 'A <Process> must be <Executable>';
280
- }
281
- }
282
-
283
- const typeString = getTypeString(parentNode || node);
284
-
285
- if (is(node, 'bpmn:CompensateEventDefinition') && property === 'waitForCompletion') {
286
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Wait for completion> disabled`, executionPlatform, executionPlatformVersion, allowedVersion);
287
- }
288
-
289
- return message;
290
- }
291
-
292
- function getExtensionElementNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
293
- const {
294
- data,
295
- message
296
- } = report;
297
-
298
- const {
299
- allowedVersion,
300
- node,
301
- parentNode,
302
- extensionElement
303
- } = data;
304
-
305
- const typeString = getTypeString(parentNode || node);
306
-
307
- if (is(node, 'bpmn:BusinessRuleTask') && is(extensionElement, 'zeebe:CalledDecision')) {
308
- return getSupportedMessage('A <Business Rule Task> with <Implementation: DMN decision>', executionPlatform, executionPlatformVersion, allowedVersion);
309
- }
310
-
311
- if (is(extensionElement, 'zeebe:Properties')) {
312
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Extension properties>`, executionPlatform, executionPlatformVersion, allowedVersion);
313
- }
314
-
315
- if (is(extensionElement, 'zeebe:UserTask')) {
316
- return getSupportedMessage('A <User Task> with <Implementation: Zeebe user task>', executionPlatform, executionPlatformVersion, allowedVersion);
317
- }
318
-
319
- if (is(node, 'bpmn:ScriptTask') && is(extensionElement, 'zeebe:Script')) {
320
- return getSupportedMessage('A <Script Task> with <Implementation: FEEL expression>', executionPlatform, executionPlatformVersion, allowedVersion);
321
- }
322
-
323
- if (is(node, 'bpmn:UserTask') && is(extensionElement, 'zeebe:TaskSchedule')) {
324
- return getSupportedMessage('A <User Task> with <Due date> or <Follow up date>', executionPlatform, executionPlatformVersion, allowedVersion);
325
- }
326
-
327
- if (is(node, 'bpmn:UserTask') && is(extensionElement, 'zeebe:PriorityDefinition')) {
328
- return getSupportedMessage('A <User Task> with <Priority>', executionPlatform, executionPlatformVersion, allowedVersion);
329
- }
330
-
331
- if (is(node, 'bpmn:StartEvent') && is(extensionElement, 'zeebe:FormDefinition')) {
332
- return getSupportedMessage('A <Start Event> with <User Task Form>', executionPlatform, executionPlatformVersion, allowedVersion);
333
- }
334
-
335
- if (is(extensionElement, 'zeebe:ExecutionListeners')) {
336
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Execution listeners>`, executionPlatform, executionPlatformVersion, allowedVersion);
337
- }
338
-
339
- if (is(node, 'bpmn:Process') && is(extensionElement, 'zeebe:VersionTag')) {
340
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Version tag>`, executionPlatform, executionPlatformVersion, allowedVersion);
341
- }
342
-
343
- return message;
344
- }
345
-
346
- function getExtensionElementRequiredErrorMessage(report) {
347
- const {
348
- data,
349
- message
350
- } = report;
351
-
352
- const {
353
- node,
354
- parentNode,
355
- requiredExtensionElement
356
- } = data;
357
-
358
- const typeString = getTypeString(parentNode || node);
359
-
360
- if (requiredExtensionElement === 'zeebe:CalledElement') {
361
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Called element>`;
362
- }
363
-
364
- if (requiredExtensionElement === 'zeebe:LoopCharacteristics') {
365
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Multi-instance marker> must have a defined <Input collection>`;
366
- }
367
-
368
- if (requiredExtensionElement === 'zeebe:Subscription') {
369
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Message Reference> must have a defined <Subscription correlation key>`;
370
- }
371
-
372
- if (requiredExtensionElement === 'zeebe:TaskDefinition') {
373
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a <Task definition type>`;
374
- }
375
-
376
- if (isArray(requiredExtensionElement) && requiredExtensionElement.includes('zeebe:CalledDecision')) {
377
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Implementation>`;
378
- }
379
-
380
- if (isArray(requiredExtensionElement) && requiredExtensionElement.includes('zeebe:Script')) {
381
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Implementation>`;
382
- }
383
-
384
- if (requiredExtensionElement === 'zeebe:FormDefinition') {
385
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> should have a defined <Form>`;
386
- }
387
-
388
- if (requiredExtensionElement === 'zeebe:UserTask') {
389
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have <Implementation: Zeebe user task>`;
390
- }
391
-
392
- return message;
393
- }
394
-
395
- function getPropertyDependentRequiredErrorMessage(report) {
396
- const {
397
- data,
398
- message
399
- } = report;
400
-
401
- const {
402
- node,
403
- parentNode,
404
- property,
405
- dependentRequiredProperty
406
- } = data;
407
-
408
- const typeString = getTypeString(parentNode || node);
409
-
410
- if (is(node, 'zeebe:LoopCharacteristics') && property === 'outputCollection' && dependentRequiredProperty === 'outputElement') {
411
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>`;
412
- }
413
-
414
- if (is(node, 'zeebe:LoopCharacteristics') && property === 'outputElement' && dependentRequiredProperty === 'outputCollection') {
415
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>`;
416
- }
417
-
418
- return message;
419
- }
420
-
421
- function getPropertyNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler = 'desktop') {
422
- const {
423
- data,
424
- message
425
- } = report;
426
-
427
- const {
428
- allowedVersion,
429
- node,
430
- parentNode,
431
- property
432
- } = data;
433
-
434
- const typeString = getTypeString(parentNode || node);
435
-
436
- if (property === 'modelerTemplate') {
437
- if (modeler === 'desktop') {
438
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <Template ${ typeString }>`, executionPlatform, executionPlatformVersion, allowedVersion);
439
- } else if (modeler === 'web') {
440
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <Connector ${ typeString }>`, executionPlatform, executionPlatformVersion, allowedVersion);
441
- }
442
- }
443
-
444
- if (is(node, 'bpmn:InclusiveGateway') && property === 'incoming') {
445
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with more than one incoming <Sequence Flow> is not supported by ${ getExecutionPlatformLabel(executionPlatform, executionPlatformVersion) }`;
446
- }
447
-
448
- if (is(node, 'zeebe:AssignmentDefinition') && property === 'candidateUsers') {
449
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Candidate users>`, executionPlatform, executionPlatformVersion, allowedVersion);
450
- }
451
-
452
- if (is(node, 'bpmn:SequenceFlow') && property === 'conditionExpression') {
453
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Condition expression> is only supported if the source is an <Exclusive Gateway> or <Inclusive Gateway>`;
454
- }
455
-
456
- if (is(node, 'bpmn:TimerEventDefinition') && TIMER_PROPERTIES.includes(property)) {
457
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <${ TIMER_PROPERTY_LABELS[ property ] }>`, executionPlatform, executionPlatformVersion, allowedVersion);
458
- }
459
-
460
- if (is(node, 'zeebe:FormDefinition') && property === 'formId') {
461
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Camunda form (linked)>`, executionPlatform, executionPlatformVersion, allowedVersion);
462
- }
463
-
464
- return message;
465
- }
466
-
467
-
468
- function getPropertyRequiredErrorMessage(report, executionPlatform, executionPlatformVersion) {
469
- const {
470
- data,
471
- message
472
- } = report;
473
-
474
- const {
475
- allowedVersion,
476
- node,
477
- parentNode,
478
- requiredProperty
479
- } = data;
480
-
481
- const typeString = getTypeString(parentNode || node);
482
-
483
- if (parentNode && is(parentNode, 'bpmn:BusinessRuleTask') && is(node, 'zeebe:CalledDecision') && requiredProperty === 'decisionId') {
484
- return 'A <Business Rule Task> with <Implementation: DMN decision> must have a defined <Called decision ID>';
485
- }
486
-
487
- if (parentNode && is(parentNode, 'bpmn:BusinessRuleTask') && is(node, 'zeebe:CalledDecision') && requiredProperty === 'resultVariable') {
488
- return 'A <Business Rule Task> with <Implementation: DMN decision> must have a defined <Result variable>';
489
- }
490
-
491
- if (parentNode && is(parentNode, 'bpmn:ScriptTask') && is(node, 'zeebe:Script') && requiredProperty === 'expression') {
492
- return 'A <Script Task> with <Implementation: FEEL expression> must have a defined <FEEL expression>';
493
- }
494
-
495
- if (parentNode && is(parentNode, 'bpmn:ScriptTask') && is(node, 'zeebe:Script') && requiredProperty === 'resultVariable') {
496
- return 'A <Script Task> with <Implementation: FEEL expression> must have a defined <Result variable>';
497
- }
498
-
499
- if (parentNode && isAny(parentNode, [ 'bpmn:BusinessRuleTask', 'bpmn:ScriptTask' ]) && is(node, 'zeebe:TaskDefinition') && requiredProperty === 'type') {
500
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Implementation: Job worker> must have a defined <Task definition type>`;
501
- }
502
-
503
- if (is(node, 'zeebe:CalledElement') && requiredProperty === 'processId') {
504
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Called element>`;
505
- }
506
-
507
- if (is(node, 'bpmn:Error') && requiredProperty === 'errorCode') {
508
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Error Reference> must have a defined <Error code>`;
509
- }
510
-
511
- if (is(node, 'bpmn:Escalation') && requiredProperty === 'escalationCode') {
512
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Escalation Reference> must have a defined <Escalation code>`;
513
- }
514
-
515
- if (is(node, 'zeebe:LoopCharacteristics') && requiredProperty === 'inputCollection') {
516
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Multi-instance marker> must have a defined <Input collection>`;
517
- }
518
-
519
- if (is(node, 'bpmn:Message') && requiredProperty === 'name') {
520
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Message Reference> must have a defined <Name>`;
521
- }
522
-
523
- if (is(node, 'bpmn:Signal') && requiredProperty === 'name') {
524
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Signal Reference> must have a defined <Name>`;
525
- }
526
-
527
- if (is(node, 'zeebe:Subscription') && requiredProperty === 'correlationKey') {
528
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Message Reference> must have a defined <Subscription correlation key>`;
529
- }
530
-
531
- if (is(node, 'zeebe:TaskDefinition') && requiredProperty === 'type') {
532
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Implementation: Job worker> must have a defined <Task definition type>`;
533
- }
534
-
535
- if (is(node, 'zeebe:ExecutionListener') && requiredProperty === 'type') {
536
- return 'An <Execution Listener> must have a defined <Type>';
537
- }
538
-
539
- if (requiredProperty === 'errorRef') {
540
-
541
- if (parentNode && is(parentNode, 'bpmn:CatchEvent')) {
542
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> without defined <Error Reference>`, executionPlatform, executionPlatformVersion, allowedVersion);
543
- } else if (parentNode && is(parentNode, 'bpmn:ThrowEvent')) {
544
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Error Reference>`;
545
- }
546
-
547
- }
548
-
549
- if (requiredProperty === 'messageRef') {
550
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Message Reference>`;
551
- }
552
-
553
- if (requiredProperty === 'signalRef') {
554
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Signal Reference>`;
555
- }
556
-
557
- if (is(node, 'zeebe:FormDefinition')
558
- && (
559
- requiredProperty === 'formKey'
560
- || (isArray(requiredProperty) && requiredProperty.includes('formKey') && isEmptyString(node.get('formKey')))
561
- )) {
562
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Custom form key> must have a defined <Form key>`;
563
- }
564
-
565
- // Zeebe User Task
566
- if (is(node, 'zeebe:FormDefinition') && isZeebeUserTask(parentNode)) {
567
- if (isEmptyString(node.get('externalReference'))) {
568
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: External reference> must have a defined <External reference>`;
569
- } else if (isEmptyString(node.get('formId'))) {
570
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Camunda Form> must have a defined <Form ID>`;
571
- }
572
- }
573
-
574
- if (is(node, 'zeebe:FormDefinition') && isArray(requiredProperty) && requiredProperty.includes('formId') && isEmptyString(node.get('formId'))) {
575
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Camunda form (linked)> must have a defined <Form ID>`;
576
- }
577
-
578
- if (is(node, 'zeebe:UserTaskForm') && requiredProperty === 'body') {
579
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Camunda form (embedded)> must have a defined <Form JSON configuration>`;
580
- }
581
-
582
- if (is(node, 'bpmn:SequenceFlow') && requiredProperty === 'conditionExpression') {
583
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Condition expression> or be the default <Sequence Flow>`;
584
- }
585
-
586
- if (is(node, 'bpmn:TimerEventDefinition')
587
- && isArray(requiredProperty)
588
- && TIMER_PROPERTIES.some(property => requiredProperty.includes(property))
589
- ) {
590
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Timer type>`;
591
- }
592
-
593
- if (is(node, 'bpmn:Process') && requiredProperty === 'historyTimeToLive') {
594
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <History time to live>`;
595
- }
596
-
597
- if (is(node, 'bpmn:LinkEventDefinition') && requiredProperty === 'name') {
598
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Name>`;
599
- }
600
-
601
- if (isAny(node, [
602
- 'zeebe:CalledDecision',
603
- 'zeebe:CalledElement',
604
- 'zeebe:FormDefinition'
605
- ]) && requiredProperty === 'versionTag') {
606
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Binding: version tag> must have a defined <Version tag>`;
607
- }
608
-
609
- return message;
610
- }
611
-
612
- function getExpressionRequiredErrorMessage(report) {
613
- const {
614
- data,
615
- message
616
- } = report;
617
-
618
- const {
619
- node,
620
- parentNode,
621
- property
622
- } = data;
623
-
624
- const typeString = getTypeString(parentNode || node);
625
-
626
- if (is(node, 'bpmn:FormalExpression') && TIMER_PROPERTIES.includes(property)) {
627
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Timer value>`;
628
- }
629
-
630
- return message;
631
- }
632
-
633
- function getExpressionValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
634
- const {
635
- data,
636
- message
637
- } = report;
638
-
639
- const {
640
- node,
641
- parentNode,
642
- property
643
- } = data;
644
-
645
- const typeString = getTypeString(parentNode || node);
646
-
647
- if (is(node, 'bpmn:FormalExpression') && property === 'timeCycle') {
648
- if (!greaterOrEqual(executionPlatformVersion, '8.1')) {
649
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Time cycle> must be an expression, an ISO 8601 repeating interval, or a cron expression (cron only supported by Camunda 8.1 or newer)`;
650
- } else {
651
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Time cycle> must be an expression, an ISO 8601 repeating interval, or a cron expression`;
652
- }
653
- }
654
-
655
- if (is(node, 'bpmn:FormalExpression') && property === 'timeDate') {
656
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Time date> must be an expression, or an ISO 8601 date`;
657
- }
658
-
659
- if (is(node, 'bpmn:FormalExpression') && property === 'timeDuration') {
660
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Time duration> must be an expression, or an ISO 8601 interval`;
661
- }
662
-
663
- if (is(node, 'zeebe:TaskSchedule') && property === 'dueDate') {
664
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Due date> must be an ISO 8601 date`;
665
- }
666
-
667
- if (is(node, 'zeebe:TaskSchedule') && property === 'followUpDate') {
668
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Follow up date> must be an ISO 8601 date`;
669
- }
670
-
671
- if (is(node, 'zeebe:PriorityDefinition') && property === 'priority') {
672
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Priority> must be an expression, or an integer between 0 and 100`;
673
- }
674
-
675
- return message;
676
- }
677
-
678
- function getSupportedMessage(prefix, executionPlatform, executionPlatformVersion, allowedVersion) {
679
- if (allowedVersion) {
680
- return `${ prefix } is only supported by ${ getExecutionPlatformLabel(executionPlatform, allowedVersion) } or newer`;
681
- }
682
-
683
- return `${ prefix } is not supported by ${ getExecutionPlatformLabel(executionPlatform, executionPlatformVersion) }`;
684
- }
685
-
686
- function getExpressionNotAllowedErrorMessage(report) {
687
- const {
688
- data
689
- } = report;
690
-
691
- const {
692
- node,
693
- parentNode,
694
- property
695
- } = data;
696
-
697
- if (is(node, 'bpmn:Escalation') && property === 'escalationCode' && is(parentNode, 'bpmn:CatchEvent')) {
698
- return 'Escalation code used in a catch event must be a static value';
699
- } else if (is(node, 'bpmn:Error') && property === 'errorCode' && is(parentNode, 'bpmn:CatchEvent')) {
700
- return 'Error code used in a catch event must be a static value';
701
- }
702
-
703
- return report.message;
704
- }
705
-
706
- function getEventBasedGatewayTargetNotAllowedErrorMessage(report) {
707
- const { data } = report;
708
-
709
- const { node } = data;
710
-
711
- if (is(node, 'bpmn:ReceiveTask')) {
712
- return 'A <Receive Task> cannot be the target of an <Event-Based Gateway>';
713
- }
714
-
715
- return report.message;
716
- }
717
-
718
- function getPropertyValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler = 'desktop') {
719
- const {
720
- data,
721
- message
722
- } = report;
723
-
724
- const {
725
- allowedVersion,
726
- node,
727
- parentNode,
728
- property
729
- } = data;
730
-
731
- const typeString = getTypeString(parentNode || node);
732
-
733
- if (is(node, 'zeebe:CalledElement') && property === 'propagateAllParentVariables') {
734
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Propagate all variables> disabled`, executionPlatform, executionPlatformVersion, allowedVersion);
735
- }
736
-
737
- if (isAny(node, [
738
- 'zeebe:CalledDecision',
739
- 'zeebe:CalledElement',
740
- 'zeebe:FormDefinition'
741
- ]) && property === 'bindingType') {
742
- const bindingType = node.get('bindingType');
743
-
744
- let bindingTypeString = bindingType;
745
-
746
- if (bindingType === 'versionTag') {
747
- bindingTypeString = 'version tag';
748
- }
749
-
750
- return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Binding: ${ bindingTypeString }>`, executionPlatform, executionPlatformVersion, allowedVersion);
751
- }
752
-
753
- return message;
754
- }
755
-
756
- function getSecretExpressionFormatDeprecatedErrorMessage(report) {
757
- const { data } = report;
758
-
759
- const { property } = data;
760
-
761
- return `Property <${ property }> uses deprecated secret expression format secrets.SECRET, use {{secrets.SECRET}} instead`;
762
- }
763
-
764
- function getElementPropertyValueDuplicatedErrorMessage(report) {
765
- const {
766
- data,
767
- message
768
- } = report;
769
-
770
- const {
771
- node,
772
- parentNode,
773
- duplicatedProperty
774
- } = data;
775
-
776
- const typeString = getTypeString(parentNode || node);
777
-
778
- if (is(node, 'bpmn:LinkEventDefinition') && duplicatedProperty === 'name') {
779
- return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a unique <Name>`;
780
- }
781
-
782
- return message;
783
- }
784
-
785
- function getLoopNotAllowedErrorMessage(report) {
786
- const { data } = report;
787
-
788
- const { elements } = data;
789
-
790
- return `A <Process> is not allowed to contain a straight-through processing loop: ${ elements.map(element => `<${ element }>`).join(', ') }`;
791
- }
792
-
793
- function isEmptyString(value) {
794
- return isString(value) && value.trim() === '';
795
- }
796
-
797
- function isZeebeUserTask(node) {
798
- return node.get('extensionElements').get('values').some(extensionElement => {
799
- return is(extensionElement, 'zeebe:UserTask');
800
- });
801
- }
1
+ import { ERROR_TYPES } from 'bpmnlint-plugin-camunda-compat/rules/utils/element';
2
+
3
+ import { is, isAny } from 'bpmnlint-utils';
4
+
5
+ import {
6
+ every,
7
+ isArray,
8
+ isString
9
+ } from 'min-dash';
10
+
11
+ import { getTypeString } from './types';
12
+
13
+ import {
14
+ greaterOrEqual,
15
+ toSemverMinor
16
+ } from './version';
17
+
18
+ const TIMER_PROPERTIES = [
19
+ 'timeCycle',
20
+ 'timeDate',
21
+ 'timeDuration'
22
+ ];
23
+
24
+ const TIMER_PROPERTY_LABELS = {
25
+ timeCycle: 'Cycle',
26
+ timeDate: 'Date',
27
+ timeDuration: 'Duration'
28
+ };
29
+
30
+ const executionPlatformLabels = {
31
+ 'Camunda Cloud': {
32
+ 'default': 'Camunda',
33
+ '1.0': 'Camunda 8 (Zeebe 1.0)',
34
+ '1.1': 'Camunda 8 (Zeebe 1.1)',
35
+ '1.2': 'Camunda 8 (Zeebe 1.2)',
36
+ '1.3': 'Camunda 8 (Zeebe 1.3)'
37
+ }
38
+ };
39
+
40
+ export function getExecutionPlatformLabel(executionPlatform, executionPlatformVersion) {
41
+ const executionPlatformLabel = executionPlatformLabels[ executionPlatform ]
42
+ && executionPlatformLabels[ executionPlatform ][ toSemverMinor(executionPlatformVersion) ];
43
+
44
+ if (executionPlatformLabel) {
45
+ return executionPlatformLabel;
46
+ }
47
+
48
+ if (executionPlatformLabels[ executionPlatform ]
49
+ && executionPlatformLabels[ executionPlatform ][ 'default' ]) {
50
+ executionPlatform = executionPlatformLabels[ executionPlatform ][ 'default' ];
51
+ }
52
+
53
+ return `${ executionPlatform } ${ toSemverMinor(executionPlatformVersion) }`;
54
+ }
55
+
56
+ function getIndefiniteArticle(type, uppercase = true) {
57
+ if ([
58
+ 'Ad',
59
+ 'Error',
60
+ 'Escalation',
61
+ 'Event',
62
+ 'Inclusive',
63
+ 'Intermediate',
64
+ 'Undefined'
65
+ ].includes(type.split(' ')[ 0 ])) {
66
+ return uppercase ? 'An' : 'an';
67
+ }
68
+
69
+ return uppercase ? 'A' : 'a';
70
+ }
71
+
72
+ export function getErrorMessage(report, executionPlatform, executionPlatformVersion, modeler = 'desktop') {
73
+ const {
74
+ data,
75
+ message
76
+ } = report;
77
+
78
+ if (!data) {
79
+ return message;
80
+ }
81
+
82
+ const { type } = data;
83
+
84
+ if (type === ERROR_TYPES.CHILD_ELEMENT_TYPE_NOT_ALLOWED) {
85
+ return getChildElementTypeNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
86
+ }
87
+
88
+ if (type === ERROR_TYPES.ELEMENT_COLLAPSED_NOT_ALLOWED) {
89
+ return getElementCollapsedNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
90
+ }
91
+
92
+ if (type === ERROR_TYPES.ELEMENT_PROPERTY_VALUE_DUPLICATED) {
93
+ return getElementPropertyValueDuplicatedErrorMessage(report);
94
+ }
95
+
96
+ if (type === ERROR_TYPES.ELEMENT_TYPE_NOT_ALLOWED) {
97
+ return getElementTypeNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
98
+ }
99
+
100
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED) {
101
+ return getExtensionElementNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
102
+ }
103
+
104
+ if (type === ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED) {
105
+ return getExtensionElementRequiredErrorMessage(report);
106
+ }
107
+
108
+ if (type === ERROR_TYPES.PROPERTY_DEPENDENT_REQUIRED) {
109
+ return getPropertyDependentRequiredErrorMessage(report);
110
+ }
111
+
112
+ if (type === ERROR_TYPES.PROPERTY_NOT_ALLOWED) {
113
+ return getPropertyNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler);
114
+ }
115
+
116
+ if (type === ERROR_TYPES.PROPERTY_REQUIRED) {
117
+ return getPropertyRequiredErrorMessage(report, executionPlatform, executionPlatformVersion);
118
+ }
119
+
120
+ if (type === ERROR_TYPES.PROPERTY_VALUE_DUPLICATED) {
121
+ return getPropertyValueDuplicatedErrorMessage(report);
122
+ }
123
+
124
+ if (type === ERROR_TYPES.PROPERTY_VALUES_DUPLICATED) {
125
+ return getPropertyValuesDuplicatedErrorMessage(report);
126
+ }
127
+
128
+ if (type == ERROR_TYPES.PROPERTY_VALUE_NOT_ALLOWED) {
129
+ return getPropertyValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler);
130
+ }
131
+
132
+ if (type === ERROR_TYPES.PROPERTY_VALUE_REQUIRED) {
133
+ return getPropertyValueRequiredErrorMessage(report, executionPlatform, executionPlatformVersion);
134
+ }
135
+
136
+ if (type === ERROR_TYPES.EXPRESSION_REQUIRED) {
137
+ return getExpressionRequiredErrorMessage(report);
138
+ }
139
+
140
+ if (type === ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED) {
141
+ return getExpressionValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion);
142
+ }
143
+
144
+ if (type === ERROR_TYPES.EXPRESSION_NOT_ALLOWED) {
145
+ return getExpressionNotAllowedErrorMessage(report);
146
+ }
147
+
148
+ if (type === ERROR_TYPES.EVENT_BASED_GATEWAY_TARGET_NOT_ALLOWED) {
149
+ return getEventBasedGatewayTargetNotAllowedErrorMessage(report);
150
+ }
151
+
152
+ if (type === ERROR_TYPES.SECRET_EXPRESSION_FORMAT_DEPRECATED) {
153
+ return getSecretExpressionFormatDeprecatedErrorMessage(report);
154
+ }
155
+
156
+ if (type === ERROR_TYPES.LOOP_NOT_ALLOWED) {
157
+ return getLoopNotAllowedErrorMessage(report);
158
+ }
159
+
160
+ return message;
161
+ }
162
+
163
+ function getChildElementTypeNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
164
+ const { data } = report;
165
+
166
+ const {
167
+ allowedVersion,
168
+ node,
169
+ parent
170
+ } = data;
171
+
172
+ const typeString = getTypeString(node),
173
+ parentTypeString = getTypeString(parent);
174
+
175
+ return getSupportedMessage(
176
+ `${ getIndefiniteArticle(typeString) } <${ typeString }> in ${ getIndefiniteArticle(parentTypeString, false) } <${ parentTypeString }>`,
177
+ executionPlatform,
178
+ executionPlatformVersion,
179
+ allowedVersion
180
+ );
181
+ }
182
+
183
+ function getElementCollapsedNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
184
+ const {
185
+ data,
186
+ message
187
+ } = report;
188
+
189
+ const { allowedVersion, node } = data;
190
+
191
+ const typeString = getTypeString(node);
192
+
193
+ if (is(node, 'bpmn:SubProcess')) {
194
+ return getSupportedMessage(`A collapsed <${typeString}>`, executionPlatform, executionPlatformVersion, allowedVersion);
195
+ }
196
+
197
+ return message;
198
+ }
199
+
200
+ function getElementTypeNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
201
+ const { data } = report;
202
+
203
+ const {
204
+ allowedVersion,
205
+ node
206
+ } = data;
207
+
208
+ const typeString = getTypeString(node);
209
+
210
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }>`, executionPlatform, executionPlatformVersion, allowedVersion);
211
+ }
212
+
213
+ function getPropertyValueDuplicatedErrorMessage(report) {
214
+ const {
215
+ data,
216
+ message
217
+ } = report;
218
+
219
+ const {
220
+ node,
221
+ parentNode,
222
+ duplicatedPropertyValue,
223
+ properties
224
+ } = data;
225
+
226
+ const typeString = getTypeString(parentNode || node);
227
+
228
+ if (is(node, 'zeebe:TaskHeaders') && every(properties, property => is(property, 'zeebe:Header'))) {
229
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with two or more <Headers> with the same <Key> (${ duplicatedPropertyValue }) is not supported`;
230
+ }
231
+
232
+ return message;
233
+ }
234
+
235
+ function getPropertyValuesDuplicatedErrorMessage(report) {
236
+ const {
237
+ data,
238
+ message
239
+ } = report;
240
+
241
+ const {
242
+ node,
243
+ parentNode,
244
+ duplicatedProperties,
245
+ properties
246
+ } = data;
247
+
248
+ const {
249
+ eventType,
250
+ type
251
+ } = duplicatedProperties;
252
+
253
+ const typeString = getTypeString(parentNode || node);
254
+
255
+ if (is(node, 'zeebe:ExecutionListeners') && every(properties, property => is(property, 'zeebe:ExecutionListener'))) {
256
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with two or more <Execution Listeners> with the same <Event Type> (${ eventType }) and <Type> (${ type }) is not supported`;
257
+ }
258
+
259
+ return message;
260
+ }
261
+
262
+ function getPropertyValueRequiredErrorMessage(report, executionPlatform, executionPlatformVersion) {
263
+ const {
264
+ data,
265
+ message
266
+ } = report;
267
+
268
+ const {
269
+ allowedVersion,
270
+ node,
271
+ property,
272
+ parentNode
273
+ } = data;
274
+
275
+ if (is(node, 'bpmn:Process') && property === 'isExecutable') {
276
+ if (parentNode && is(parentNode, 'bpmn:Participant')) {
277
+ return 'One <Process> must be <Executable>';
278
+ } else {
279
+ return 'A <Process> must be <Executable>';
280
+ }
281
+ }
282
+
283
+ const typeString = getTypeString(parentNode || node);
284
+
285
+ if (is(node, 'bpmn:CompensateEventDefinition') && property === 'waitForCompletion') {
286
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Wait for completion> disabled`, executionPlatform, executionPlatformVersion, allowedVersion);
287
+ }
288
+
289
+ return message;
290
+ }
291
+
292
+ function getExtensionElementNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
293
+ const {
294
+ data,
295
+ message
296
+ } = report;
297
+
298
+ const {
299
+ allowedVersion,
300
+ node,
301
+ parentNode,
302
+ extensionElement
303
+ } = data;
304
+
305
+ const typeString = getTypeString(parentNode || node);
306
+
307
+ if (is(node, 'bpmn:BusinessRuleTask') && is(extensionElement, 'zeebe:CalledDecision')) {
308
+ return getSupportedMessage('A <Business Rule Task> with <Implementation: DMN decision>', executionPlatform, executionPlatformVersion, allowedVersion);
309
+ }
310
+
311
+ if (is(extensionElement, 'zeebe:Properties')) {
312
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Extension properties>`, executionPlatform, executionPlatformVersion, allowedVersion);
313
+ }
314
+
315
+ if (is(extensionElement, 'zeebe:UserTask')) {
316
+ return getSupportedMessage('A <User Task> with <Implementation: Zeebe user task>', executionPlatform, executionPlatformVersion, allowedVersion);
317
+ }
318
+
319
+ if (is(node, 'bpmn:ScriptTask') && is(extensionElement, 'zeebe:Script')) {
320
+ return getSupportedMessage('A <Script Task> with <Implementation: FEEL expression>', executionPlatform, executionPlatformVersion, allowedVersion);
321
+ }
322
+
323
+ if (is(node, 'bpmn:UserTask') && is(extensionElement, 'zeebe:TaskSchedule')) {
324
+ return getSupportedMessage('A <User Task> with <Due date> or <Follow up date>', executionPlatform, executionPlatformVersion, allowedVersion);
325
+ }
326
+
327
+ if (is(node, 'bpmn:UserTask') && is(extensionElement, 'zeebe:PriorityDefinition')) {
328
+ return getSupportedMessage('A <User Task> with <Priority>', executionPlatform, executionPlatformVersion, allowedVersion);
329
+ }
330
+
331
+ if (is(node, 'bpmn:StartEvent') && is(extensionElement, 'zeebe:FormDefinition')) {
332
+ return getSupportedMessage('A <Start Event> with <User Task Form>', executionPlatform, executionPlatformVersion, allowedVersion);
333
+ }
334
+
335
+ if (is(extensionElement, 'zeebe:ExecutionListeners')) {
336
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Execution listeners>`, executionPlatform, executionPlatformVersion, allowedVersion);
337
+ }
338
+
339
+ if (is(extensionElement, 'zeebe:TaskListeners')) {
340
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Task listeners>`, executionPlatform, executionPlatformVersion, allowedVersion);
341
+ }
342
+
343
+ if (is(node, 'bpmn:Process') && is(extensionElement, 'zeebe:VersionTag')) {
344
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Version tag>`, executionPlatform, executionPlatformVersion, allowedVersion);
345
+ }
346
+
347
+ return message;
348
+ }
349
+
350
+ function getExtensionElementRequiredErrorMessage(report) {
351
+ const {
352
+ data,
353
+ message
354
+ } = report;
355
+
356
+ const {
357
+ node,
358
+ parentNode,
359
+ requiredExtensionElement
360
+ } = data;
361
+
362
+ const typeString = getTypeString(parentNode || node);
363
+
364
+ if (requiredExtensionElement === 'zeebe:CalledElement') {
365
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Called element>`;
366
+ }
367
+
368
+ if (requiredExtensionElement === 'zeebe:LoopCharacteristics') {
369
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Multi-instance marker> must have a defined <Input collection>`;
370
+ }
371
+
372
+ if (requiredExtensionElement === 'zeebe:Subscription') {
373
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Message Reference> must have a defined <Subscription correlation key>`;
374
+ }
375
+
376
+ if (requiredExtensionElement === 'zeebe:TaskDefinition') {
377
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a <Task definition type>`;
378
+ }
379
+
380
+ if (isArray(requiredExtensionElement) && requiredExtensionElement.includes('zeebe:CalledDecision')) {
381
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Implementation>`;
382
+ }
383
+
384
+ if (isArray(requiredExtensionElement) && requiredExtensionElement.includes('zeebe:Script')) {
385
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Implementation>`;
386
+ }
387
+
388
+ if (requiredExtensionElement === 'zeebe:FormDefinition') {
389
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> should have a defined <Form>`;
390
+ }
391
+
392
+ if (requiredExtensionElement === 'zeebe:UserTask') {
393
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have <Implementation: Zeebe user task>`;
394
+ }
395
+
396
+ return message;
397
+ }
398
+
399
+ function getPropertyDependentRequiredErrorMessage(report) {
400
+ const {
401
+ data,
402
+ message
403
+ } = report;
404
+
405
+ const {
406
+ node,
407
+ parentNode,
408
+ property,
409
+ dependentRequiredProperty
410
+ } = data;
411
+
412
+ const typeString = getTypeString(parentNode || node);
413
+
414
+ if (is(node, 'zeebe:LoopCharacteristics') && property === 'outputCollection' && dependentRequiredProperty === 'outputElement') {
415
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>`;
416
+ }
417
+
418
+ if (is(node, 'zeebe:LoopCharacteristics') && property === 'outputElement' && dependentRequiredProperty === 'outputCollection') {
419
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>`;
420
+ }
421
+
422
+ return message;
423
+ }
424
+
425
+ function getPropertyNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler = 'desktop') {
426
+ const {
427
+ data,
428
+ message
429
+ } = report;
430
+
431
+ const {
432
+ allowedVersion,
433
+ node,
434
+ parentNode,
435
+ property
436
+ } = data;
437
+
438
+ const typeString = getTypeString(parentNode || node);
439
+
440
+ if (property === 'modelerTemplate') {
441
+ if (modeler === 'desktop') {
442
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <Template ${ typeString }>`, executionPlatform, executionPlatformVersion, allowedVersion);
443
+ } else if (modeler === 'web') {
444
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <Connector ${ typeString }>`, executionPlatform, executionPlatformVersion, allowedVersion);
445
+ }
446
+ }
447
+
448
+ if (is(node, 'bpmn:InclusiveGateway') && property === 'incoming') {
449
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with more than one incoming <Sequence Flow> is not supported by ${ getExecutionPlatformLabel(executionPlatform, executionPlatformVersion) }`;
450
+ }
451
+
452
+ if (is(node, 'zeebe:AssignmentDefinition') && property === 'candidateUsers') {
453
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Candidate users>`, executionPlatform, executionPlatformVersion, allowedVersion);
454
+ }
455
+
456
+ if (is(node, 'bpmn:SequenceFlow') && property === 'conditionExpression') {
457
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Condition expression> is only supported if the source is an <Exclusive Gateway> or <Inclusive Gateway>`;
458
+ }
459
+
460
+ if (is(node, 'bpmn:TimerEventDefinition') && TIMER_PROPERTIES.includes(property)) {
461
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <${ TIMER_PROPERTY_LABELS[ property ] }>`, executionPlatform, executionPlatformVersion, allowedVersion);
462
+ }
463
+
464
+ if (is(node, 'zeebe:FormDefinition') && property === 'formId') {
465
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Camunda form (linked)>`, executionPlatform, executionPlatformVersion, allowedVersion);
466
+ }
467
+
468
+ return message;
469
+ }
470
+
471
+
472
+ function getPropertyRequiredErrorMessage(report, executionPlatform, executionPlatformVersion) {
473
+ const {
474
+ data,
475
+ message
476
+ } = report;
477
+
478
+ const {
479
+ allowedVersion,
480
+ node,
481
+ parentNode,
482
+ requiredProperty
483
+ } = data;
484
+
485
+ const typeString = getTypeString(parentNode || node);
486
+
487
+ if (parentNode && is(parentNode, 'bpmn:BusinessRuleTask') && is(node, 'zeebe:CalledDecision') && requiredProperty === 'decisionId') {
488
+ return 'A <Business Rule Task> with <Implementation: DMN decision> must have a defined <Called decision ID>';
489
+ }
490
+
491
+ if (parentNode && is(parentNode, 'bpmn:BusinessRuleTask') && is(node, 'zeebe:CalledDecision') && requiredProperty === 'resultVariable') {
492
+ return 'A <Business Rule Task> with <Implementation: DMN decision> must have a defined <Result variable>';
493
+ }
494
+
495
+ if (parentNode && is(parentNode, 'bpmn:ScriptTask') && is(node, 'zeebe:Script') && requiredProperty === 'expression') {
496
+ return 'A <Script Task> with <Implementation: FEEL expression> must have a defined <FEEL expression>';
497
+ }
498
+
499
+ if (parentNode && is(parentNode, 'bpmn:ScriptTask') && is(node, 'zeebe:Script') && requiredProperty === 'resultVariable') {
500
+ return 'A <Script Task> with <Implementation: FEEL expression> must have a defined <Result variable>';
501
+ }
502
+
503
+ if (parentNode && isAny(parentNode, [ 'bpmn:BusinessRuleTask', 'bpmn:ScriptTask' ]) && is(node, 'zeebe:TaskDefinition') && requiredProperty === 'type') {
504
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Implementation: Job worker> must have a defined <Task definition type>`;
505
+ }
506
+
507
+ if (is(node, 'zeebe:CalledElement') && requiredProperty === 'processId') {
508
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Called element>`;
509
+ }
510
+
511
+ if (is(node, 'bpmn:Error') && requiredProperty === 'errorCode') {
512
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Error Reference> must have a defined <Error code>`;
513
+ }
514
+
515
+ if (is(node, 'bpmn:Escalation') && requiredProperty === 'escalationCode') {
516
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Escalation Reference> must have a defined <Escalation code>`;
517
+ }
518
+
519
+ if (is(node, 'zeebe:LoopCharacteristics') && requiredProperty === 'inputCollection') {
520
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Multi-instance marker> must have a defined <Input collection>`;
521
+ }
522
+
523
+ if (is(node, 'bpmn:Message') && requiredProperty === 'name') {
524
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Message Reference> must have a defined <Name>`;
525
+ }
526
+
527
+ if (is(node, 'bpmn:Signal') && requiredProperty === 'name') {
528
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Signal Reference> must have a defined <Name>`;
529
+ }
530
+
531
+ if (is(node, 'zeebe:Subscription') && requiredProperty === 'correlationKey') {
532
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Message Reference> must have a defined <Subscription correlation key>`;
533
+ }
534
+
535
+ if (is(node, 'zeebe:TaskDefinition') && requiredProperty === 'type') {
536
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Implementation: Job worker> must have a defined <Task definition type>`;
537
+ }
538
+
539
+ if (is(node, 'zeebe:ExecutionListener') && requiredProperty === 'type') {
540
+ return 'An <Execution Listener> must have a defined <Type>';
541
+ }
542
+
543
+ if (is(node, 'zeebe:TaskListener') && requiredProperty === 'type') {
544
+ return 'A <Task Listener> must have a defined <Type>';
545
+ }
546
+
547
+ if (requiredProperty === 'errorRef') {
548
+
549
+ if (parentNode && is(parentNode, 'bpmn:CatchEvent')) {
550
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> without defined <Error Reference>`, executionPlatform, executionPlatformVersion, allowedVersion);
551
+ } else if (parentNode && is(parentNode, 'bpmn:ThrowEvent')) {
552
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Error Reference>`;
553
+ }
554
+
555
+ }
556
+
557
+ if (requiredProperty === 'messageRef') {
558
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Message Reference>`;
559
+ }
560
+
561
+ if (requiredProperty === 'signalRef') {
562
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Signal Reference>`;
563
+ }
564
+
565
+ if (is(node, 'zeebe:FormDefinition')
566
+ && (
567
+ requiredProperty === 'formKey'
568
+ || (isArray(requiredProperty) && requiredProperty.includes('formKey') && isEmptyString(node.get('formKey')))
569
+ )) {
570
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Custom form key> must have a defined <Form key>`;
571
+ }
572
+
573
+ // Zeebe User Task
574
+ if (is(node, 'zeebe:FormDefinition') && isZeebeUserTask(parentNode)) {
575
+ if (isEmptyString(node.get('externalReference'))) {
576
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: External reference> must have a defined <External reference>`;
577
+ } else if (isEmptyString(node.get('formId'))) {
578
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Camunda Form> must have a defined <Form ID>`;
579
+ }
580
+ }
581
+
582
+ if (is(node, 'zeebe:FormDefinition') && isArray(requiredProperty) && requiredProperty.includes('formId') && isEmptyString(node.get('formId'))) {
583
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Camunda form (linked)> must have a defined <Form ID>`;
584
+ }
585
+
586
+ if (is(node, 'zeebe:UserTaskForm') && requiredProperty === 'body') {
587
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Form type: Camunda form (embedded)> must have a defined <Form JSON configuration>`;
588
+ }
589
+
590
+ if (is(node, 'bpmn:SequenceFlow') && requiredProperty === 'conditionExpression') {
591
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Condition expression> or be the default <Sequence Flow>`;
592
+ }
593
+
594
+ if (is(node, 'bpmn:TimerEventDefinition')
595
+ && isArray(requiredProperty)
596
+ && TIMER_PROPERTIES.some(property => requiredProperty.includes(property))
597
+ ) {
598
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Timer type>`;
599
+ }
600
+
601
+ if (is(node, 'bpmn:Process') && requiredProperty === 'historyTimeToLive') {
602
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <History time to live>`;
603
+ }
604
+
605
+ if (is(node, 'bpmn:LinkEventDefinition') && requiredProperty === 'name') {
606
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Name>`;
607
+ }
608
+
609
+ if (isAny(node, [
610
+ 'zeebe:CalledDecision',
611
+ 'zeebe:CalledElement',
612
+ 'zeebe:FormDefinition'
613
+ ]) && requiredProperty === 'versionTag') {
614
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> with <Binding: version tag> must have a defined <Version tag>`;
615
+ }
616
+
617
+ return message;
618
+ }
619
+
620
+ function getExpressionRequiredErrorMessage(report) {
621
+ const {
622
+ data,
623
+ message
624
+ } = report;
625
+
626
+ const {
627
+ node,
628
+ parentNode,
629
+ property
630
+ } = data;
631
+
632
+ const typeString = getTypeString(parentNode || node);
633
+
634
+ if (is(node, 'bpmn:FormalExpression') && TIMER_PROPERTIES.includes(property)) {
635
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a defined <Timer value>`;
636
+ }
637
+
638
+ return message;
639
+ }
640
+
641
+ function getExpressionValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion) {
642
+ const {
643
+ data,
644
+ message
645
+ } = report;
646
+
647
+ const {
648
+ node,
649
+ parentNode,
650
+ property
651
+ } = data;
652
+
653
+ const typeString = getTypeString(parentNode || node);
654
+
655
+ if (is(node, 'bpmn:FormalExpression') && property === 'timeCycle') {
656
+ if (!greaterOrEqual(executionPlatformVersion, '8.1')) {
657
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Time cycle> must be an expression, an ISO 8601 repeating interval, or a cron expression (cron only supported by Camunda 8.1 or newer)`;
658
+ } else {
659
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Time cycle> must be an expression, an ISO 8601 repeating interval, or a cron expression`;
660
+ }
661
+ }
662
+
663
+ if (is(node, 'bpmn:FormalExpression') && property === 'timeDate') {
664
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Time date> must be an expression, or an ISO 8601 date`;
665
+ }
666
+
667
+ if (is(node, 'bpmn:FormalExpression') && property === 'timeDuration') {
668
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Time duration> must be an expression, or an ISO 8601 interval`;
669
+ }
670
+
671
+ if (is(node, 'zeebe:TaskSchedule') && property === 'dueDate') {
672
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Due date> must be an ISO 8601 date`;
673
+ }
674
+
675
+ if (is(node, 'zeebe:TaskSchedule') && property === 'followUpDate') {
676
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Follow up date> must be an ISO 8601 date`;
677
+ }
678
+
679
+ if (is(node, 'zeebe:PriorityDefinition') && property === 'priority') {
680
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> <Priority> must be an expression, or an integer between 0 and 100`;
681
+ }
682
+
683
+ return message;
684
+ }
685
+
686
+ function getSupportedMessage(prefix, executionPlatform, executionPlatformVersion, allowedVersion) {
687
+ if (allowedVersion) {
688
+ return `${ prefix } is only supported by ${ getExecutionPlatformLabel(executionPlatform, allowedVersion) } or newer`;
689
+ }
690
+
691
+ return `${ prefix } is not supported by ${ getExecutionPlatformLabel(executionPlatform, executionPlatformVersion) }`;
692
+ }
693
+
694
+ function getExpressionNotAllowedErrorMessage(report) {
695
+ const {
696
+ data
697
+ } = report;
698
+
699
+ const {
700
+ node,
701
+ parentNode,
702
+ property
703
+ } = data;
704
+
705
+ if (is(node, 'bpmn:Escalation') && property === 'escalationCode' && is(parentNode, 'bpmn:CatchEvent')) {
706
+ return 'Escalation code used in a catch event must be a static value';
707
+ } else if (is(node, 'bpmn:Error') && property === 'errorCode' && is(parentNode, 'bpmn:CatchEvent')) {
708
+ return 'Error code used in a catch event must be a static value';
709
+ }
710
+
711
+ return report.message;
712
+ }
713
+
714
+ function getEventBasedGatewayTargetNotAllowedErrorMessage(report) {
715
+ const { data } = report;
716
+
717
+ const { node } = data;
718
+
719
+ if (is(node, 'bpmn:ReceiveTask')) {
720
+ return 'A <Receive Task> cannot be the target of an <Event-Based Gateway>';
721
+ }
722
+
723
+ return report.message;
724
+ }
725
+
726
+ function getPropertyValueNotAllowedErrorMessage(report, executionPlatform, executionPlatformVersion, modeler = 'desktop') {
727
+ const {
728
+ data,
729
+ message
730
+ } = report;
731
+
732
+ const {
733
+ allowedVersion,
734
+ node,
735
+ parentNode,
736
+ property
737
+ } = data;
738
+
739
+ const typeString = getTypeString(parentNode || node);
740
+
741
+ if (is(node, 'zeebe:CalledElement') && property === 'propagateAllParentVariables') {
742
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Propagate all variables> disabled`, executionPlatform, executionPlatformVersion, allowedVersion);
743
+ }
744
+
745
+ if (isAny(node, [
746
+ 'zeebe:CalledDecision',
747
+ 'zeebe:CalledElement',
748
+ 'zeebe:FormDefinition'
749
+ ]) && property === 'bindingType') {
750
+ const bindingType = node.get('bindingType');
751
+
752
+ let bindingTypeString = bindingType;
753
+
754
+ if (bindingType === 'versionTag') {
755
+ bindingTypeString = 'version tag';
756
+ }
757
+
758
+ return getSupportedMessage(`${ getIndefiniteArticle(typeString) } <${ typeString }> with <Binding: ${ bindingTypeString }>`, executionPlatform, executionPlatformVersion, allowedVersion);
759
+ }
760
+
761
+ return message;
762
+ }
763
+
764
+ function getSecretExpressionFormatDeprecatedErrorMessage(report) {
765
+ const { data } = report;
766
+
767
+ const { property } = data;
768
+
769
+ return `Property <${ property }> uses deprecated secret expression format secrets.SECRET, use {{secrets.SECRET}} instead`;
770
+ }
771
+
772
+ function getElementPropertyValueDuplicatedErrorMessage(report) {
773
+ const {
774
+ data,
775
+ message
776
+ } = report;
777
+
778
+ const {
779
+ node,
780
+ parentNode,
781
+ duplicatedProperty
782
+ } = data;
783
+
784
+ const typeString = getTypeString(parentNode || node);
785
+
786
+ if (is(node, 'bpmn:LinkEventDefinition') && duplicatedProperty === 'name') {
787
+ return `${ getIndefiniteArticle(typeString) } <${ typeString }> must have a unique <Name>`;
788
+ }
789
+
790
+ return message;
791
+ }
792
+
793
+ function getLoopNotAllowedErrorMessage(report) {
794
+ const { data } = report;
795
+
796
+ const { elements } = data;
797
+
798
+ return `A <Process> is not allowed to contain a straight-through processing loop: ${ elements.map(element => `<${ element }>`).join(', ') }`;
799
+ }
800
+
801
+ function isEmptyString(value) {
802
+ return isString(value) && value.trim() === '';
803
+ }
804
+
805
+ function isZeebeUserTask(node) {
806
+ return node.get('extensionElements').get('values').some(extensionElement => {
807
+ return is(extensionElement, 'zeebe:UserTask');
808
+ });
809
+ }