bpmnlint-plugin-camunda-compat 0.9.1 → 0.11.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/index.js CHANGED
@@ -1,71 +1,62 @@
1
+ const { omit } = require('min-dash');
2
+
1
3
  const calledDecisionOrTaskDefinitionConfig = require('./rules/called-decision-or-task-definition/config'),
2
4
  elementTypeConfig = require('./rules/element-type/config');
3
5
 
6
+ const camundaCloud10Rules = {
7
+ 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud10 ],
8
+ 'called-element': 'error',
9
+ 'duplicate-task-headers': 'error',
10
+ 'element-type': [ 'error', elementTypeConfig.camundaCloud10 ],
11
+ 'error-reference': 'error',
12
+ 'loop-characteristics': 'error',
13
+ 'message-reference': 'error',
14
+ 'no-template': 'error',
15
+ 'no-zeebe-properties': 'error',
16
+ 'subscription': 'error',
17
+ 'user-task-form': 'error'
18
+ };
19
+
20
+ const camundaCloud11Rules = {
21
+ ...camundaCloud10Rules,
22
+ 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud11 ],
23
+ 'element-type': [ 'error', elementTypeConfig.camundaCloud11 ]
24
+ };
25
+
26
+ const camundaCloud12Rules = {
27
+ ...camundaCloud11Rules,
28
+ 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud12 ],
29
+ 'element-type': [ 'error', elementTypeConfig.camundaCloud12 ]
30
+ };
31
+
32
+ const camundaCloud13Rules = {
33
+ ...camundaCloud12Rules,
34
+ 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud13 ]
35
+ };
36
+
37
+ const camundaCloud80Rules = omit(camundaCloud13Rules, 'no-template');
38
+
39
+ const camundaCloud81Rules = omit(camundaCloud13Rules, 'no-zeebe-properties');
40
+
4
41
  module.exports = {
5
42
  configs: {
6
43
  'camunda-cloud-1-0': {
7
- rules: {
8
- 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud10 ],
9
- 'called-element': 'error',
10
- 'element-type': [ 'error', elementTypeConfig.camundaCloud10 ],
11
- 'error-reference': 'error',
12
- 'loop-characteristics': 'error',
13
- 'message-reference': 'error',
14
- 'no-template': 'error',
15
- 'subscription': 'error',
16
- 'user-task-form': 'error'
17
- }
44
+ rules: camundaCloud10Rules
18
45
  },
19
46
  'camunda-cloud-1-1': {
20
- rules: {
21
- 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud11 ],
22
- 'called-element': 'error',
23
- 'element-type': [ 'error', elementTypeConfig.camundaCloud11 ],
24
- 'error-reference': 'error',
25
- 'loop-characteristics': 'error',
26
- 'message-reference': 'error',
27
- 'no-template': 'error',
28
- 'subscription': 'error',
29
- 'user-task-form': 'error'
30
- }
47
+ rules: camundaCloud11Rules
31
48
  },
32
49
  'camunda-cloud-1-2': {
33
- rules: {
34
- 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud12 ],
35
- 'called-element': 'error',
36
- 'element-type': [ 'error', elementTypeConfig.camundaCloud12 ],
37
- 'error-reference': 'error',
38
- 'loop-characteristics': 'error',
39
- 'message-reference': 'error',
40
- 'no-template': 'error',
41
- 'subscription': 'error',
42
- 'user-task-form': 'error'
43
- }
50
+ rules: camundaCloud12Rules
44
51
  },
45
52
  'camunda-cloud-1-3': {
46
- rules: {
47
- 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud13 ],
48
- 'called-element': 'error',
49
- 'element-type': [ 'error', elementTypeConfig.camundaCloud12 ],
50
- 'error-reference': 'error',
51
- 'loop-characteristics': 'error',
52
- 'message-reference': 'error',
53
- 'no-template': 'error',
54
- 'subscription': 'error',
55
- 'user-task-form': 'error'
56
- }
53
+ rules: camundaCloud13Rules
57
54
  },
