bpmnlint-plugin-camunda-compat 1.2.0 → 1.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmnlint-plugin-camunda-compat",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "A bpmnlint plug-in for Camunda Platform compatibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,4 +1,47 @@
1
+ const { is } = require('bpmnlint-utils');
2
+
1
3
  module.exports = {
2
- 'cron': '8.1',
3
- 'iso8601': '1.0'
4
- };
4
+ expressionType: {
5
+ 'cron': '8.1',
6
+ 'iso8601': '1.0'
7
+ },
8
+ elementType: {
9
+ 'bpmn:StartEvent': {
10
+ 'timeCycle': (isInterrupting, parent) => {
11
+ if (!isInterrupting || !isEventSubProcess(parent)) {
12
+ return '1.0';
13
+ }
14
+
15
+ return null;
16
+ },
17
+ 'timeDate': () => '1.0',
18
+ 'timeDuration': (_, parent) => {
19
+ if (isEventSubProcess(parent)) {
20
+ return '1.0';
21
+ }
22
+
23
+ return null;
24
+ }
25
+ },
26
+ 'bpmn:BoundaryEvent': {
27
+ 'timeCycle': (cancelActivity) => {
28
+ if (!cancelActivity) {
29
+ return '1.0';
30
+ }
31
+
32
+ return null;
33
+ },
34
+ 'timeDate': () => '8.3',
35
+ 'timeDuration': () => '1.0'
36
+ },
37
+ 'bpmn:IntermediateCatchEvent': {
38
+ 'timeCycle': () => null,
39
+ 'timeDate': () => '8.3',
40
+ 'timeDuration': () => '1.0'
41
+ }
42
+ }
43
+ };
44
+
45
+ function isEventSubProcess(element) {
46
+ return is(element, 'bpmn:SubProcess') && element.get('triggeredByEvent') === true;
47
+ }
@@ -2,14 +2,16 @@ const {
2
2
  is
3
3
  } = require('bpmnlint-utils');
4
4
 
5
- const config = require('./config');
5
+ const {
6
+ elementType: elementTypeConfig,
7
+ expressionType: expressionTypeConfig
8
+ } = require('./config');
6
9
 
7
10
  const { greaterOrEqual } = require('../utils/version');
8
11
 
9
12
  const {
10
13
  getEventDefinition,
11
14
  hasExpression,
12
- hasProperties,
13
15
  hasProperty
14
16
  } = require('../utils/element');
15
17
 
