bpmnlint-plugin-camunda-compat 0.23.0 → 1.0.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
@@ -12,6 +12,7 @@ const camundaCloud10Rules = withConfig({
12
12
  'message-reference': 'error',
13
13
  'no-candidate-users': 'error',
14
14
  'no-expression': 'error',
15
+ 'no-task-schedule': 'error',
15
16
  'no-template': 'error',
16
17
  'no-zeebe-properties': 'error',
17
18
  'sequence-flow-condition': 'error',
@@ -37,8 +38,13 @@ const camundaCloud81Rules = withConfig({
37
38
  }, { version: '8.1' });
38
39
 
39
40
  const camundaCloud82Rules = withConfig({
40
- ...omit(camundaCloud81Rules, 'no-candidate-users'),
41
- 'escalation-reference': 'error'
41
+ ...omit(camundaCloud81Rules, [
42
+ 'no-candidate-users',
43
+ 'no-task-schedule'
44
+ ]),
45
+ 'escalation-reference': 'error',
46
+ 'no-signal-event-sub-process': 'error',
47
+ 'task-schedule': 'error'
42
48
  }, { version: '8.2' });
43
49
 
44
50
  const camundaPlatform719Rules = withConfig({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmnlint-plugin-camunda-compat",
3
- "version": "0.23.0",
3
+ "version": "1.0.0",
4
4
  "description": "A bpmnlint plug-in for Camunda Platform compatibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -33,7 +33,7 @@
33
33
  "modeler-moddle": "^0.1.0",
34
34
  "sinon": "^14.0.0",
35
35
  "sinon-chai": "^3.7.0",
36
- "zeebe-bpmn-moddle": "^0.17.0"
36
+ "zeebe-bpmn-moddle": "^0.18.0"
37
37
  },
38
38
  "dependencies": {
39
39
  "@bpmn-io/feel-lint": "^0.1.1",
@@ -50,6 +50,7 @@ module.exports = {
50
50
  'bpmn:ErrorEventDefinition': '1.0',
51
51
  'bpmn:EscalationEventDefinition': '8.2',
52
52
  'bpmn:MessageEventDefinition': '1.0',
53
+ 'bpmn:SignalEventDefinition': '8.2',
53
54
  'bpmn:TimerEventDefinition': '1.0'
54
55
  },
55
56
  'bpmn:SubProcess': '1.0',
@@ -27,17 +27,27 @@ module.exports = skipInNonExecutableProcess(function({ version }) {
27
27
  // (1) Element not allowed
28
28
  const allowedVersion = element || null;
29
29
 
30
+ let message = `Element of type <${ node.$type }> not allowed`;
31
+
32
+ let data = {
33
+ type: ERROR_TYPES.ELEMENT_TYPE_NOT_ALLOWED,
34
+ node,
35
+ parentNode: null
36
+ };
37
+
38
+ if (allowedVersion) {
39
+ message = `Element of type <${ node.$type }> only allowed by Camunda Platform ${ allowedVersion } or newer`;
40
+
41
+ data = {
42
+ ...data,
43
+ allowedVersion
44
+ };
45
+ }
46
+
30
47
  const error = {
31
- message: allowedVersion
32
- ? `Element of type <${ node.$type }> only allowed by Camunda Platform ${ allowedVersion } or newer`
33
- : `Element of type <${ node.$type }> not allowed`,
48
+ message,
34
49
  path: null,
35
- data: {
36
- type: ERROR_TYPES.ELEMENT_TYPE_NOT_ALLOWED,
37
- node,
38
- parentNode: null,
39
- allowedVersion
40
- }
50
+ data
41
51
  };
42
52
 
43
53
  reportErrors(node, reporter, error);
@@ -57,18 +67,28 @@ module.exports = skipInNonExecutableProcess(function({ version }) {
57
67
  // (2) Element with event definition not allowed
58
68
  const allowedVersion = element[ eventDefinition.$type ] || null;
59
69
 
70
+ let message = `Element of type <${ node.$type }> with event definition of type <${ eventDefinition.$type }> not allowed`;
71
+
72
+ let data = {
73
+ type: ERROR_TYPES.ELEMENT_TYPE_NOT_ALLOWED,
74
+ node,
75
+ parentNode: null,
76
+ eventDefinition
77
+ };
78
+
79
+ if (allowedVersion) {
80
+ message = `Element of type <${ node.$type }> with event definition of type <${ eventDefinition.$type }> only allowed by Camunda Platform ${ allowedVersion } or newer`;
81
+
82
+ data = {
83
+ ...data,
84
+ allowedVersion
85
+ };
86
+ }
87
+
60
88
  const error = {
61
- message: allowedVersion
62
- ? `Element of type <${ node.$type }> with event definition of type <${ eventDefinition.$type }> only allowed by Camunda Platform ${ allowedVersion } or newer`
63
- : `Element of type <${ node.$type }> with event definition of type <${ eventDefinition.$type }> not allowed`,
89
+ message,
64
90
  path: null,
65
- data: {
66
- type: ERROR_TYPES.ELEMENT_TYPE_NOT_ALLOWED,
67
- node,
68
- parentNode: null,
69
- eventDefinition,
70
- allowedVersion
71
- }
91
+ data
72
92
  };
73
93
 
74
94
  reportErrors(node, reporter, error);
@@ -79,18 +99,28 @@ module.exports = skipInNonExecutableProcess(function({ version }) {
79
99
  // (3) Element without event definition not allowed
80
100
  const allowedVersion = element[ '_' ] || null;
81
101
 
102
+ let message = `Element of type <${ node.$type }> with no event definition not allowed`;
103
+
104
+ let data = {
105
+ type: ERROR_TYPES.ELEMENT_TYPE_NOT_ALLOWED,
106
+ node,
107
+ parentNode: null,
108
+ eventDefinition
109
+ };
110
+
111
+ if (allowedVersion) {
112
+ message = `Element of type <${ node.$type }> with no event definition only allowed by Camunda Platform ${ allowedVersion } or newer`;
113
+
114
+ data = {
115
+ ...data,
116
+ allowedVersion
117
+ };
118
+ }
119
+
82
120
  const error = {
83
- message: allowedVersion
84
- ? `Element of type <${ node.$type }> with no event definition only allowed by Camunda Platform ${ allowedVersion } or newer`
85
- : `Element of type <${ node.$type }> with no event definition not allowed`,
121
+ message,
86
122
  path: null,
87
- data: {
88
- type: ERROR_TYPES.ELEMENT_TYPE_NOT_ALLOWED,
89
- node,
90
- parentNode: null,
91
- eventDefinition,
92
- allowedVersion
93
- }
123
+ data
94
124
  };
95
125
 
96
126
  reportErrors(node, reporter, error);
@@ -47,8 +47,7 @@ module.exports = skipInNonExecutableProcess(function({ version }) {
47
47
 
48
48
  errors = hasProperties(errorRef, {
49
49
  errorCode: {
50
- required: true,
51
- allowedVersion: '8.2'
50
+ required: true
52
51
  }
53
52
  }, node);
54
53
 
@@ -49,10 +49,10 @@ module.exports = skipInNonExecutableProcess(function() {
49
49
  required: true
50
50
  },
51
51
  outputCollection: {
52
- dependendRequired: 'outputElement'
52
+ dependentRequired: 'outputElement'
53
53
  },
54
54
  outputElement: {
55
- dependendRequired: 'outputCollection'
55
+ dependentRequired: 'outputCollection'
56
56
  }
57
57
  }, node);
58
58
 
@@ -68,29 +68,37 @@ function checkForVersion(node, version) {
68
68
  }
69
69
 
70
70
  function noExpression(node, propertyName, parentNode, allowedVersion) {
71
- const propertyValue = node.get(propertyName);
72
- const path = getPath(node, parentNode);
71
+ const path = getPath(node, parentNode),
72
+ propertyValue = node.get(propertyName);
73
73
 
74
74
  if (!isExpression(propertyValue)) {
75
75
  return;
76
76
  }
77
77
 
78
- const errorMessage = allowedVersion ?
79
- `Expression statement <${truncate(propertyValue)}> only supported by Camunda Platform ${allowedVersion} or newer` :
80
- `Expression statement <${truncate(propertyValue)}> not supported`;
78
+ let message = `Expression statement <${truncate(propertyValue)}> not supported`;
79
+
80
+ let data = {
81
+ type: ERROR_TYPES.EXPRESSION_NOT_ALLOWED,
82
+ node,
83
+ parentNode: parentNode == node ? null : parentNode,
84
+ property: propertyName
85
+ };
86
+
87
+ if (allowedVersion) {
88
+ message = `Expression statement <${truncate(propertyValue)}> only supported by Camunda Platform ${allowedVersion} or newer`;
89
+
90
+ data = {
91
+ ...data,
92
+ allowedVersion
93
+ };
94
+ }
81
95
 
82
96
  return {
83
- message: errorMessage,
97
+ message,
84
98
  path: path
85
99
  ? [ ...path, propertyName ]
86
100
  : [ propertyName ],
87
- data: {
88
- type: ERROR_TYPES.EXPRESSION_NOT_ALLOWED,
89
- node,
90
- parentNode: parentNode == node ? null : parentNode,
91
- property: propertyName,
92
- allowedVersion
93
- }
101
+ data
94
102
  };
95
103
  }
96
104
 
@@ -0,0 +1,45 @@
1
+ const { is } = require('bpmnlint-utils');
2
+
3
+ const { reportErrors } = require('./utils/reporter');
4
+
5
+ const { getEventDefinition } = require('./utils/element');
6
+
7
+ const { ERROR_TYPES } = require('./utils/error-types');
8
+
9
+ const { skipInNonExecutableProcess } = require('./utils/rule');
10
+
11
+ module.exports = skipInNonExecutableProcess(function() {
12
+ function check(node, reporter) {
13
+ if (!is(node, 'bpmn:StartEvent')) {
14
+ return;
15
+ }
16
+
17
+ const eventDefinition = getEventDefinition(node);
18
+
19
+ if (!eventDefinition || !is(eventDefinition, 'bpmn:SignalEventDefinition')) {
20
+ return;
21
+ }
22
+
23
+ const { $parent: parent } = node;
24
+
25
+ if (parent && is(parent, 'bpmn:SubProcess')) {
26
+ const error = {
27
+ message: 'Element of type <bpmn:StartEvent> with event definition of type <bpmn:SignalEventDefinition> not allowed as child of <bpmn:SubProcess>',
28
+ path: null,
29
+ data: {
30
+ type: ERROR_TYPES.CHILD_ELEMENT_TYPE_NOT_ALLOWED,
31
+ node,
32
+ parentNode: null,
33
+ eventDefinition,
34
+ parent
35
+ }
36
+ };
37
+
38
+ reportErrors(node, reporter, error);
39
+ }
40
+ }
41
+
42
+ return {
43
+ check
44
+ };
45
+ });
@@ -0,0 +1,19 @@
1
+ const { hasNoExtensionElement } = require('./utils/element');
2
+
3
+ const { reportErrors } = require('./utils/reporter');
4
+
5
+ const { skipInNonExecutableProcess } = require('./utils/rule');
6
+
7
+ module.exports = skipInNonExecutableProcess(function() {
8
+ function check(node, reporter) {
9
+ const errors = hasNoExtensionElement(node, 'zeebe:TaskSchedule', node, '8.2');
10
+
11
+ if (errors && errors.length) {
12
+ reportErrors(node, reporter, errors);
13
+ }
14
+ }
15
+
16
+ return {
17
+ check
18
+ };
19
+ });
@@ -1,5 +1,3 @@
1
- const { is } = require('bpmnlint-utils');
2
-
3
1
  const { hasNoExtensionElement } = require('./utils/element');
4
2
 
5
3
  const { reportErrors } = require('./utils/reporter');
@@ -8,10 +6,6 @@ const { skipInNonExecutableProcess } = require('./utils/rule');
8
6
 
9
7
  module.exports = skipInNonExecutableProcess(function() {
10
8
  function check(node, reporter) {
11
- if (!is(node, 'zeebe:PropertiesHolder')) {
12
- return;
13
- }
14
-
15
9
  const errors = hasNoExtensionElement(node, 'zeebe:Properties', node, '8.1');
16
10
 
17
11
  if (errors && errors.length) {
@@ -0,0 +1,68 @@
1
+ const { is } = require('bpmnlint-utils');
2
+
3
+ const { isDefined } = require('min-dash');
4
+
5
+ const {
6
+ findExtensionElement,
7
+ hasExpression
8
+ } = require('./utils/element');
9
+
10
+ const { validateDate: validateISO8601Date } = require('./utils/iso8601');
11
+
12
+ const { reportErrors } = require('./utils/reporter');
13
+
14
+ const { skipInNonExecutableProcess } = require('./utils/rule');
15
+
16
+ module.exports = skipInNonExecutableProcess(function() {
17
+ function check(node, reporter) {
18
+ if (!is(node, 'bpmn:UserTask')) {
19
+ return;
20
+ }
21
+
22
+ const taskSchedule = findExtensionElement(node, 'zeebe:TaskSchedule');
23
+
24
+ if (!taskSchedule) {
25
+ return;
26
+ }
27
+
28
+ const dueDate = taskSchedule.get('dueDate');
29
+
30
+ let errors = [];
31
+
32
+ if (isDefined(dueDate)) {
33
+ errors = [
34
+ ...errors,
35
+ ...hasExpression(taskSchedule, 'dueDate', {
36
+ allowed: date => isValidDate(date)
37
+ }, node)
38
+ ];
39
+ }
40
+
41
+ const followUpDate = taskSchedule.get('followUpDate');
42
+
43
+ if (isDefined(followUpDate)) {
44
+ errors = [
45
+ ...errors,
46
+ ...hasExpression(taskSchedule, 'followUpDate', {
47
+ allowed: date => isValidDate(date)
48
+ }, node)
49
+ ];
50
+ }
51
+
52
+ if (errors.length) {
53
+ reportErrors(node, reporter, errors);
54
+ }
55
+ }
56
+
57
+ return {
58
+ check
59
+ };
60
+ });
61
+
62
+ function isValidDate(value) {
63
+ return isExpression(value) || validateISO8601Date(value);
64
+ }
65
+
66
+ function isExpression(value) {
67
+ return value.startsWith('=');
68
+ }
@@ -161,23 +161,23 @@ module.exports.hasProperties = function(node, properties, parentNode = null) {
161
161
  ];
162
162
  }
163
163
 
164
- if (propertyChecks.dependendRequired) {
165
- const dependency = node.get(propertyChecks.dependendRequired);
164
+ if (propertyChecks.dependentRequired) {
165
+ const dependency = node.get(propertyChecks.dependentRequired);
166
166
 
167
167
  if (dependency && !propertyValue) {
168
168
  return [
169
169
  ...results,
170
170
  {
171
- message: `Element of type <${ node.$type }> must have property <${ propertyName }> if it has property <${ propertyChecks.dependendRequired }>`,
171
+ message: `Element of type <${ node.$type }> must have property <${ propertyName }> if it has property <${ propertyChecks.dependentRequired }>`,
172
172
  path: path
173
173
  ? [ ...path, propertyName ]
174
174
  : [ propertyName ],
175
175
  data: {
176
- type: ERROR_TYPES.PROPERTY_DEPENDEND_REQUIRED,
176
+ type: ERROR_TYPES.PROPERTY_DEPENDENT_REQUIRED,
177
177
  node,
178
178
  parentNode: parentNode == node ? null : parentNode,
179
- property: propertyChecks.dependendRequired,
180
- dependendRequiredProperty: propertyName
179
+ property: propertyChecks.dependentRequired,
180
+ dependentRequiredProperty: propertyName
181
181
  }
182
182
  }
183
183
  ];
@@ -363,11 +363,15 @@ module.exports.hasExpression = function(node, propertyName, check, parentNode =
363
363
  throw new Error('Expression not found');
364
364
  }
365
365
 
366
- const body = expression.get('body');
366
+ let propertyValue = expression;
367
+
368
+ if (is(expression, 'bpmn:Expression')) {
369
+ propertyValue = expression.get('body');
370
+ }
367
371
 
368
372
  const path = getPath(node, parentNode);
369
373
 
370
- if (!body) {
374
+ if (!propertyValue) {
371
375
  if (check.required !== false) {
372
376
  return [
373
377
  {
@@ -377,7 +381,7 @@ module.exports.hasExpression = function(node, propertyName, check, parentNode =
377
381
  : null,
378
382
  data: {
379
383
  type: ERROR_TYPES.EXPRESSION_REQUIRED,
380
- node: expression,
384
+ node: is(expression, 'bpmn:Expression') ? expression : node,
381
385
  parentNode,
382
386
  property: propertyName
383
387
  }
@@ -388,7 +392,7 @@ module.exports.hasExpression = function(node, propertyName, check, parentNode =
388
392
  return [];
389
393
  }
390
394
 
391
- const allowed = check.allowed(body);
395
+ const allowed = check.allowed(propertyValue);
392
396
 
393
397
  if (allowed !== true) {
394
398
  let allowedVersion = null;
@@ -400,14 +404,14 @@ module.exports.hasExpression = function(node, propertyName, check, parentNode =
400
404
  return [
401
405
  {
402
406
  message: allowedVersion
403
- ? `Expression value of <${ body }> only allowed by Camunda Platform ${ allowedVersion }`
404
- : `Expression value of <${ body }> not allowed`,
407
+ ? `Expression value of <${ propertyValue }> only allowed by Camunda Platform ${ allowedVersion }`
408
+ : `Expression value of <${ propertyValue }> not allowed`,
405
409
  path: path
406
410
  ? [ ...path, propertyName ]
407
411
  : null,
408
412
  data: addAllowedVersion({
409
413
  type: ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED,
410
- node: expression,
414
+ node: is(expression, 'bpmn:Expression') ? expression : node,
411
415
  parentNode,
412
416
  property: propertyName
413
417
  }, allowedVersion)
@@ -1,5 +1,6 @@
1
1
  module.exports.ERROR_TYPES = Object.freeze({
2
2
  ELEMENT_COLLAPSED_NOT_ALLOWED: 'camunda.elementCollapsedNotAllowed',
3
+ CHILD_ELEMENT_TYPE_NOT_ALLOWED: 'camunda.childElementTypeNotAllowed',
3
4
  ELEMENT_TYPE_NOT_ALLOWED: 'camunda.elementTypeNotAllowed',
4
5
  EXPRESSION_NOT_ALLOWED: 'camunda.expressionNotAllowed',
5
6
  EXPRESSION_REQUIRED: 'camunda.expressionRequired',
@@ -7,7 +8,7 @@ module.exports.ERROR_TYPES = Object.freeze({
7
8
  EXTENSION_ELEMENT_NOT_ALLOWED: 'camunda.extensionElementNotAllowed',
8
9
  EXTENSION_ELEMENT_REQUIRED: 'camunda.extensionElementRequired',
9
10
  FEEL_EXPRESSION_INVALID: 'camunda.feelExpressionInvalid',
10
- PROPERTY_DEPENDEND_REQUIRED: 'camunda.propertyDependendRequired',
11
+ PROPERTY_DEPENDENT_REQUIRED: 'camunda.propertyDependentRequired',
11
12
  PROPERTY_NOT_ALLOWED: 'camunda.propertyNotAllowed',
12
13
  PROPERTY_REQUIRED: 'camunda.propertyRequired',
13
14
  PROPERTY_TYPE_NOT_ALLOWED: 'camunda.propertyTypeNotAllowed',