bpmnlint 11.1.0 → 11.3.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/lib/types.d.ts CHANGED
@@ -1,5 +1,81 @@
1
1
  export type ModdleElement = any;
2
2
 
3
- export type EnterFn = (element: ModdleElement) => boolean | null;
3
+ export interface Reporter {
4
4
 
5
- export type LeaveFn = (element: ModdleElement) => void;
5
+ report(id: string, message: string): void;
6
+
7
+ report(id: string, message: string, path: string[]): void;
8
+
9
+ report(id: string, message: string, context: {
10
+ path?: string[],
11
+ [key: string]: any
12
+ }) : void;
13
+ }
14
+
15
+ export interface Resolver {
16
+
17
+ resolveRule(pkg: string, ruleName: string): Promise<RuleFactory> | RuleFactory,
18
+
19
+ resolveConfig(pkg: string, configName: string): Promise<Config> | Config;
20
+ }
21
+
22
+ export type EnterFn = (element: ModdleElement, reporter: Reporter) => boolean | void;
23
+
24
+ export type LeaveFn = (element: ModdleElement, reporter: Reporter) => void;
25
+
26
+ export type CheckDefinition = EnterFn | {
27
+ enter: EnterFn
28
+ } | {
29
+ leave: LeaveFn
30
+ } | {
31
+ enter: EnterFn,
32
+ leave: LeaveFn
33
+ };
34
+
35
+ export type RuleDefinition = {
36
+ meta?: {
37
+ documentation?: {
38
+ url?: string
39
+ }
40
+ },
41
+ check: CheckDefinition
42
+ };
43
+
44
+ export type RuleFactory = (ruleOptions?: any) => RuleDefinition;
45
+
46
+ export type ReportingCategoryMap = {
47
+ 0: 'off',
48
+ 1: 'warn',
49
+ 2: 'error',
50
+ 3: 'info'
51
+ };
52
+
53
+ export type ReportingCategoryIndex = keyof ReportingCategoryMap;
54
+ export type ReportingCategory = ReportingCategoryMap[ReportingCategoryIndex];
55
+
56
+ export type RuleErrorCategory = 'rule-error';
57
+
58
+ export type RuleConfig =
59
+ ReportingCategoryIndex |
60
+ ReportingCategory |
61
+ [ ReportingCategoryIndex, config?: any ] |
62
+ [ ReportingCategory, config?: any ];
63
+
64
+ export type RuleConfigs = Record<string, RuleConfig>;
65
+
66
+ export type Config = {
67
+ extends?: string | string[],
68
+ rules?: RuleConfigs
69
+ };
70
+
71
+ export type TransformRuleFn = (
72
+ rule: RuleDefinition,
73
+ options: { pkg: string, ruleName: string }
74
+ ) => RuleDefinition;
75
+
76
+ export type Report = {
77
+ id?: string,
78
+ path?: string[],
79
+ message: string,
80
+ [key: string]: any
81
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bpmnlint",
3
3
  "description": "Validate your BPMN diagrams based on configurable lint rules",
4
- "version": "11.1.0",
4
+ "version": "11.3.0",
5
5
  "main": "lib/index.js",
6
6
  "keywords": [
7
7
  "bpmnlint",
@@ -27,8 +27,9 @@
27
27
  },
28
28
  "license": "MIT",
29
29
  "scripts": {
30
- "all": "run-s lint test-coverage",
30
+ "all": "run-s lint lint:types test-coverage",
31
31
  "lint": "eslint .",
32
+ "lint:types": "tsc",
32
33
  "dev": "npm test -- --watch",
33
34
  "test": "mocha --exclude 'test/integration/*/**' 'test/**/*.*js'",
34
35
  "test-coverage": "nyc --reporter=lcov --reporter=html npm test",
@@ -44,22 +45,24 @@
44
45
  "bpmnlint-utils": "^1.1.1",
45
46
  "cli-table": "^0.3.11",
46
47
  "color-support": "^1.1.3",
47
- "min-dash": "^4.2.2",
48
+ "min-dash": "^4.2.3",
48
49
  "mri": "^1.2.0",
49
50
  "pluralize": "^7.0.0",
50
51
  "tiny-glob": "^0.2.9"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@bpmn-io/bpmnlint-generate-docs-images": "^0.4.0",
55
+ "@types/mocha": "^10.0.10",
54
56
  "chai": "^4.5.0",
55
57
  "eslint": "^9.17.0",
56
- "eslint-plugin-bpmn-io": "^2.0.2",
58
+ "eslint-plugin-bpmn-io": "^2.2.0",
57
59
  "execa": "^9.5.2",
58
60
  "install-local": "^3.0.1",
59
61
  "mocha": "^11.0.1",
60
62
  "npm-run-all": "^4.1.5",
61
63
  "nyc": "^17.1.0",
62
- "strip-indent": "^3.0.0"
64
+ "strip-indent": "^3.0.0",
65
+ "typescript": "^5.7.3"
63
66
  },
64
67
  "files": [
65
68
  "bin",
@@ -3,11 +3,18 @@ const {
3
3
  isAny
4
4
  } = require('bpmnlint-utils');
5
5
 
6
+ const {
7
+ annotateRule
8
+ } = require('./helper');
9
+
10
+
6
11
  /**
7
12
  * A rule that ensures that an Ad Hoc Sub Process is valid according to the BPMN spec:
8
13
  *
9
14
  * - No start or end events
10
15
  * - Every intermediate event has an outgoing sequence flow
16
+ *
17
+ * @type { import('../lib/types.js').RuleFactory }
11
18
  */
12
19
  module.exports = function() {
13
20
 
@@ -38,8 +45,8 @@ module.exports = function() {
38
45
  });
39
46
  }
40
47
 
41
- return {
48
+ return annotateRule('ad-hoc-sub-process', {
42
49
  check
43
- };
50
+ });
44
51
 
45
52
  };