58
55
  'camunda-cloud-8-0': {
59
- rules: {
60
- 'called-decision-or-task-definition': [ 'error', calledDecisionOrTaskDefinitionConfig.camundaCloud13 ],
61
- 'called-element': 'error',
62
- 'element-type': [ 'error', elementTypeConfig.camundaCloud12 ],
63
- 'error-reference': 'error',
64
- 'loop-characteristics': 'error',
65
- 'message-reference': 'error',
66
- 'subscription': 'error',
67
- 'user-task-form': 'error'
68
- }
56
+ rules: camundaCloud80Rules
57
+ },
58
+ 'camunda-cloud-8-1': {
59
+ rules: camundaCloud81Rules
69
60
  }
70
61
  }
71
62
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmnlint-plugin-camunda-compat",
3
- "version": "0.9.1",
3
+ "version": "0.11.0",
4
4
  "description": "A bpmnlint plug-in for Camunda Platform compatibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -23,21 +23,21 @@
23
23
  },
24
24
  "license": "MIT",
25
25
  "devDependencies": {
26
- "bpmn-moddle": "^7.1.2",
26
+ "bpmn-moddle": "^7.1.3",
27
27
  "bpmnlint": "^7.8.0",
28
- "chai": "^4.3.5",
29
- "eslint": "^7.32.0",
30
- "eslint-plugin-bpmn-io": "^0.13.0",
31
- "mocha": "^5.2.0",
28
+ "chai": "^4.3.6",
29
+ "eslint": "^8.23.0",
30
+ "eslint-plugin-bpmn-io": "^0.14.1",
31
+ "mocha": "^10.0.0",
32
32
  "modeler-moddle": "^0.1.0",
33
- "sinon": "^13.0.1",
33
+ "sinon": "^14.0.0",
34
34
  "sinon-chai": "^3.7.0",
35
- "zeebe-bpmn-moddle": "^0.12.1"
35
+ "zeebe-bpmn-moddle": "^0.14.0"
36
36
  },
37
37
  "dependencies": {
38
38
  "@bpmn-io/moddle-utils": "^0.1.0",
39
39
  "bpmnlint-utils": "^1.0.2",
40
- "min-dash": "^3.8.0"
40
+ "min-dash": "^3.8.1"
41
41
  },