@@ -37,7 +39,7 @@ module.exports = skipInNonExecutableProcess(function({ version }) {
37
39
  return;
38
40
  }
39
41
 
40
- let errors = checkTimePropertyExists(eventDefinition, node);
42
+ let errors = checkTimePropertyExists(eventDefinition, node, version);
41
43
 
42
44
  if (errors && errors.length) {
43
45
  reportErrors(node, reporter, errors);
@@ -57,20 +59,8 @@ module.exports = skipInNonExecutableProcess(function({ version }) {
57
59
  };
58
60
  });
59
61
 
60
- function checkTimePropertyExists(eventDefinition, event) {
61
- if (is(event, 'bpmn:StartEvent')) {
62
- return hasProperty(eventDefinition, [ 'timeCycle', 'timeDate' ], event);
63
- } else if (is(event, 'bpmn:IntermediateCatchEvent') || isInterruptingBoundaryEvent(event)) {
64
- return hasProperties(eventDefinition, {
65
- timeDuration: {
66
- required: true
67
- }
68
- }, event);
69
- } else if (is(event, 'bpmn:BoundaryEvent')) {
70
- return hasProperty(eventDefinition, [ 'timeCycle', 'timeDuration' ], event);
71
- }
72
-
73
- return [];
62
+ function checkTimePropertyExists(eventDefinition, node, version) {
63
+ return hasProperty(eventDefinition, getSupportedTimePropertiesForVersion(node, version), node);
74
64
  }
75
65
 
76
66
  function checkTimeProperty(eventDefinition, event, version) {
@@ -95,32 +85,28 @@ function checkTimeProperty(eventDefinition, event, version) {
95
85
 
96
86
 
97
87
 
98
- // helper //////////////
99
- function isInterruptingBoundaryEvent(event) {
100
- return is(event, 'bpmn:BoundaryEvent') && event.get('cancelActivity') !== false;
101
- }
102
-
103
- function validateDate(date, version) {
104
- if (validateExpression(date)) {
105
- return true;
106
- }
107
-
108
- if (validateISO8601Date(date)) {
109
- return greaterOrEqual(version, config.iso8601);
110
- }
111
- }
112
-
88
+ // helpers //////////
113
89
  function validateCycle(cycle, version) {
114
90
  if (validateExpression(cycle)) {
115
91
  return true;
116
92
  }
117
93
 
118
94
  if (validateISO8601Cycle(cycle)) {
119
- return greaterOrEqual(version, config.iso8601);
95
+ return greaterOrEqual(version, expressionTypeConfig.iso8601);
120
96
  }
121
97
 
122
98
  if (validateCronExpression(cycle)) {
123
- return greaterOrEqual(version, config.cron) || { allowedVersion: config.cron };
99
+ return greaterOrEqual(version, expressionTypeConfig.cron) || { allowedVersion: expressionTypeConfig.cron };
100
+ }
101
+ }
102
+
103
+ function validateDate(date, version) {
104
+ if (validateExpression(date)) {
105
+ return true;
106
+ }
107
+
108
+ if (validateISO8601Date(date)) {
109
+ return greaterOrEqual(version, expressionTypeConfig.iso8601);
124
110
  }
125
111
  }
126
112
 
@@ -130,7 +116,7 @@ function validateDuration(duration, version) {
130
116
  }
131
117
 
132
118
  if (validateISO8601Duration(duration)) {
133
- return greaterOrEqual(version, config.iso8601);
119
+ return greaterOrEqual(version, expressionTypeConfig.iso8601);
134
120
  }
135
121
  }
136
122
 
@@ -139,3 +125,21 @@ function validateExpression(text) {
139
125
  return true;
140
126
  }
141
127
  }
128
+
129
+ function getSupportedTimePropertiesForVersion(element, version) {
130
+ const config = elementTypeConfig[ element.$type ];
131
+
132
+ return Object.keys(config).filter((property) => {
133
+ const supportedVersion = config[ property ](isInterrupting(element), element.$parent);
134
+
135
+ return supportedVersion && greaterOrEqual(version, supportedVersion);
136
+ });
137
+ }
138
+
139
+ function isInterrupting(element) {
140
+ if (is(element, 'bpmn:BoundaryEvent')) {
141
+ return element.get('cancelActivity') !== false;
142
+ }
143
+
144
+ return element.get('isInterrupting') !== false;
145
+ }
@@ -68,24 +68,24 @@ function findExtensionElement(node, types) {
68
68
 
69
69
  module.exports.findExtensionElement = findExtensionElement;
70
70
 
71
- function formatTypes(types, exclusive = false) {
72
- return types.reduce((string, type, index) => {
71
+ function formatNames(names, exclusive = false) {
72
+ return names.reduce((string, name, index) => {
73
73
 
74
74
  // first
75
75
  if (index === 0) {
76
- return `<${ type }>`;
76
+ return `<${ name }>`;
77
77
  }
78
78
 
79
79
  // last
80
- if (index === types.length - 1) {
81
- return `${ string } ${ exclusive ? 'or' : 'and' } <${ type }>`;
80
+ if (index === names.length - 1) {
81
+ return `${ string } ${ exclusive ? 'or' : 'and' } <${ name }>`;
82
82
  }
83
83
 
84
- return `${ string }, <${ type }>`;
84
+ return `${ string }, <${ name }>`;
85
85
  }, '');
86
86
  }
87
87
 
88
- module.exports.formatTypes = formatTypes;
88
+ module.exports.formatNames = formatNames;
89
89
 
90
90
  module.exports.hasDuplicatedPropertyValues = function(node, propertiesName, propertyName, parentNode = null) {
91
91
  const properties = node.get(propertiesName);
@@ -276,21 +276,21 @@ module.exports.hasProperties = function(node, properties, parentNode = null) {
276
276
  }, []);
277
277
  };
278
278
 
279
- module.exports.hasProperty = function(node, types, parentNode = null) {
280
- const typesArray = isArray(types) ? types : [ types ];
279
+ module.exports.hasProperty = function(node, propertyNames, parentNode = null) {
280
+ propertyNames = isArray(propertyNames) ? propertyNames : [ propertyNames ];
281
281
 
282
- const properties = findProperties(node, typesArray);
282
+ const properties = findProperties(node, propertyNames);
283
283
 
284
284
  if (properties.length !== 1) {
285
285
  return [
286
286
  {
287
- message: `Element of type <${ node.$type }> must have one property of type ${ formatTypes(typesArray, true) }`,
287
+ message: `Element of type <${ node.$type }> must have property ${ formatNames(propertyNames, true) }`,
288
288
  path: getPath(node, parentNode),
289
289
  data: {
290
290
  type: ERROR_TYPES.PROPERTY_REQUIRED,
291
291
  node,
292
292
  parentNode: parentNode == node ? null : parentNode,
293
- requiredProperty: types
293
+ requiredProperty: propertyNames
294
294
  }
295
295
  }
296
296
  ];
@@ -299,11 +299,12 @@ module.exports.hasProperty = function(node, types, parentNode = null) {
299
299
  return [];
300
300
  };
301
301
 
302
- function findProperties(node, types) {
302
+ function findProperties(node, propertyNames) {
303
303
  const properties = [];
304
- for (const type of types) {
305
- if (isDefined(node.get(type))) {
306
- properties.push(node.get(type));
304
+
305
+ for (const propertyName of propertyNames) {
306
+ if (isDefined(node.get(propertyName))) {
307
+ properties.push(node.get(propertyName));
307
308
  }
308
309
  }
309
310
 
@@ -318,7 +319,7 @@ module.exports.hasExtensionElement = function(node, types, parentNode = null) {
318
319
  if (!extensionElements || extensionElements.length !== 1) {
319
320
  return [
320
321
  {
321
- message: `Element of type <${ node.$type }> must have one extension element of type ${ formatTypes(typesArray, true) }`,
322
+ message: `Element of type <${ node.$type }> must have one extension element of type ${ formatNames(typesArray, true) }`,
322
323
  path: getPath(node, parentNode),
323
324
  data: {
324
325
  type: ERROR_TYPES.EXTENSION_ELEMENT_REQUIRED,