@@ -1,7 +1,14 @@
1
+ const {
2
+ annotateRule
3
+ } = require('./helper');
4
+
5
+
1
6
  /**
2
7
  * A rule that checks that sequence flows outgoing from a
3
8
  * conditional forking gateway or activity are
4
9
  * either default flows _or_ have a condition attached
10
+ *
11
+ * @type { import('../lib/types.js').RuleFactory }
5
12
  */
6
13
  module.exports = function() {
7
14
 
@@ -25,9 +32,9 @@ module.exports = function() {
25
32
  });
26
33
  }
27
34
 
28
- return {
35
+ return annotateRule('conditional-flows', {
29
36
  check
30
- };
37
+ });
31
38
 
32
39
  };
33
40
 
@@ -3,9 +3,15 @@ const {
3
3
  isAny
4
4
  } = require('bpmnlint-utils');
5
5
 
6
+ const {
7
+ annotateRule
8
+ } = require('./helper');
9
+
6
10
 
7
11
  /**
8
12
  * A rule that checks the presence of an end event per scope.
13
+ *
14
+ * @type { import('../lib/types.js').RuleFactory }
9
15
  */
10
16
  module.exports = function() {
11
17
 
@@ -33,5 +39,7 @@ module.exports = function() {
33
39
  }
34
40
  }
35
41
 
36
- return { check };
42
+ return annotateRule('end-event-required', {
43
+ check
44
+ });
37
45
  };
@@ -2,9 +2,16 @@ const {
2
2
  is
3
3
  } = require('bpmnlint-utils');
4
4
 
5
+ const {
6
+ annotateRule
7
+ } = require('./helper');
8
+
9
+
5
10
  /**
6
11
  * A rule that checks that start events inside an event sub-process
7
12
  * are typed.
13
+ *
14
+ * @type { import('../lib/types.js').RuleFactory }
8
15
  */
9
16
  module.exports = function() {
10
17
 
@@ -30,8 +37,8 @@ module.exports = function() {
30
37
  });
31
38
  }
32
39
 
33
- return {
40
+ return annotateRule('event-sub-process-typed-start-event', {
34
41
  check
35
- };
42
+ });
36
43
 
37
44
  };
@@ -2,12 +2,19 @@ const {
2
2
  isAny
3
3
  } = require('bpmnlint-utils');
4
4
 
5
+ const {
6
+ annotateRule
7
+ } = require('./helper');
8
+
9
+
5
10
  /**
6
11
  * A rule that checks that no fake join is modeled by attempting
7
12
  * to give a task or event join semantics.
8
13
  *
9
14
  * Users should model a parallel joining gateway
10
15
  * to achieve the desired behavior.
16
+ *
17
+ * @type { import('../lib/types.js').RuleFactory }
11
18
  */
12
19
  module.exports = function() {
13
20
 
@@ -27,8 +34,8 @@ module.exports = function() {
27
34
  }
28
35
  }
29
36
 
30
- return {
37
+ return annotateRule('fake-join', {
31
38
  check
32
- };
39
+ });
33
40
 
34
41
  };
package/rules/global.js CHANGED
@@ -3,6 +3,10 @@ const {
3
3
  isAny
4
4
  } = require('bpmnlint-utils');