42
42
  "files": [
43
43
  "rules",
@@ -8,9 +8,8 @@ const { getPath } = require('@bpmn-io/moddle-utils');
8
8
  const {
9
9
  findExtensionElement,
10
10
  getEventDefinition,
11
- hasProperties,
12
- hasExtensionElementOfType,
13
- hasExtensionElementsOfTypes
11
+ hasExtensionElement,
12
+ hasProperties
14
13
  } = require('../utils/element');
15
14
 
16
15
  const { reportErrors } = require('../utils/reporter');
@@ -99,14 +98,14 @@ module.exports = function(config) {
99
98
  }
100
99
 
101
100
  if (isAny(node, elementsCalledDecision) && isAny(node, elementsTaskDefinition)) {
102
- errors = hasExtensionElementsOfTypes(node, [
101
+ errors = hasExtensionElement(node, [
103
102
  'zeebe:CalledDecision',
104
103
  'zeebe:TaskDefinition'
105
- ], node, true);
104
+ ], node);
106
105
  } else if (isAny(node, elementsCalledDecision)) {
107
- errors = hasExtensionElementOfType(node, 'zeebe:CalledDecision', node);
106
+ errors = hasExtensionElement(node, 'zeebe:CalledDecision', node);
108
107
  } else {
109
- errors = hasExtensionElementOfType(node, 'zeebe:TaskDefinition', node);
108
+ errors = hasExtensionElement(node, 'zeebe:TaskDefinition', node);
110
109
  }
111
110
 
112
111
  if (errors && errors.length) {
@@ -2,7 +2,7 @@ const { is } = require('bpmnlint-utils');
2
2
 
3
3
  const {
4
4
  findExtensionElement,
5
- hasExtensionElementOfType,
5
+ hasExtensionElement,
6
6
  hasProperties
7
7
  } = require('./utils/element');
8
8
 
@@ -14,7 +14,7 @@ module.exports = function() {
14
14
  return;
15
15
  }
16
16
 
17
- let errors = hasExtensionElementOfType(node, 'zeebe:CalledElement', node);
17
+ let errors = hasExtensionElement(node, 'zeebe:CalledElement', node);
18
18
 
19
19
  if (errors && errors.length) {
20
20
  reportErrors(node, reporter, errors);
@@ -0,0 +1,57 @@
1
+ const {
2
+ is,
3
+ isAny
4
+ } = require('bpmnlint-utils');
5
+
6
+ const {
7
+ findExtensionElement,
8
+ getMessageEventDefinition,
9
+ hasDuplicatedPropertyValues
10
+ } = require('./utils/element');
11
+
12
+ const { reportErrors } = require('./utils/reporter');
13
+
14
+ module.exports = function() {
15
+ function check(node, reporter) {
16
+ if (!is(node, 'bpmn:UserTask') && !isZeebeServiceTask(node)) {
17
+ return;
18
+ }
19
+
20
+ const taskHeaders = findExtensionElement(node, 'zeebe:TaskHeaders');
21
+
22
+ if (!taskHeaders) {
23
+ return;
24
+ }
25
+
26
+ const errors = hasDuplicatedPropertyValues(taskHeaders, 'values', 'key', node);
27
+
28
+ if (errors && errors.length) {
29
+ reportErrors(node, reporter, errors);
30
+ }
31
+ }
32
+
33
+ return {
34
+ check
35
+ };
36
+ };
37
+
38
+ // helpers //////////
39
+
40
+ function isZeebeServiceTask(element) {
41
+ if (is(element, 'zeebe:ZeebeServiceTask')) {
42
+ return true;
43
+ }
44
+
45
+ if (isAny(element, [
46
+ 'bpmn:EndEvent',
47
+ 'bpmn:IntermediateThrowEvent'
48
+ ])) {
49
+ return getMessageEventDefinition(element);
50
+ }
51
+
52
+ if (is(element, 'bpmn:BusinessRuleTask')) {
53
+ return findExtensionElement(element, 'zeebe:TaskDefinition');
54
+ }
55
+
56
+ return false;
57
+ }
@@ -3,7 +3,7 @@ const { is } = require('bpmnlint-utils');
3
3
  const {
4
4
  findExtensionElement,
5
5
  hasProperties,
6
- hasExtensionElementOfType
6
+ hasExtensionElement
7
7
  } = require('./utils/element');
8
8
 
9
9
  const { reportErrors } = require('./utils/reporter');
@@ -32,7 +32,7 @@ module.exports = function() {
32
32
  return;
33
33
  }
34
34
 
35
- errors = hasExtensionElementOfType(loopCharacteristics, 'zeebe:LoopCharacteristics', node);
35
+ errors = hasExtensionElement(loopCharacteristics, 'zeebe:LoopCharacteristics', node);
36
36
 
37
37
  if (errors && errors.length) {
38
38
  reportErrors(node, reporter, errors);
@@ -0,0 +1,23 @@
1
+ const { is } = require('bpmnlint-utils');
2
+
3
+ const { hasNoExtensionElement } = require('./utils/element');
4
+
5
+ const { reportErrors } = require('./utils/reporter');
6
+
7
+ module.exports = function() {
8
+ function check(node, reporter) {
9
+ if (!is(node, 'zeebe:PropertiesHolder')) {
10
+ return;
11
+ }
12
+
13
+ const errors = hasNoExtensionElement(node, 'zeebe:Properties', node);
14
+
15
+ if (errors && errors.length) {
16
+ reportErrors(node, reporter, errors);
17
+ }
18
+ }
19
+
20
+ return {
21
+ check
22
+ };
23
+ };
@@ -6,7 +6,7 @@ const {
6
6
  const {
7
7
  findExtensionElement,
8
8
  getEventDefinition,
9
- hasExtensionElementOfType,
9
+ hasExtensionElement,
10
10
  hasProperties
11
11
  } = require('./utils/element');
12
12
 
@@ -37,7 +37,7 @@ module.exports = function() {
37
37
  return;
38
38
  }
39
39
 
40
- let errors = hasExtensionElementOfType(messageRef, 'zeebe:Subscription', node);
40
+ let errors = hasExtensionElement(messageRef, 'zeebe:Subscription', node);
41
41
 
42
42
  if (errors && errors.length) {
43
43
  reportErrors(node, reporter, errors);
@@ -56,6 +56,8 @@ module.exports = function() {
56
56
  };
57
57
  };
58
58
 
59
+ // helpers //////////
60
+
59
61
  function findUserTaskForm(node, formKey) {
60
62
  const process = findParent(node, 'bpmn:Process');
61
63
 
@@ -1,10 +1,14 @@
1
1
  const {
2
2
  isArray,
3
3
  isDefined,
4
+ isNil,
4
5
  some
5
6
  } = require('min-dash');
6
7
 
7
- const { isAny } = require('bpmnlint-utils');
8
+ const {
9
+ is,
10
+ isAny
11
+ } = require('bpmnlint-utils');
8
12
 
9
13
  const { getPath } = require('@bpmn-io/moddle-utils');
10
14
 
@@ -12,12 +16,22 @@ const { ERROR_TYPES } = require('./error-types');
12
16
 
13
17
  module.exports.ERROR_TYPES = ERROR_TYPES;
14
18
 
15
- module.exports.getEventDefinition = function(node) {
19
+ function getEventDefinition(node) {
16
20
  const eventDefinitions = node.get('eventDefinitions');
17
21
 
18
22
  if (eventDefinitions) {
19
23
  return eventDefinitions[ 0 ];
20
24
  }
25
+ }
26
+
27
+ module.exports.getEventDefinition = getEventDefinition;
28
+
29
+ module.exports.getMessageEventDefinition = function(node) {
30
+ if (is(node, 'bpmn:ReceiveTask')) {
31
+ return node;
32
+ }
33
+
34
+ return getEventDefinition(node);
21
35
  };
22
36
 
23
37
  function findExtensionElements(node, types) {
@@ -71,6 +85,50 @@ function formatTypes(types, exclusive = false) {
71
85
 
72
86
  module.exports.formatTypes = formatTypes;
73
87
 
88
+ module.exports.hasDuplicatedPropertyValues = function(node, propertiesName, propertyName, parentNode = null) {
89
+ const properties = node.get(propertiesName);
90
+
91
+ const propertyValues = properties.map(property => property.get(propertyName));
92
+
93
+ // (1) find duplicates
94
+ const duplicates = propertyValues.reduce((duplicates, propertyValue, index) => {
95
+ if (propertyValues.indexOf(propertyValue) !== index && !duplicates.includes(propertyValue)) {
96
+ return [
97
+ ...duplicates,
98
+ propertyValue
99
+ ];
100
+ }
101
+
102
+ return duplicates;
103
+ }, []);
104
+
105
+ // (2) report error for each duplicate
106
+ if (duplicates.length) {
107
+ return duplicates.map(duplicate => {
108
+
109
+ // (3) find properties with duplicate
110
+ const duplicateProperties = properties.filter(property => property.get(propertyName) === duplicate);
111
+
112
+ // (4) report error
113
+ return {
114
+ message: `Properties of type <${ duplicateProperties[ 0 ].$type }> have property <${ propertyName }> with duplicate value of <${ duplicate }>`,
115
+ path: null,
116
+ error: {
117
+ type: ERROR_TYPES.PROPERTY_VALUE_DUPLICATED,
118
+ node,
119
+ parentNode: parentNode == node ? null : parentNode,
120
+ duplicatedProperty: propertyName,
121
+ duplicatedPropertyValue: duplicate,
122
+ properties: duplicateProperties,
123
+ propertiesName
124
+ }
125
+ };
126
+ });
127
+ }
128
+
129
+ return [];
130
+ };
131
+
74
132
  module.exports.hasProperties = function(node, properties, parentNode = null) {
75
133
  return Object.entries(properties).reduce((results, property) => {
76
134
  const [ propertyName, propertyChecks ] = property;
@@ -132,7 +190,7 @@ module.exports.hasProperties = function(node, properties, parentNode = null) {
132
190
  return [
133
191
  ...results,
134
192
  {
135
- message: `Property <${ propertyName }> of type <${ propertyValue.$type }> not allowed`,
193
+ message: `Element of type <${ node.$type }> must not have property <${ propertyName }> of type <${ propertyValue.$type }>`,
136
194
  path: path
137
195
  ? [ ...path, propertyName ]
138
196
  : [ propertyName ],
@@ -147,11 +205,11 @@ module.exports.hasProperties = function(node, properties, parentNode = null) {
147
205
  ];
148
206
  }
149
207
 
150
- if (propertyChecks.allowed === false && isDefined(propertyValue)) {
208
+ if (propertyChecks.allowed === false && isDefined(propertyValue) && !isNil(propertyValue)) {
151
209
  return [
152
210
  ...results,
153
211
  {
154
- message: `Property <${ propertyName }> not allowed`,
212
+ message: `Element of type <${ node.$type }> must not have property <${ propertyName }>`,
155
213
  path: path
156
214
  ? [ ...path, propertyName ]
157
215
  : [ propertyName ],
@@ -169,38 +227,21 @@ module.exports.hasProperties = function(node, properties, parentNode = null) {
169
227
  }, []);
170
228
  };
171
229
 
172
- module.exports.hasExtensionElementsOfTypes = function(node, types, parentNode = null, exclusive = false) {
173
- const extensionElements = findExtensionElements(node, types);
230
+ module.exports.hasExtensionElement = function(node, types, parentNode = null) {
231
+ const typesArray = isArray(types) ? types : [ types ];
174
232
 
175
- if (!extensionElements || !extensionElements.length) {
176
- return [
177
- {
178
- message: exclusive
179
- ? `Element of type <${ node.$type }> must have one extension element of type ${ formatTypes(types, true) }`
180
- : `Element of type <${ node.$type }> must have one or many extension elements of type ${ formatTypes(types, true) }`,
181
- path: getPath(node, parentNode),
182
- error: {
183
- type: ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
184
- node,
185
- parentNode: parentNode == node ? null : parentNode,
186
- requiredExtensionElement: types,
187
- exclusive
188
- }
189
- }
190
- ];
191
- }
233
+ const extensionElements = findExtensionElements(node, typesArray);
192
234
 
193
- if (exclusive && extensionElements.length > 1) {
235
+ if (!extensionElements || extensionElements.length !== 1) {
194
236
  return [
195
237
  {
196
- message: `Element of type <${ node.$type }> must have one extension element of type ${ formatTypes(types, true) }`,
238
+ message: `Element of type <${ node.$type }> must have one extension element of type ${ formatTypes(typesArray, true) }`,
197
239
  path: getPath(node, parentNode),
198
240
  error: {
199
241
  type: ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
200
242
  node,
201
243
  parentNode: parentNode == node ? null : parentNode,
202
- requiredExtensionElement: types,
203
- exclusive
244
+ requiredExtensionElement: types
204
245
  }
205
246
  }
206
247
  ];
@@ -209,19 +250,19 @@ module.exports.hasExtensionElementsOfTypes = function(node, types, parentNode =
209
250
  return [];
210
251
  };
211
252
 
212
- module.exports.hasExtensionElementOfType = function(node, type, parentNode = null) {
253
+ module.exports.hasNoExtensionElement = function(node, type, parentNode = null) {
213
254
  const extensionElement = findExtensionElement(node, type);
214
255
 
215
- if (!extensionElement) {
256
+ if (extensionElement) {
216
257
  return [
217
258
  {
218
- message: `Element of type <${ node.$type }> must have extension element of type <${ type }>`,
219
- path: getPath(node, parentNode),
259
+ message: `Element of type <${ node.$type }> must not have extension element of type <${ type }>`,
260
+ path: getPath(extensionElement, parentNode),
220
261
  error: {
221
- type: ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,
262
+ type: ERROR_TYPES.EXTENSION_ELEMENT_NOT_ALLOWED,
222
263
  node,
223
264
  parentNode: parentNode == node ? null : parentNode,
224
- requiredExtensionElement: type
265
+ extensionElement
225
266
  }
226
267
  }
227
268
  ];
@@ -5,5 +5,6 @@ module.exports.ERROR_TYPES = Object.freeze({
5
5
  PROPERTY_DEPENDEND_REQUIRED: 'propertyDependendRequired',
6
6
  PROPERTY_NOT_ALLOWED: 'propertyNotAllowed',
7
7
  PROPERTY_REQUIRED: 'propertyRequired',
8
- PROPERTY_TYPE_NOT_ALLOWED: 'propertyTypeNotAllowed'
8
+ PROPERTY_TYPE_NOT_ALLOWED: 'propertyTypeNotAllowed',
9
+ PROPERTY_VALUE_DUPLICATED: 'propertyValueDuplicated'
9
10
  });
package/CHANGELOG.md DELETED
@@ -1,83 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to [bpmnlint-plugin-camunda-compat](https://github.com/camunda/bpmnlint-plugin-camunda-compat) are documented here. We use [semantic versioning](http://semver.org/) for releases.
4
-
5
- ## Unreleased
6
-
7
- ___Note:__ Yet to be released changes appear here._
8
-
9
- ## 0.9.1
10
-
11
- * `FIX`: add name to reports ([#38](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/38))
12
-
13
- ## 0.9.0
14
-
15
- * `FEAT`: add user task forms rule ([#32](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/32))
16
-
17
- ## 0.8.0
18
-
19
- * `FEAT`: add templates rule ([#31](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/31))
20
-
21
- ## 0.7.1
22
-
23
- * `FIX`: lint subscription only if start event child of sub process ([#34](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/34))
24
-
25
- ## 0.7.0
26
-
27
- * `FEAT`: refactor plugin structure ([#29](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/29))
28
- * `DEPS`: update to `bpmnlint@7.8.0` ([#29](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/29))
29
-
30
- ### Breaking Changes
31
-
32
- * configuration not selected based on execution platform and version anymore, either configure manually or use [`@camunda/linting`](https://github.com/camunda/linting)
33
- * error message not adjusted to be shown in Camunda Modeler anymore
34
- * error type ELEMENT_TYPE changed to ELEMENT_TYPE_NOT_ALLOWED
35
- * error type PROPERTY_TYPE changed to PROPERTY_TYPE_NOT_ALLOWED
36
- * error data changed (cf. docs/ERRORS.md)
37
-
38
- ## 0.6.2
39
-
40
- * `FIX`: fix error message formatting ([#27](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/27))
41
-
42
- ## 0.6.1
43
-
44
- * `FIX`: lanes supported ([#26](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/26))
45
-
46
- ## 0.6.0
47
-
48
- * `FEAT`: adjust error messages to be more friendly ([#22](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/22))
49
- * `FEAT`: lint error code and message name ([#21](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/21))
50
- * `FIX`: task definition retries not required ([#20](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/20))
51
-
52
- ## 0.5.0
53
-
54
- * `FEAT`: update Camunda Cloud rules to lint extension elements and their properties ([#18](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/18))
55
-
56
- ## 0.4.0
57
-
58
- * `CHORE`: rename `Cloud` `1.4` to `8.0` ([#14](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/14))
59
- * `CHORE`: rename `Cloud` to `Platform`/`Zeebe` ([#15](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/15))
60
-
61
- ## 0.3.0
62
-
63
- * `FEAT`: support multiInstance for subprocesses with cloud 1.0 ([#6](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/6))
64
- * `FEAT`: add Camunda Platform rules ([#5](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/5))
65
- * `FEAT`: add Camunda Cloud 1.4 rule ([#5](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/5))
66
- * `TEST`: add Cloud 1.1, 1.2, 1.3 integration tests ([#4](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/4))
67
- * `TEST`: verify exported configs ([#5](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/5))
68
- * `DEPS`: fix security audit warnings ([#6](https://github.com/camunda/bpmnlint-plugin-camunda-compat/pull/6))
69
- * `DOCS`: update link to documentation
70
- * `DOCS`: link Camunda Cloud and Platform BPMN coverage
71
-
72
- ## 0.2.0
73
-
74
- * `FEAT`: early return if execution platform does not match
75
- * `FIX`: correct check for `bpmn:BaseElement`
76
-
77
- ## 0.1.1
78
-
79
- * `FEAT`: initial support for Camunda Cloud 1.0, 1.1, 1.2, and 1.3
80
-
81
- ## ...
82
-
83
- Check `git log` for earlier history.