bpmnlint-plugin-camunda-compat 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@ All notable changes to [bpmnlint-plugin-camunda-compat](https://github.com/camun
6
6
 
7
7
  ___Note:__ Yet to be released changes appear here._
8
8
 
9
+ ## 0.6.0
10
+
11
+ * `FEAT`: adjust error messages to be more friendly ([#22](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/22))
12
+ * `FEAT`: lint error code and message name ([#21](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/21))
13
+ * `FIX`: task definition retries not required ([#20](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/20))
14
+
9
15
  ## 0.5.0
10
16
 
11
17
  * `FEAT`: update Camunda Cloud rules to lint extension elements and their properties ([#18](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/18))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmnlint-plugin-camunda-compat",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "A bpmnlint plug-in for Camunda Cloud and Platform compatibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -5,6 +5,7 @@ const {
5
5
  hasErrorReference,
6
6
  hasEventDefinitionOfType,
7
7
  hasEventDefinitionOfTypeOrNone,
8
+ hasMessageReference,
8
9
  hasNoLanes,
9
10
  isNotBpmn,
10
11
  withTranslations
@@ -39,61 +40,131 @@ module.exports = [
39
40
  'bpmn:TextAnnotation',
40
41
  {
41
42
  type: 'bpmn:BoundaryEvent',
42
- check: checkEvery(
43
- hasEventDefinitionOfType([
44
- 'bpmn:ErrorEventDefinition',
45
- 'bpmn:MessageEventDefinition',
46
- 'bpmn:TimerEventDefinition'
47
- ]),
48
- checkIf(
49
- checkEventDefinition(hasErrorReference),
50
- hasEventDefinitionOfType('bpmn:ErrorEventDefinition')
43
+ check: withTranslations(
44
+ checkEvery(
45
+ hasEventDefinitionOfType([
46
+ 'bpmn:ErrorEventDefinition',
47
+ 'bpmn:MessageEventDefinition',
48
+ 'bpmn:TimerEventDefinition'
49
+ ]),
50
+ checkIf(
51
+ checkEventDefinition(hasErrorReference),
52
+ hasEventDefinitionOfType('bpmn:ErrorEventDefinition')
53
+ ),
54
+ checkIf(
55
+ checkEvery(
56
+ checkEventDefinition(hasMessageReference),
57
+ checkIf(
58
+ checkEventDefinition(hasZeebeSubscription),
59
+ checkEventDefinition(hasMessageReference)
60
+ )
61
+ ),
62
+ hasEventDefinitionOfType('bpmn:MessageEventDefinition')
63
+ )
51
64
  ),
52
- checkIf(
53
- checkEventDefinition(hasZeebeSubscription),
54
- hasEventDefinitionOfType('bpmn:MessageEventDefinition')
55
- )
65
+ {
66
+ 'Element of type <bpmn:BoundaryEvent> not supported by {{ executionPlatform }}': 'An <Undefined Boundary Event> is not supported by {{ executionPlatform }}',
67
+ 'Element of type <bpmn:ErrorEventDefinition> must have property <errorRef>': 'An <Error Boundary Event> must have a defined <Error Reference>',
68
+ 'Element of type <bpmn:Error> must have property <errorCode>': 'An <Error Boundary Event> with <Error Reference> must have a defined <Error code>',
69
+ 'Element of type <bpmn:MessageEventDefinition> must have property <messageRef>': 'A <Message Boundary Event> must have a defined <Message Reference>',
70
+ 'Element of type <bpmn:Message> must have property <name>': 'A <Message Boundary Event> with <Message Reference> must have a defined <Name>',
71
+ 'Element of type <bpmn:Message> must have extension element of type <zeebe:Subscription>': 'A <Message Boundary Event> with <Message Reference> must have a defined <Subscription correlation key>',
72
+ 'Element of type <zeebe:Subscription> must have property <correlationKey>': 'A <Message Boundary Event> with <Message Reference> must have a defined <Subscription correlation key>'
73
+ }
56
74
  )
57
75
  },
58
76
  {
59
77
  type: 'bpmn:CallActivity',
60
- check: checkEvery(
61
- hasZeebeCalledElement,
62
- hasZeebeLoopCharacteristics
78
+ check: withTranslations(
79
+ checkEvery(
80
+ hasZeebeCalledElement,
81
+ hasZeebeLoopCharacteristics
82
+ ),
83
+ {
84
+ 'Element of type <bpmn:CallActivity> must have extension element of type <zeebe:CalledElement>': 'A <Call Activity> must have a defined <Called element>',
85
+ 'Element of type <zeebe:CalledElement> must have property <processId>': 'A <Call Activity> must have a defined <Called element>',
86
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Call Activity> with <Multi-instance marker> must have a defined <Input collection>',
87
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Call Activity> with <Multi-instance marker> must have a defined <Input collection>',
88
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Call Activity> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
89
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Call Activity> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
90
+ }
63
91
  )
64
92
  },
65
93
  {
66
94
  type: 'bpmn:EndEvent',
67
- check: checkEvery(
68
- hasEventDefinitionOfTypeOrNone('bpmn:ErrorEventDefinition'),
69
- checkIf(
70
- checkEventDefinition(hasErrorReference),
71
- hasEventDefinitionOfType('bpmn:ErrorEventDefinition')
72
- )
95
+ check: withTranslations(
96
+ checkEvery(
97
+ hasEventDefinitionOfTypeOrNone('bpmn:ErrorEventDefinition'),
98
+ checkIf(
99
+ checkEventDefinition(hasErrorReference),
100
+ hasEventDefinitionOfType('bpmn:ErrorEventDefinition')
101
+ )
102
+ ),
103
+ {
104
+ 'Element of type <bpmn:EndEvent> (<bpmn:MessageEventDefinition>) not supported by {{ executionPlatform }}': 'A <Message End Event> is not supported by {{ executionPlatform }}',
105
+ 'Element of type <bpmn:ErrorEventDefinition> must have property <errorRef>': 'An <Error End Event> must have a defined <Error Reference>',
106
+ 'Element of type <bpmn:Error> must have property <errorCode>': 'An <Error End Event> with <Error Reference> must have a defined <Error code>'
107
+ }
73
108
  )
74
109
  },
75
110
  {
76
111
  type: 'bpmn:IntermediateCatchEvent',
77
- check: checkEvery(
78
- hasEventDefinitionOfType([
79
- 'bpmn:TimerEventDefinition',
80
- 'bpmn:MessageEventDefinition'
81
- ]),
82
- checkIf(
83
- checkEventDefinition(hasZeebeSubscription),
84
- hasEventDefinitionOfType('bpmn:MessageEventDefinition')
85
- )
112
+ check: withTranslations(
113
+ checkEvery(
114
+ hasEventDefinitionOfType([
115
+ 'bpmn:TimerEventDefinition',
116
+ 'bpmn:MessageEventDefinition'
117
+ ]),
118
+ checkIf(
119
+ checkEvery(
120
+ checkEventDefinition(hasMessageReference),
121
+ checkIf(
122
+ checkEventDefinition(hasZeebeSubscription),
123
+ checkEventDefinition(hasMessageReference)
124
+ )
125
+ ),
126
+ hasEventDefinitionOfType('bpmn:MessageEventDefinition')
127
+ )
128
+ ),
129
+ {
130
+ 'Element of type <bpmn:IntermediateCatchEvent> not supported by {{ executionPlatform }}': 'A <Undefined Intermediate Catch Event> is not supported by {{ executionPlatform }}',
131
+ 'Element of type <bpmn:MessageEventDefinition> must have property <messageRef>': 'A <Message Intermediate Catch Event> must have a defined <Message Reference>',
132
+ 'Element of type <bpmn:Message> must have property <name>': 'A <Message Intermediate Catch Event> with <Message Reference> must have a defined <Name>',
133
+ 'Element of type <bpmn:Message> must have extension element of type <zeebe:Subscription>': 'A <Message Intermediate Catch Event> with <Message Reference> must have a defined <Subscription correlation key>',
134
+ 'Element of type <zeebe:Subscription> must have property <correlationKey>': 'A <Message Intermediate Catch Event> with <Message Reference> must have a defined <Subscription correlation key>'
135
+ }
86
136
  )
87
137
  },
88
138
  {
89
139
  type: 'bpmn:Process',
90
- check: hasNoLanes
140
+ check: withTranslations(
141
+ hasNoLanes,
142
+ {
143
+ 'Element of type <bpmn:Process> (<bpmn:LaneSet>) not supported by {{ executionPlatform }}': 'A <Lane> is not supported by Camunda Platform 8 (Zeebe 1.0)'
144
+ }
145
+ )
91
146
  },
92
147
  {
93
148
  type: 'bpmn:ReceiveTask',
94
- check: checkEvery(
95
- checkFlowNode(hasZeebeSubscription),
96
- hasZeebeLoopCharacteristics
149
+ check: withTranslations(
150
+ checkEvery(
151
+ checkFlowNode(hasMessageReference),
152
+ checkIf(
153
+ checkFlowNode(hasZeebeSubscription),
154
+ checkFlowNode(hasMessageReference)
155
+ ),
156
+ hasZeebeLoopCharacteristics
157
+ ),
158
+ {
159
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Receive Task> with <Multi-instance marker> must have a defined <Input collection>',
160
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Receive Task> with <Multi-instance marker> must have a defined <Input collection>',
161
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Receive Task> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
162
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Receive Task> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>',
163
+ 'Element of type <bpmn:ReceiveTask> must have property <messageRef>': 'A <Receive Task> must have a defined <Message Reference>',
164
+ 'Element of type <bpmn:Message> must have property <name>': 'A <Receive Task> with <Message Reference> must have a defined <Name>',
165
+ 'Element of type <bpmn:Message> must have extension element of type <zeebe:Subscription>': 'A <Receive Task> with <Message Reference> must have a defined <Subscription correlation key>',
166
+ 'Element of type <zeebe:Subscription> must have property <correlationKey>': 'A <Receive Task> with <Message Reference> must have a defined <Subscription correlation key>'
167
+ }
97
168
  )
98
169
  },
99
170
  {
@@ -104,34 +175,71 @@ module.exports = [
104
175
  hasZeebeTaskDefinition
105
176
  ),
106
177
  {
107
- 'foo': 'bar'
178
+ 'Element of type <bpmn:ServiceTask> must have extension element of type <zeebe:TaskDefinition>': 'A <Service Task> must have a <Task definition type>',
179
+ 'Element of type <zeebe:TaskDefinition> must have property <type>': 'A <Service Task> must have a <Task definition type>',
180
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Service Task> with <Multi-instance marker> must have a defined <Input collection>',
181
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Service Task> with <Multi-instance marker> must have a defined <Input collection>',
182
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Service Task> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
183
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Service Task> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
108
184
  }
109
185
  )
110
186
  },
111
187
  {
112
188
  type: 'bpmn:StartEvent',
113
- check: checkEvery(
114
- hasEventDefinitionOfTypeOrNone([
115
- 'bpmn:ErrorEventDefinition',
116
- 'bpmn:MessageEventDefinition',
117
- 'bpmn:TimerEventDefinition'
118
- ]),
119
- checkIf(
120
- checkEventDefinition(hasErrorReference),
121
- hasEventDefinitionOfType('bpmn:ErrorEventDefinition')
189
+ check: withTranslations(
190
+ checkEvery(
191
+ hasEventDefinitionOfTypeOrNone([
192
+ 'bpmn:ErrorEventDefinition',
193
+ 'bpmn:MessageEventDefinition',
194
+ 'bpmn:TimerEventDefinition'
195
+ ]),
196
+ checkIf(
197
+ checkEventDefinition(hasErrorReference),
198
+ hasEventDefinitionOfType('bpmn:ErrorEventDefinition')
199
+ ),
200
+ checkIf(
201
+ checkEvery(
202
+ checkEventDefinition(hasMessageReference),
203
+ checkIf(
204
+ checkEventDefinition(hasZeebeSubscription),
205
+ checkEventDefinition(hasMessageReference)
206
+ )
207
+ ),
208
+ hasEventDefinitionOfType('bpmn:MessageEventDefinition')
209
+ )
122
210
  ),
123
- checkIf(
124
- checkEventDefinition(hasZeebeSubscription),
125
- hasEventDefinitionOfType('bpmn:MessageEventDefinition')
126
- )
211
+ {
212
+ 'Element of type <bpmn:ErrorEventDefinition> must have property <errorRef>': 'An <Error Start Event> must have a defined <Error Reference>',
213
+ 'Element of type <bpmn:Error> must have property <errorCode>': 'An <Error Start Event> with <Error Reference> must have a defined <Error code>',
214
+ 'Element of type <bpmn:MessageEventDefinition> must have property <messageRef>': 'A <Message Start Event> must have a defined <Message Reference>',
215
+ 'Element of type <bpmn:Message> must have property <name>': 'A <Message Start Event> with <Message Reference> must have a defined <Name>',
216
+ 'Element of type <bpmn:Message> must have extension element of type <zeebe:Subscription>': 'A <Message Start Event> with <Message Reference> must have a defined <Subscription correlation key>',
217
+ 'Element of type <zeebe:Subscription> must have property <correlationKey>': 'A <Message Start Event> with <Message Reference> must have a defined <Subscription correlation key>'
218
+ }
127
219
  )
128
220
  },
129
221
  {
130
222
  type: 'bpmn:SubProcess',
131
- check: hasZeebeLoopCharacteristics
223
+ check: withTranslations(
224
+ hasZeebeLoopCharacteristics,
225
+ {
226
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Sub Process> with <Multi-instance marker> must have a defined <Input collection>',
227
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Sub Process> with <Multi-instance marker> must have a defined <Input collection>',
228
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Sub Process> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
229
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Sub Process> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
230
+ }
231
+ )
132
232
  },
133
233
  {
134
234
  type: 'bpmn:UserTask',
135
- check: hasZeebeLoopCharacteristics
235
+ check: withTranslations(
236
+ hasZeebeLoopCharacteristics,
237
+ {
238
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <User Task> with <Multi-instance marker> must have a defined <Input collection>',
239
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <User Task> with <Multi-instance marker> must have a defined <Input collection>',
240
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <User Task> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
241
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <User Task> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
242
+ }
243
+ )
136
244
  }
137
245
  ];
@@ -2,4 +2,4 @@ const { createRule } = require('./utils/rule');
2
2
 
3
3
  const checks = require('./camunda-cloud-1-0-checks');
4
4
 
5
- module.exports = createRule('Camunda Cloud', '1.0', checks, 'Zeebe');
5
+ module.exports = createRule('Camunda Cloud', '1.0', checks, 'Camunda Platform 8 (Zeebe 1.0)');
@@ -2,7 +2,10 @@ const camundaCloud10Checks = require('./camunda-cloud-1-0-checks');
2
2
 
3
3
  const { checkEvery } = require('./utils/rule');
4
4
 
5
- const { hasNoEventDefinition } = require('./utils/element');
5
+ const {
6
+ hasNoEventDefinition,
7
+ withTranslations
8
+ } = require('./utils/element');
6
9
 
7
10
  const {
8
11
  hasZeebeTaskDefinition,
@@ -13,31 +16,74 @@ module.exports = [
13
16
  ...camundaCloud10Checks,
14
17
  {
15
18
  type: 'bpmn:BusinessRuleTask',
16
- check: checkEvery(
17
- hasZeebeLoopCharacteristics,
18
- hasZeebeTaskDefinition
19
+ check: withTranslations(
20
+ checkEvery(
21
+ hasZeebeLoopCharacteristics,
22
+ hasZeebeTaskDefinition
23
+ ),
24
+ {
25
+ 'Element of type <bpmn:BusinessRuleTask> must have extension element of type <zeebe:TaskDefinition>': 'A <Business Rule Task> must have a <Task definition type>',
26
+ 'Element of type <zeebe:TaskDefinition> must have property <type>': 'A <Business Rule Task> must have a <Task definition type>',
27
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Business Rule Task> with <Multi-instance marker> must have a defined <Input collection>',
28
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Business Rule Task> with <Multi-instance marker> must have a defined <Input collection>',
29
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Business Rule Task> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
30
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Business Rule Task> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
31
+ }
19
32
  )
20
33
  },
21
34
  {
22
35
  type: 'bpmn:IntermediateThrowEvent',
23
- check: hasNoEventDefinition
36
+ check: withTranslations(
37
+ hasNoEventDefinition,
38
+ {
39
+ 'Element of type <bpmn:IntermediateThrowEvent> (<bpmn:MessageEventDefinition>) not supported by {{ executionPlatform }}': 'A <Message Intermediate Throw Event> is not supported by {{ executionPlatform }}'
40
+ }
41
+ )
24
42
  },
25
43
  {
26
44
  type: 'bpmn:ManualTask',
27
- check: hasZeebeLoopCharacteristics
45
+ check: withTranslations(
46
+ hasZeebeLoopCharacteristics,
47
+ {
48
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Manual Task> with <Multi-instance marker> must have a defined <Input collection>',
49
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Manual Task> with <Multi-instance marker> must have a defined <Input collection>',
50
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Manual Task> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
51
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Manual Task> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
52
+ }
53
+ )
28
54
  },
29
55
  {
30
56
  type: 'bpmn:ScriptTask',
31
- check: checkEvery(
32
- hasZeebeLoopCharacteristics,
33
- hasZeebeTaskDefinition
57
+ check: withTranslations(
58
+ checkEvery(
59
+ hasZeebeLoopCharacteristics,
60
+ hasZeebeTaskDefinition
61
+ ),
62
+ {
63
+ 'Element of type <bpmn:ScriptTask> must have extension element of type <zeebe:TaskDefinition>': 'A <Script Task> must have a <Task definition type>',
64
+ 'Element of type <zeebe:TaskDefinition> must have property <type>': 'A <Script Task> must have a <Task definition type>',
65
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Script Task> with <Multi-instance marker> must have a defined <Input collection>',
66
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Script Task> with <Multi-instance marker> must have a defined <Input collection>',
67
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Script Task> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
68
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Script Task> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
69
+ }
34
70
  )
35
71
  },
36
72
  {
37
73
  type: 'bpmn:SendTask',
38
- check: checkEvery(
39
- hasZeebeLoopCharacteristics,
40
- hasZeebeTaskDefinition
74
+ check: withTranslations(
75
+ checkEvery(
76
+ hasZeebeLoopCharacteristics,
77
+ hasZeebeTaskDefinition
78
+ ),
79
+ {
80
+ 'Element of type <bpmn:SendTask> must have extension element of type <zeebe:TaskDefinition>': 'A <Send Task> must have a <Task definition type>',
81
+ 'Element of type <zeebe:TaskDefinition> must have property <type>': 'A <Send Task> must have a <Task definition type>',
82
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Send Task> with <Multi-instance marker> must have a defined <Input collection>',
83
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Send Task> with <Multi-instance marker> must have a defined <Input collection>',
84
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Send Task> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
85
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Send Task> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
86
+ }
41
87
  )
42
88
  }
43
89
  ];
@@ -2,4 +2,4 @@ const { createRule } = require('./utils/rule');
2
2
 
3
3
  const checks = require('./camunda-cloud-1-1-checks');
4
4
 
5
- module.exports = createRule('Camunda Cloud', '1.1', checks, 'Zeebe');
5
+ module.exports = createRule('Camunda Cloud', '1.1', checks, 'Camunda Platform 8 (Zeebe 1.1)');
@@ -11,6 +11,7 @@ const {
11
11
  hasErrorReference,
12
12
  hasEventDefinitionOfType,
13
13
  hasEventDefinitionOfTypeOrNone,
14
+ withTranslations
14
15
  } = require('./utils/element');
15
16
 
16
17
  const { hasZeebeTaskDefinition } = require('./utils/cloud/element');
@@ -21,25 +22,37 @@ module.exports = [
21
22
  [
22
23
  {
23
24
  type: 'bpmn:IntermediateThrowEvent',
24
- check: checkEvery(
25
- hasEventDefinitionOfTypeOrNone('bpmn:MessageEventDefinition'),
26
- checkIf(
27
- hasZeebeTaskDefinition,
28
- hasEventDefinitionOfType('bpmn:MessageEventDefinition')
29
- )
25
+ check: withTranslations(
26
+ checkEvery(
27
+ hasEventDefinitionOfTypeOrNone('bpmn:MessageEventDefinition'),
28
+ checkIf(
29
+ hasZeebeTaskDefinition,
30
+ hasEventDefinitionOfType('bpmn:MessageEventDefinition')
31
+ )
32
+ ),
33
+ {
34
+ 'Element of type <bpmn:IntermediateThrowEvent> must have extension element of type <zeebe:TaskDefinition>': 'An <Intermediate Throw Event> must have a <Task definition type>',
35
+ 'Element of type <zeebe:TaskDefinition> must have property <type>': 'An <Intermediate Throw Event> must have a <Task definition type>'
36
+ }
30
37
  )
31
38
  },
32
39
  {
33
40
  type: 'bpmn:EndEvent',
34
- check: checkEvery(
35
- hasEventDefinitionOfTypeOrNone([
36
- 'bpmn:ErrorEventDefinition',
37
- 'bpmn:MessageEventDefinition'
38
- ]),
39
- checkIf(
40
- checkEventDefinition(hasErrorReference),
41
- hasEventDefinitionOfType('bpmn:ErrorEventDefinition')
42
- )
41
+ check: withTranslations(
42
+ checkEvery(
43
+ hasEventDefinitionOfTypeOrNone([
44
+ 'bpmn:ErrorEventDefinition',
45
+ 'bpmn:MessageEventDefinition'
46
+ ]),
47
+ checkIf(
48
+ checkEventDefinition(hasErrorReference),
49
+ hasEventDefinitionOfType('bpmn:ErrorEventDefinition')
50
+ )
51
+ ),
52
+ {
53
+ 'Element of type <bpmn:ErrorEventDefinition> must have property <errorRef>': 'An <Error End Event> must have a defined <Error Reference>',
54
+ 'Element of type <bpmn:Error> must have property <errorCode>': 'An <Error End Event> with <Error Reference> must have a defined <Error code>'
55
+ }
43
56
  )
44
57
  }
45
58
  ]
@@ -2,4 +2,4 @@ const { createRule } = require('./utils/rule');
2
2
 
3
3
  const checks = require('./camunda-cloud-1-2-checks');
4
4
 
5
- module.exports = createRule('Camunda Cloud', '1.2', checks, 'Zeebe');
5
+ module.exports = createRule('Camunda Cloud', '1.2', checks, 'Camunda Platform 8 (Zeebe 1.2)');
@@ -5,6 +5,8 @@ const {
5
5
  replaceCheck
6
6
  } = require('./utils/rule');
7
7
 
8
+ const { withTranslations } = require('./utils/element');
9
+
8
10
  const {
9
11
  hasZeebeCalledDecisionOrTaskDefinition,
10
12
  hasZeebeLoopCharacteristics
@@ -14,9 +16,22 @@ module.exports = [
14
16
  ...replaceCheck(
15
17
  camundaCloud12Checks,
16
18
  'bpmn:BusinessRuleTask',
17
- checkEvery(
18
- hasZeebeCalledDecisionOrTaskDefinition,
19
- hasZeebeLoopCharacteristics
19
+ withTranslations(
20
+ checkEvery(
21
+ hasZeebeCalledDecisionOrTaskDefinition,
22
+ hasZeebeLoopCharacteristics
23
+ ),
24
+ {
25
+ 'Element of type <bpmn:BusinessRuleTask> must have one extension element of type <zeebe:CalledDecision> or <zeebe:TaskDefinition>': 'A <Business Rule Task> must have a defined <Implementation>',
26
+ 'Element of type <bpmn:BusinessRuleTask> must have one or many extension elements of type <zeebe:CalledDecision> or <zeebe:TaskDefinition>': 'A <Business Rule Task> must have a defined <Implementation>',
27
+ 'Element of type <zeebe:TaskDefinition> must have property <type>': 'A <Business Rule Task> with <Implementation: Job worker> must have a defined <Task definition type>',
28
+ 'Element of type <zeebe:CalledDecision> must have property <decisionId>': 'A <Business Rule Task> with <Implementation: DMN decision> must have a defined <Called decision ID>',
29
+ 'Element of type <zeebe:CalledDecision> must have property <resultVariable>': 'A Business Rule Task with <Implementation: DMN decision> must have a defined <Result variable>',
30
+ 'Element of type <bpmn:MultiInstanceLoopCharacteristics> must have extension element of type <zeebe:LoopCharacteristics>': 'A <Business Rule Task> with <Multi-instance marker> must have a defined <Input collection>',
31
+ 'Element of type <zeebe:LoopCharacteristics> must have property <inputCollection>': 'A <Business Rule Task> with <Multi-instance marker> must have a defined <Input collection>',
32
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputElement> if it has property <outputCollection>': 'A <Business Rule Task> with <Multi-instance marker> and defined <Output collection> must have a defined <Output element>',
33
+ 'Element of type <zeebe:LoopCharacteristics> must have property <outputCollection> if it has property <outputElement>': 'A <Business Rule Task> with <Multi-instance marker> and defined <Output element> must have a defined <Output collection>'
34
+ }
20
35
  )
21
36
  )
22
37
  ];
@@ -2,4 +2,4 @@ const { createRule } = require('./utils/rule');
2
2
 
3
3
  const checks = require('./camunda-cloud-1-3-checks');
4
4
 
5
- module.exports = createRule('Camunda Cloud', '1.3', checks, 'Zeebe');
5
+ module.exports = createRule('Camunda Cloud', '1.3', checks, 'Camunda Platform 8 (Zeebe 1.3)');
@@ -2,4 +2,4 @@ const { createRule } = require('./utils/rule');
2
2
 
3
3
  const checks = require('./camunda-cloud-8-0-checks');
4
4
 
5
- module.exports = createRule('Camunda Cloud', '8.0', checks, 'Camunda Platform');
5
+ module.exports = createRule('Camunda Cloud', '8.0', checks, 'Camunda Platform 8');
@@ -29,9 +29,6 @@ module.exports.hasZeebeCalledDecisionOrTaskDefinition = checkFlowNode(
29
29
  properties: {
30
30
  type: {
31
31
  required: true
32
- },
33
- retries: {
34
- required: true
35
32
  }
36
33
  }
37
34
  }
@@ -102,9 +99,6 @@ module.exports.hasZeebeTaskDefinition = checkFlowNode(
102
99
  properties: {
103
100
  type: {
104
101
  required: true
105
- },
106
- retries: {
107
- required: true
108
102
  }
109
103
  }
110
104
  })
@@ -176,7 +176,7 @@ module.exports.findExtensionElement = findExtensionElement;
176
176
  function getElementNotSupportedError(type, propertyType, path = null) {
177
177
  if (propertyType) {
178
178
  return {
179
- message: `Element of type <${ type }> (<${ propertyType }>) not supported by {{ executionPlatform }} {{ executionPlatformVersion }}`,
179
+ message: `Element of type <${ type }> (<${ propertyType }>) not supported by {{ executionPlatform }}`,
180
180
  path,
181
181
  error: {
182
182
  type: ERROR_TYPES.ELEMENT_TYPE,
@@ -187,7 +187,7 @@ function getElementNotSupportedError(type, propertyType, path = null) {
187
187
  }
188
188
 
189
189
  return {
190
- message: `Element of type <${ type }> not supported by {{ executionPlatform }} {{ executionPlatformVersion }}`,
190
+ message: `Element of type <${ type }> not supported by {{ executionPlatform }}`,
191
191
  path,
192
192
  error: {
193
193
  type: ERROR_TYPES.ELEMENT_TYPE,
@@ -288,7 +288,7 @@ function checkProperties(node, properties, parentNode) {
288
288
  return [
289
289
  ...results,
290
290
  {
291
- message: `Element of type <${ node.$type }> must have property <${ propertyName }> if property <${ propertyChecks.dependendRequired }> is set`,
291
+ message: `Element of type <${ node.$type }> must have property <${ propertyName }> if it has property <${ propertyChecks.dependendRequired }>`,
292
292
  path: path
293
293
  ? [ ...path, propertyName ]
294
294
  : [ propertyName ],
@@ -343,8 +343,7 @@ module.exports.checkProperties = checkProperties;
343
343
  * {
344
344
  * type: 'zeebe:TaskDefinition',
345
345
  * properties: {
346
- * type: { required: true },
347
- * retries: { required: true }
346
+ * type: { required: true }
348
347
  * }
349
348
  * }
350
349
  * ]);
@@ -361,7 +360,7 @@ module.exports.hasExtensionElementsOfTypes = function(types, exclusive = false)
361
360
 
362
361
  if (!extensionElements || !extensionElements.length) {
363
362
  return {
364
- message: `Element of type <${ node.$type }> must have have at least one ${ formatTypes(types, true) } extension element`,
363
+ message: `Element of type <${ node.$type }> must have one or many extension elements of type ${ formatTypes(types, true) }`,
365
364
  path: getPath(node, parentNode),
366
365
  error: {
367
366
  type: ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
@@ -372,7 +371,7 @@ module.exports.hasExtensionElementsOfTypes = function(types, exclusive = false)
372
371
 
373
372
  if (exclusive && extensionElements.length > 1) {
374
373
  return {
375
- message: `Element of type <${ node.$type }> must have have either one ${ formatTypes(types, true) } extension element`,
374
+ message: `Element of type <${ node.$type }> must have one extension element of type ${ formatTypes(types, true) }`,
376
375
  path: getPath(node, parentNode)
377
376
  };
378
377
  }
@@ -415,8 +414,7 @@ module.exports.hasExtensionElementsOfTypes = function(types, exclusive = false)
415
414
  * {
416
415
  * type: 'zeebe:TaskDefinition',
417
416
  * properties: {
418
- * type: { required: true },
419
- * retries: { required: true }
417
+ * type: { required: true }
420
418
  * }
421
419
  * }
422
420
  * );
@@ -433,9 +431,7 @@ module.exports.hasExtensionElementOfType = function(type) {
433
431
 
434
432
  if (!extensionElement) {
435
433
  return {
436
- message: `Element of type <${ node.$type }> must have <${getType(
437
- type
438
- )}> extension element`,
434
+ message: `Element of type <${ node.$type }> must have extension element of type <${ getType(type) }>`,
439
435
  path: getPath(node, parentNode),
440
436
  error: {
441
437
  type: ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
@@ -552,7 +548,7 @@ module.exports.checkFlowNode = function(check) {
552
548
  *
553
549
  * @returns {Function}
554
550
  */
555
- module.exports.checkMessage = function(check) {
551
+ function checkMessage(check) {
556
552
  return function(node, parentNode) {
557
553
  const results = checkProperties(node, {
558
554
  messageRef: {
@@ -570,7 +566,9 @@ module.exports.checkMessage = function(check) {
570
566
 
571
567
  return check(message);
572
568
  };
573
- };
569
+ }
570
+
571
+ module.exports.checkMessage = checkMessage;
574
572
 
575
573
  /**
576
574
  * @example
@@ -603,7 +601,41 @@ module.exports.checkLoopCharacteristics = function(check) {
603
601
  };
604
602
  };
605
603
 
606
- module.exports.hasErrorReference = checkError(() => true);
604
+ module.exports.hasErrorReference = checkError(
605
+ (node) => {
606
+ const results = checkProperties(node, {
607
+ errorCode: {
608
+ required: true
609
+ }
610
+ });
611
+
612
+ if (results.length === 1) {
613
+ return results[ 0 ];
614
+ } else if (results.length > 1) {
615
+ return results;
616
+ }
617
+
618
+ return true;
619
+ }
620
+ );
621
+
622
+ module.exports.hasMessageReference = checkMessage(
623
+ (node) => {
624
+ const results = checkProperties(node, {
625
+ name: {
626
+ required: true
627
+ }
628
+ });
629
+
630
+ if (results.length === 1) {
631
+ return results[ 0 ];
632
+ } else if (results.length > 1) {
633
+ return results;
634
+ }
635
+
636
+ return true;
637
+ }
638
+ );
607
639
 
608
640
  function translate(result, translations) {
609
641
  if (isString(result)) {
@@ -13,6 +13,10 @@ const {
13
13
 
14
14
  const { toSemverMinor } = require('./engine-profile');
15
15
 
16
+ const { ERROR_TYPES } = require('./element');
17
+
18
+ const { getTypeString } = require('./type');
19
+
16
20
  /**
17
21
  * Factory function for rules. Returns a rule for a given execution platform,
18
22
  * execution platform version and an array of checks. Must be run on
@@ -23,6 +27,7 @@ const { toSemverMinor } = require('./engine-profile');
23
27
  * @param {string} ruleExecutionPlatform
24
28
  * @param {string} ruleExecutionPlatformVersion
25
29
  * @param {(Object|string)[]} checks
30
+ * @param {string} executionPlatformLabel
26
31
  *
27
32
  * @returns {Function}
28
33
  */
@@ -52,8 +57,26 @@ module.exports.createRule = function(ruleExecutionPlatform, ruleExecutionPlatfor
52
57
 
53
58
  const id = node.get('id') || '';
54
59
 
60
+ const label = getLabel(node);
61
+
55
62
  if (results === false) {
56
- reporter.report(id, `Element of type <${ node.$type }> not supported by ${ executionPlatformLabel || ruleExecutionPlatform } ${ toSemverMinor(ruleExecutionPlatformVersion) }`);
63
+ const message = getMessage(node, ruleExecutionPlatform, ruleExecutionPlatformVersion, executionPlatformLabel);
64
+
65
+ let options = {
66
+ error: {
67
+ type: ERROR_TYPES.ELEMENT_TYPE,
68
+ element: node.$type
69
+ }
70
+ };
71
+
72
+ if (label) {
73
+ options = {
74
+ ...options,
75
+ label
76
+ };
77
+ }
78
+
79
+ reporter.report(id, message, options);
57
80
  } else {
58
81
  if (!isArray(results)) {
59
82
  results = [ results ];
@@ -69,9 +92,20 @@ module.exports.createRule = function(ruleExecutionPlatform, ruleExecutionPlatfor
69
92
  ...rest
70
93
  } = result;
71
94
 
72
- message = addExecutionPlatform(message, executionPlatformLabel || ruleExecutionPlatform, toSemverMinor(ruleExecutionPlatformVersion));
95
+ message = addExecutionPlatform(message, executionPlatformLabel || `${ ruleExecutionPlatform } ${ toSemverMinor(ruleExecutionPlatformVersion) }`);
96
+
97
+ let options = {
98
+ ...rest
99
+ };
73
100
 
74
- reporter.report(id, message, rest);
101
+ if (label) {
102
+ options = {
103
+ ...options,
104
+ label
105
+ };
106
+ }
107
+
108
+ reporter.report(id, message, options);
75
109
  });
76
110
  }
77
111
  }
@@ -106,7 +140,7 @@ function checkNode(node, checks) {
106
140
 
107
141
  // (1) check using type only
108
142
  if (isString(check)) {
109
- return is(node, check);
143
+ return isExactly(node, check);
110
144
  }
111
145
 
112
146
  const { type } = check;
@@ -117,7 +151,7 @@ function checkNode(node, checks) {
117
151
  }
118
152
 
119
153
  // (3) check using type and function
120
- if (!is(node, type)) {
154
+ if (!isExactly(node, type)) {
121
155
  return false;
122
156
  }
123
157
 
@@ -209,10 +243,9 @@ function replaceChecks(checks, replacements) {
209
243
 
210
244
  module.exports.replaceChecks = replaceChecks;
211
245
 
212
- function addExecutionPlatform(string, executionPlatform, executionPlatformVersion) {
246
+ function addExecutionPlatform(string, executionPlatform) {
213
247
  return string
214
- .replace('{{ executionPlatform }}', executionPlatform)
215
- .replace('{{ executionPlatformVersion }}', executionPlatformVersion);
248
+ .replace('{{ executionPlatform }}', executionPlatform);
216
249
  }
217
250
 
218
251
  /**
@@ -248,4 +281,44 @@ function getErrors(results) {
248
281
  }
249
282
 
250
283
  return false;
284
+ }
285
+
286
+ function isExactly(node, type) {
287
+ const { $model } = node;
288
+
289
+ return $model.getType(node.$type) === $model.getType(type);
290
+ }
291
+
292
+ function getIndefiniteArticle(type) {
293
+ if ([
294
+ 'Error',
295
+ 'Escalation',
296
+ 'Event',
297
+ 'Intermediate',
298
+ 'Undefined'
299
+ ].includes(type.split(' ')[ 0 ])) {
300
+ return 'An';
301
+ }
302
+
303
+ return 'A';
304
+ }
305
+
306
+ function getMessage(node, executionPlatform, executionPlatformVersion, label) {
307
+ const type = getTypeString(node);
308
+
309
+ const indefiniteArticle = getIndefiniteArticle(type);
310
+
311
+ return addExecutionPlatform(`${ indefiniteArticle } <${ type }> is not supported by {{ executionPlatform }}`, label || `${ executionPlatform } ${ toSemverMinor(executionPlatformVersion) }`);
312
+ }
313
+
314
+ function getLabel(node) {
315
+ if (is(node, 'bpmn:Group')) {
316
+ const categoryValueRef = node.get('categoryValueRef');
317
+
318
+ return categoryValueRef && categoryValueRef.get('value');
319
+ } else if (is(node, 'bpmn:TextAnnotation')) {
320
+ return node.get('text');
321
+ }
322
+
323
+ return node.get('name');
251
324
  }
@@ -0,0 +1,47 @@
1
+ function getEventDefinition(node) {
2
+ const eventDefinitions = node.get('eventDefinitions');
3
+
4
+ return eventDefinitions && eventDefinitions[0];
5
+ }
6
+
7
+ function getEventDefinitionPrefix(eventDefinition) {
8
+ const localType = getLocalType(eventDefinition);
9
+
10
+ return localType.replace('EventDefinition', '');
11
+ }
12
+
13
+ function getLocalType(node) {
14
+ const { $descriptor } = node;
15
+
16
+ const { localName } = $descriptor.ns;
17
+
18
+ return localName;
19
+ }
20
+
21
+ function formatTypeString(string) {
22
+ return string.replace(/([a-z])([A-Z])/g, '$1 $2').trim();
23
+ }
24
+
25
+ module.exports.getTypeString = function(node) {
26
+ let type = getLocalType(node);
27
+
28
+ const eventDefinition = getEventDefinition(node);
29
+
30
+ if (eventDefinition) {
31
+ type = `${ getEventDefinitionPrefix(eventDefinition) }${ type }`;
32
+ } else if ([
33
+ 'BoundaryEvent',
34
+ 'EndEvent',
35
+ 'IntermediateCatchEvent',
36
+ 'IntermediateThrowEvent',
37
+ 'StartEvent'
38
+ ].includes(type)) {
39
+ type = `Undefined ${ type }`;
40
+ }
41
+
42
+ if (type === 'Task') {
43
+ type = 'Undefined Task';
44
+ }
45
+
46
+ return formatTypeString(type);
47
+ };