5
5
 
6
+ const {
7
+ annotateRule
8
+ } = require('./helper');
9
+
6
10
 
7
11
  /**
8
12
  * A rule that verifies that global elements are properly used.
@@ -19,6 +23,8 @@ const {
19
23
  * * element must have a name
20
24
  * * element is referenced by at least one element
21
25
  * * there exists only a single element per type with a given name
26
+ *
27
+ * @type { import('../lib/types.js').RuleFactory }
22
28
  */
23
29
  module.exports = function() {
24
30
 
@@ -48,9 +54,9 @@ module.exports = function() {
48
54
 
49
55
  }
50
56
 
51
- return {
57
+ return annotateRule('global', {
52
58
  check
53
- };
59
+ });
54
60
 
55
61
  // helpers /////////////////////////////
56
62
 
package/rules/helper.js CHANGED
@@ -2,15 +2,26 @@ const {
2
2
  is
3
3
  } = require('bpmnlint-utils');
4
4
 
5
+ /**
6
+ * @typedef { import('../lib/types.js').ModdleElement } ModdleElement
7
+ *
8
+ * @typedef { import('../lib/types.js').RuleFactory } RuleFactory
9
+ * @typedef { import('../lib/types.js').RuleDefinition } RuleDefinition
10
+ */
11
+
12
+
5
13
  /**
6
14
  * Create a checker that disallows the given element type.
7
15
  *
8
- * @param {String} type
16
+ * @param { string } type
9
17
  *
10
- * @return {Function} ruleImpl
18
+ * @return { RuleFactory } ruleFactory
11
19
  */
12
- function disallowNodeType(type) {
20
+ function disallowNodeType(type, ruleName) {
13
21
 
22
+ /**
23
+ * @type { RuleFactory }
24
+ */
14
25
  return function() {
15
26
 
16
27
  function check(node, reporter) {
@@ -20,9 +31,9 @@ function disallowNodeType(type) {
20
31
  }
21
32
  }
22
33
 
23
- return {
34
+ return annotateRule(ruleName, {
24
35
  check
25
- };
36
+ });
26
37
 
27
38
  };
28
39
 
@@ -30,16 +41,15 @@ function disallowNodeType(type) {
30
41
 
31
42
  module.exports.disallowNodeType = disallowNodeType;
32
43
 
44
+
33
45
  /**
34
46
  * Find a parent for the given element
35
47
  *
36
- * @param {ModdleElement} node
48
+ * @param { ModdleElement } node
49
+ * @param { string } type
37
50
  *
38
- * @param {String} type
39
- *
40
- * @return {ModdleElement} element
51
+ * @return { ModdleElement } element
41
52
  */
42
-
43
53
  function findParent(node, type) {
44
54
  if (!node) {
45
55
  return null;
@@ -58,4 +68,41 @@ function findParent(node, type) {
58
68
  return findParent(parent, type);
59
69
  }
60
70
 
61
- module.exports.findParent = findParent;
71
+ module.exports.findParent = findParent;
72
+
73
+
74
+ const documentationBaseUrl = 'https://github.com/bpmn-io/bpmnlint/blob/main/docs/rules';
75
+
76
+ /**
77
+ * Annotate a rule with core information, such as the documentation url.
78
+ *
79
+ * @param {string} ruleName
80
+ * @param {RuleDefinition} options
81
+ *
82
+ * @return {RuleDefinition}
83
+ */
84
+ function annotateRule(ruleName, options) {
85
+
86
+ const {
87
+ meta: {
88
+ documentation = {},
89
+ ...restMeta
90
+ } = {},
91
+ ...restOptions
92
+ } = options;
93
+
94
+ const documentationUrl = `${documentationBaseUrl}/${ruleName}.md`;
95
+
96
+ return {
97
+ meta: {
98
+ documentation: {
99
+ url: documentationUrl,
100
+ ...documentation
101
+ },
102
+ ...restMeta
103
+ },
104
+ ...restOptions
105
+ };
106
+ }
107
+
108
+ module.exports.annotateRule = annotateRule;
@@ -3,9 +3,15 @@ const {
3
3
  isAny
4
4
  } = require('bpmnlint-utils');
5
5
 
6
+ const {
7
+ annotateRule
8
+ } = require('./helper');
9
+
6
10
 
7
11
  /**
8
12
  * A rule that checks the presence of a label.
13
+ *
14
+ * @type { import('../lib/types.js').RuleFactory }
9
15
  */
10
16
  module.exports = function() {
11
17
 
@@ -51,7 +57,9 @@ module.exports = function() {
51
57
  }
52
58
  }
53
59
 
54
- return { check };
60
+ return annotateRule('label-required', {
61
+ check
62
+ });
55
63
  };
56
64
 
57
65
 
@@ -6,6 +6,10 @@ const {
6
6
  is
7
7
  } = require('bpmnlint-utils');
8
8
 
9
+ const {
10
+ annotateRule
11
+ } = require('./helper');
12
+
9
13
 
10
14
  /**
11
15
  * A rule that verifies that link events are properly used.
@@ -18,6 +22,7 @@ const {
18
22
  * with a given name, per scope
19
23
  * * link events have a name
20
24
  *
25
+ * @type { import('../lib/types.js').RuleFactory }
21
26
  */
22
27
  module.exports = function() {
23
28
 
@@ -70,9 +75,9 @@ module.exports = function() {
70
75
 
71
76
  }
72
77
 
73
- return {
78
+ return annotateRule('link-event', {
74
79
  check
75
- };
80
+ });
76
81
  };
77
82
 
78
83
 
@@ -6,9 +6,20 @@ const {
6
6
  flatten
7
7
  } = require('min-dash');
8
8
 
9
+ const {
10
+ annotateRule
11
+ } = require('./helper');
12
+
13
+ /**
14
+ * @typedef { import('../lib/types.js').ModdleElement } ModdleElement
15
+ */
16
+
17
+
9
18
  /**
10
19
  * A rule that checks that there is no BPMNDI information missing for elements,
11
20
  * which require BPMNDI.
21
+ *
22
+ * @type { import('../lib/types.js').RuleFactory }
12
23
  */
13
24
  module.exports = function() {
14
25
 
@@ -35,9 +46,9 @@ module.exports = function() {
35
46
  });
36
47
  }
37
48
 
38
- return {
49
+ return annotateRule('no-bpmndi', {
39
50
  check
40
- };
51
+ });
41
52
 
42
53
  };
43
54
 
@@ -47,11 +58,12 @@ module.exports = function() {
47
58
  /**
48
59
  * Get all BPMN elements within a bpmn:Definitions node
49
60
  *
50
- * @param {array<ModdleElement>} rootElements - An array of Moddle rootElements
51
- * @return {array<Object>} A flat array with all BPMN elements, each represented with { id: elementId, $type: elementType }
61
+ * @param { ModdleElement[] } rootElements - An array of Moddle rootElements
52
62
  *
63
+ * @return { { id: string, $type: string }[] } A flat array with all BPMN elements, each represented with { id: elementId, $type: elementType }
53
64
  */
54
65
  function getAllBpmnElements(rootElements) {
66
+
55
67
  return flatten(rootElements.map((rootElement) => {
56
68
  const laneSet =
57
69
  rootElement.laneSets && rootElement.laneSets[0] || rootElement.childLaneSet;
@@ -66,7 +78,7 @@ function getAllBpmnElements(rootElements) {
66
78
  // * childLaneSets
67
79
  // * nested childLaneSets
68
80
  // * messageFlows
69
- const elements = flatten([].concat(
81
+ const elements = flatten([
70
82
  rootElement.flowElements || [],
71
83
  (rootElement.flowElements && getAllBpmnElements(rootElement.flowElements.filter(hasFlowElements))) || [],
72
84
  rootElement.participants || [],
@@ -74,7 +86,7 @@ function getAllBpmnElements(rootElements) {
74
86
  laneSet && laneSet.lanes || [],
75
87
  laneSet && laneSet.lanes && getAllBpmnElements(laneSet.lanes.filter(hasChildLaneSet)) || [],
76
88
  rootElement.messageFlows || []
77
- ));
89
+ ]);
78
90
 
79
91
  if (elements.length > 0) {
80
92
  return elements.map((element) => {
@@ -96,10 +108,10 @@ function getAllBpmnElements(rootElements) {
96
108
  * Get all BPMN elements within a bpmn:Definitions node
97
109
  *
98
110
  * @param {ModdleElement} definitionsNode - A moddleElement representing the
99
- * bpmn:Definitions element
100
- * @return {array<String>} A flat array with all BPMNDI element ids part of
101
- * this bpmn:Definitions node
111
+ * bpmn:Definitions element
102
112
  *
113
+ * @return {string[]} ids of all BPMNDI element part of
114
+ * this bpmn:Definitions node
103
115
  */
104
116
  function getAllDiBpmnReferences(definitionsNode) {
105
117
  return flatten(
@@ -115,16 +127,31 @@ function getAllDiBpmnReferences(definitionsNode) {
115
127
  );
116
128
  }
117
129
 
130
+ /**
131
+ * @param { ModdleElement } element
132
+ *
133
+ * @return {boolean}
134
+ */
118
135
  function hasVisualRepresentation(element) {
119
136
  const noVisRepresentation = [ 'bpmn:DataObject' ];
120
137
 
121
138
  return noVisRepresentation.includes(element.$type) ? false : true;
122
139
  }
123
140
 
141
+ /**
142
+ * @param { ModdleElement } element
143
+ *
144
+ * @return {boolean}
145
+ */
124
146
  function hasFlowElements(element) {
125
147
  return element.flowElements ? true : false;
126
148
  }
127
149
 
150
+ /**
151
+ * @param { ModdleElement } element
152
+ *
153
+ * @return {boolean}
154
+ */
128
155
  function hasChildLaneSet(element) {
129
156
  return element.childLaneSet ? true : false;
130
157
  }
@@ -1,3 +1,3 @@
1
1
  const disallowNodeType = require('./helper').disallowNodeType;
2
2
 
3
- module.exports = disallowNodeType('bpmn:ComplexGateway');
3
+ module.exports = disallowNodeType('bpmn:ComplexGateway', 'no-complex-gateway');
@@ -3,11 +3,16 @@ const {
3
3
  is
4
4
  } = require('bpmnlint-utils');
5
5
 
6
+ const {
7
+ annotateRule
8
+ } = require('./helper');
9
+
6
10
 
7
11
  /**
8
12
  * A rule that verifies that there exists no disconnected
9
- * flow elements, i.e. elements without incoming
10
- * _or_ outgoing sequence flows
13
+ * flow elements, i.e. elements without incoming or outgoing sequence flows.
14
+ *
15
+ * @type { import('../lib/types.js').RuleFactory }
11
16
  */
12
17
  module.exports = function() {
13
18
 
@@ -37,9 +42,9 @@ module.exports = function() {
37
42
  }
38
43
  }
39
44
 
40
- return {
45
+ return annotateRule('no-disconnected', {
41
46
  check
42
- };
47
+ });
43
48
  };
44
49
 
45
50
 
@@ -2,10 +2,16 @@ const {
2
2
  is
3
3
  } = require('bpmnlint-utils');
4
4
 
5
+ const {
6
+ annotateRule
7
+ } = require('./helper');
8
+
9
+
5
10
  /**
6
11
  * A rule that verifies that there are no disconnected
7
- * flow elements, i.e. elements without incoming
8
- * _or_ outgoing sequence flows
12
+ * flow elements, i.e. elements without incoming or outgoing sequence flows.
13
+ *
14
+ * @type { import('../lib/types.js').RuleFactory }
9
15
  */
10
16
  module.exports = function() {
11
17
 
@@ -44,9 +50,9 @@ module.exports = function() {
44
50
  }
45
51
  }
46
52
 
47
- return {
53
+ return annotateRule('no-duplicate-sequence-flows', {
48
54
  check
49
- };
55
+ });
50
56
 
51
57
  };
52
58
 
@@ -2,10 +2,16 @@ const {
2
2
  is
3
3
  } = require('bpmnlint-utils');
4
4
 
5
+ const {
6
+ annotateRule
7
+ } = require('./helper');
8
+
5
9
 
6
10
  /**
7
11
  * A rule that checks, whether a gateway forks and joins
8
12
  * at the same time.
13
+ *
14
+ * @type { import('../lib/types.js').RuleFactory }
9
15
  */
10
16
  module.exports = function() {
11
17
 
@@ -23,8 +29,8 @@ module.exports = function() {
23
29
  }
24
30
  }
25
31
 
26
- return {
32
+ return annotateRule('no-gateway-fork-join', {
27
33
  check
28
- };
34
+ });
29
35
 
30
36
  };
@@ -4,11 +4,15 @@ const {
4
4
  } = require('bpmnlint-utils');
5
5
 
6
6
  const {
7
- findParent
7
+ findParent,
8
+ annotateRule
8
9
  } = require('./helper');
9
10
 
11
+
10
12
  /**
11
13
  * A rule that checks that an element is not an implicit end (token sink).
14
+ *
15
+ * @type { import('../lib/types.js').RuleFactory }
12
16
  */
13
17
  module.exports = function() {
14
18
 
@@ -85,5 +89,7 @@ module.exports = function() {
85
89
  }
86
90
  }
87
91
 
88
- return { check };
92
+ return annotateRule('no-implicit-end', {
93
+ check
94
+ });
89
95
  };