bpmnlint 10.2.3 → 10.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/config/all.js +1 -0
- package/config/recommended.js +1 -0
- package/lib/testers/rule-tester.d.ts +37 -0
- package/lib/traverse.js +6 -1
- package/lib/types.d.ts +5 -0
- package/package.json +6 -6
- package/rules/global.js +117 -0
package/config/all.js
CHANGED
package/config/recommended.js
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type TestFn = (...any) => any;
|
|
2
|
+
|
|
3
|
+
export type ModdleElement = any;
|
|
4
|
+
|
|
5
|
+
export type ValidRuleTest = {
|
|
6
|
+
config?: any,
|
|
7
|
+
it?: TestFn,
|
|
8
|
+
moddleElement: ModdleElement,
|
|
9
|
+
name?: string
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type InvalidReport = {
|
|
13
|
+
id: string,
|
|
14
|
+
message: string
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type InvalidRuleTest = {
|
|
18
|
+
config?: any,
|
|
19
|
+
it?: TestFn,
|
|
20
|
+
moddleElement: ModdleElement,
|
|
21
|
+
name?: string,
|
|
22
|
+
report: InvalidReport | InvalidReport[]
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type RuleTests = {
|
|
26
|
+
valid?: ValidRuleTest[],
|
|
27
|
+
invalid?: InvalidRuleTest[]
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Verify a rule.
|
|
32
|
+
*
|
|
33
|
+
* @param ruleName
|
|
34
|
+
* @param rule the rule implementation
|
|
35
|
+
* @param tests the tests to verify
|
|
36
|
+
*/
|
|
37
|
+
export function verify(ruleName: string, rule: any, tests: RuleTests): void;
|
package/lib/traverse.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef { import('./types.js').EnterFn } EnterFn
|
|
3
|
+
* @typedef { import('./types.js').LeaveFn } LeaveFn
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* Traverse a moddle tree, depth first from top to bottom
|
|
3
8
|
* and call the passed visitor fn.
|
|
4
9
|
*
|
|
5
10
|
* @param {ModdleElement} element
|
|
6
|
-
* @param {{ enter?:
|
|
11
|
+
* @param {{ enter?: EnterFn; leave?: LeaveFn }} options
|
|
7
12
|
*/
|
|
8
13
|
module.exports = function traverse(element, options) {
|
|
9
14
|
|
package/lib/types.d.ts
ADDED
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": "10.
|
|
4
|
+
"version": "10.3.0",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"bpmnlint",
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@bpmn-io/moddle-utils": "^0.2.1",
|
|
42
42
|
"ansi-colors": "^4.1.3",
|
|
43
|
-
"bpmn-moddle": "^8.0
|
|
43
|
+
"bpmn-moddle": "^8.1.0",
|
|
44
44
|
"bpmnlint-utils": "^1.1.1",
|
|
45
45
|
"cli-table": "^0.3.11",
|
|
46
46
|
"color-support": "^1.1.3",
|
|
47
|
-
"min-dash": "^4.
|
|
47
|
+
"min-dash": "^4.2.1",
|
|
48
48
|
"mri": "^1.2.0",
|
|
49
49
|
"pluralize": "^7.0.0",
|
|
50
50
|
"tiny-glob": "^0.2.9"
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@bpmn-io/bpmnlint-generate-docs-images": "^0.4.0",
|
|
54
54
|
"bpmnlint": ".",
|
|
55
|
-
"chai": "^4.
|
|
56
|
-
"eslint": "^8.
|
|
55
|
+
"chai": "^4.4.1",
|
|
56
|
+
"eslint": "^8.57.0",
|
|
57
57
|
"eslint-plugin-bpmn-io": "^1.0.0",
|
|
58
58
|
"execa": "^8.0.1",
|
|
59
59
|
"install-local": "^3.0.1",
|
|
60
|
-
"mocha": "^10.
|
|
60
|
+
"mocha": "^10.4.0",
|
|
61
61
|
"npm-run-all": "^4.1.5",
|
|
62
62
|
"nyc": "^15.1.0",
|
|
63
63
|
"strip-indent": "^3.0.0"
|
package/rules/global.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const {
|
|
2
|
+
isAny, is
|
|
3
|
+
} = require('bpmnlint-utils');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A rule that verifies that global elements are properly used.
|
|
8
|
+
*
|
|
9
|
+
* Currently recognized global elements are:
|
|
10
|
+
*
|
|
11
|
+
* * `bpmn:Error`
|
|
12
|
+
* * `bpmn:Escalation`
|
|
13
|
+
* * `bpmn:Signal`
|
|
14
|
+
* * `bpmn:Message`
|
|
15
|
+
*
|
|
16
|
+
* For each of these elements proper usage implies:
|
|
17
|
+
*
|
|
18
|
+
* * element must have a name
|
|
19
|
+
* * element is used (referenced) from event definitions
|
|
20
|
+
* * there exists only a single element per type with a given name
|
|
21
|
+
*/
|
|
22
|
+
module.exports = function() {
|
|
23
|
+
|
|
24
|
+
function check(node, reporter) {
|
|
25
|
+
|
|
26
|
+
if (!is(node, 'bpmn:Definitions')) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const events = getEvents(node);
|
|
31
|
+
const eventDefinitions = getEventDefinitions(node);
|
|
32
|
+
|
|
33
|
+
events.forEach(event => {
|
|
34
|
+
if (!hasName(event)) {
|
|
35
|
+
reporter.report(event.id, 'Element is missing name');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!isReferenced(event, eventDefinitions)) {
|
|
39
|
+
reporter.report(event.id, 'Element is unused');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!isUnique(event, events)) {
|
|
43
|
+
reporter.report(event.id, 'Element name is not unique');
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
check
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// helpers /////////////////////////////
|
|
54
|
+
|
|
55
|
+
function getEvents(definition) {
|
|
56
|
+
return definition.rootElements.filter(node => isAny(node, [ 'bpmn:Error', 'bpmn:Escalation', 'bpmn:Message', 'bpmn:Signal' ]));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getEventDefinitions(definition) {
|
|
60
|
+
const eventDefinitions = [];
|
|
61
|
+
|
|
62
|
+
function traverse(element) {
|
|
63
|
+
if (element.rootElements) {
|
|
64
|
+
element.rootElements.forEach(traverse);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (element.flowElements) {
|
|
68
|
+
element.flowElements.forEach(traverse);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (element.eventDefinitions) {
|
|
72
|
+
element.eventDefinitions.forEach(eventDefinition => eventDefinitions.push(eventDefinition));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
traverse(definition);
|
|
77
|
+
return eventDefinitions;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function hasName(event) {
|
|
81
|
+
return (
|
|
82
|
+
event.name?.trim() !== ''
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function isReferenced(event, eventDefinitions) {
|
|
87
|
+
if (is(event, 'bpmn:Error')) {
|
|
88
|
+
return (
|
|
89
|
+
eventDefinitions.some(node => is(node, 'bpmn:ErrorEventDefinition') && event.id === node.errorRef?.id)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (is(event, 'bpmn:Escalation')) {
|
|
94
|
+
return (
|
|
95
|
+
eventDefinitions.some(node => is(node, 'bpmn:EscalationEventDefinition') && event.id === node.escalationRef?.id)
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (is(event, 'bpmn:Message')) {
|
|
100
|
+
return (
|
|
101
|
+
eventDefinitions.some(node => is(node, 'bpmn:MessageEventDefinition') && event.id === node.messageRef?.id)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (is(event, 'bpmn:Signal')) {
|
|
106
|
+
return (
|
|
107
|
+
eventDefinitions.some(node => is(node, 'bpmn:SignalEventDefinition') && event.id === node.signalRef?.id)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function isUnique(event, events) {
|
|
113
|
+
return (
|
|
114
|
+
events.filter(node => is(node, event.$type) && event.name === node.name).length === 1
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
};
|