Comparing version 10.3.0 to 10.3.1
{ | ||
"name": "bpmnlint", | ||
"description": "Validate your BPMN diagrams based on configurable lint rules", | ||
"version": "10.3.0", | ||
"version": "10.3.1", | ||
"main": "lib/index.js", | ||
@@ -6,0 +6,0 @@ "keywords": [ |
const { | ||
isAny, is | ||
is, | ||
isAny | ||
} = require('bpmnlint-utils'); | ||
@@ -13,4 +14,4 @@ | ||
* * `bpmn:Escalation` | ||
* * `bpmn:Message` | ||
* * `bpmn:Signal` | ||
* * `bpmn:Message` | ||
* | ||
@@ -20,3 +21,3 @@ * For each of these elements proper usage implies: | ||
* * element must have a name | ||
* * element is used (referenced) from event definitions | ||
* * element is referenced by at least one element | ||
* * there exists only a single element per type with a given name | ||
@@ -32,16 +33,17 @@ */ | ||
const events = getEvents(node); | ||
const eventDefinitions = getEventDefinitions(node); | ||
const rootElements = getRootElements(node); | ||
events.forEach(event => { | ||
if (!hasName(event)) { | ||
reporter.report(event.id, 'Element is missing name'); | ||
const referencingElements = getReferencingElements(node); | ||
rootElements.forEach(rootElement => { | ||
if (!hasName(rootElement)) { | ||
reporter.report(rootElement.id, 'Element is missing name'); | ||
} | ||
if (!isReferenced(event, eventDefinitions)) { | ||
reporter.report(event.id, 'Element is unused'); | ||
if (!isReferenced(rootElement, referencingElements)) { | ||
reporter.report(rootElement.id, 'Element is unused'); | ||
} | ||
if (!isUnique(event, events)) { | ||
reporter.report(event.id, 'Element name is not unique'); | ||
if (!isUnique(rootElement, rootElements)) { | ||
reporter.report(rootElement.id, 'Element name is not unique'); | ||
} | ||
@@ -58,25 +60,38 @@ }); | ||
function getEvents(definition) { | ||
return definition.rootElements.filter(node => isAny(node, [ 'bpmn:Error', 'bpmn:Escalation', 'bpmn:Message', 'bpmn:Signal' ])); | ||
function getRootElements(definitions) { | ||
return definitions.rootElements.filter(node => isAny(node, [ 'bpmn:Error', 'bpmn:Escalation', 'bpmn:Message', 'bpmn:Signal' ])); | ||
} | ||
function getEventDefinitions(definition) { | ||
const eventDefinitions = []; | ||
function getReferencingElements(definitions) { | ||
const referencingElements = []; | ||
function traverse(element) { | ||
if (element.rootElements) { | ||
element.rootElements.forEach(traverse); | ||
if (is(element, 'bpmn:Definitions') && element.get('rootElements').length) { | ||
element.get('rootElements').forEach(traverse); | ||
} | ||
if (element.flowElements) { | ||
element.flowElements.forEach(traverse); | ||
if (is(element, 'bpmn:FlowElementsContainer') && element.get('flowElements').length) { | ||
element.get('flowElements').forEach(traverse); | ||
} | ||
if (element.eventDefinitions) { | ||
element.eventDefinitions.forEach(eventDefinition => eventDefinitions.push(eventDefinition)); | ||
if (is(element, 'bpmn:Event') && element.get('eventDefinitions').length) { | ||
element.get('eventDefinitions').forEach(eventDefinition => referencingElements.push(eventDefinition)); | ||
} | ||
if (is(element, 'bpmn:Collaboration') && element.get('messageFlows').length) { | ||
element.get('messageFlows').forEach(traverse); | ||
} | ||
if (isAny(element, [ | ||
'bpmn:MessageFlow', | ||
'bpmn:ReceiveTask', | ||
'bpmn:SendTask' | ||
])) { | ||
referencingElements.push(element); | ||
} | ||
} | ||
traverse(definition); | ||
return eventDefinitions; | ||
traverse(definitions); | ||
return referencingElements; | ||
} | ||
@@ -90,33 +105,41 @@ | ||
function isReferenced(event, eventDefinitions) { | ||
if (is(event, 'bpmn:Error')) { | ||
return ( | ||
eventDefinitions.some(node => is(node, 'bpmn:ErrorEventDefinition') && event.id === node.errorRef?.id) | ||
); | ||
function isReferenced(rootElement, referencingElements) { | ||
if (is(rootElement, 'bpmn:Error')) { | ||
return referencingElements.some(referencingElement => { | ||
return is(referencingElement, 'bpmn:ErrorEventDefinition') | ||
&& rootElement.get('id') === referencingElement.get('errorRef')?.get('id'); | ||
}); | ||
} | ||
if (is(event, 'bpmn:Escalation')) { | ||
return ( | ||
eventDefinitions.some(node => is(node, 'bpmn:EscalationEventDefinition') && event.id === node.escalationRef?.id) | ||
); | ||
if (is(rootElement, 'bpmn:Escalation')) { | ||
return referencingElements.some(referencingElement => { | ||
return is(referencingElement, 'bpmn:EscalationEventDefinition') | ||
&& rootElement.get('id') === referencingElement.get('escalationRef')?.get('id'); | ||
}); | ||
} | ||
if (is(event, 'bpmn:Message')) { | ||
return ( | ||
eventDefinitions.some(node => is(node, 'bpmn:MessageEventDefinition') && event.id === node.messageRef?.id) | ||
); | ||
if (is(rootElement, 'bpmn:Message')) { | ||
return referencingElements.some(referencingElement => { | ||
return isAny(referencingElement, [ | ||
'bpmn:MessageEventDefinition', | ||
'bpmn:MessageFlow', | ||
'bpmn:ReceiveTask', | ||
'bpmn:SendTask' | ||
]) && rootElement.get('id') === referencingElement.get('messageRef')?.get('id'); | ||
}); | ||
} | ||
if (is(event, 'bpmn:Signal')) { | ||
return ( | ||
eventDefinitions.some(node => is(node, 'bpmn:SignalEventDefinition') && event.id === node.signalRef?.id) | ||
); | ||
if (is(rootElement, 'bpmn:Signal')) { | ||
return referencingElements.some(referencingElement => { | ||
return is(referencingElement, 'bpmn:SignalEventDefinition') | ||
&& rootElement.get('id') === referencingElement.get('signalRef')?.get('id'); | ||
}); | ||
} | ||
} | ||
function isUnique(event, events) { | ||
function isUnique(rootElement, rootElements) { | ||
return ( | ||
events.filter(node => is(node, event.$type) && event.name === node.name).length === 1 | ||
rootElements.filter(otherRootElement => is(otherRootElement, rootElement.$type) && rootElement.name === otherRootElement.name).length === 1 | ||
); | ||
} | ||
}; |
@@ -31,2 +31,32 @@ const { | ||
module.exports.disallowNodeType = disallowNodeType; | ||
module.exports.disallowNodeType = disallowNodeType; | ||
/** | ||
* Find a parent for the given element | ||
* | ||
* @param {ModdleElement} node | ||
* | ||
* @param {String} type | ||
* | ||
* @return {ModdleElement} element | ||
*/ | ||
function findParent(node, type) { | ||
if (!node) { | ||
return null; | ||
} | ||
const parent = node.$parent; | ||
if (!parent) { | ||
return node; | ||
} | ||
if (is(parent, type)) { | ||
return parent; | ||
} | ||
return findParent(parent, type); | ||
} | ||
module.exports.findParent = findParent; |
@@ -26,6 +26,2 @@ const { | ||
if (is(node, 'bpmn:BoundaryEvent')) { | ||
return; | ||
} | ||
// ignore sub-processes | ||
@@ -32,0 +28,0 @@ if (is(node, 'bpmn:SubProcess')) { |
@@ -6,2 +6,5 @@ const { | ||
const { | ||
findParent | ||
} = require('./helper'); | ||
@@ -21,2 +24,30 @@ /** | ||
function isCompensationEvent(node) { | ||
const eventDefinitions = node.eventDefinitions || []; | ||
return eventDefinitions.length && eventDefinitions.every( | ||
definition => is(definition, 'bpmn:CompensateEventDefinition') | ||
); | ||
} | ||
function hasCompensationActivity(node) { | ||
const parent = findParent(node, 'bpmn:Process'); | ||
const artifacts = parent.artifacts || []; | ||
return artifacts.some((element) => { | ||
if (!is(element, 'bpmn:Association')) { | ||
return false; | ||
} | ||
const source = element.sourceRef; | ||
return source.id === node.id; | ||
}); | ||
} | ||
function isForCompensation(node) { | ||
return node.isForCompensation; | ||
} | ||
function isImplicitEnd(node) { | ||
@@ -37,2 +68,10 @@ const outgoing = node.outgoing || []; | ||
if (is(node, 'bpmn:BoundaryEvent') && isCompensationEvent(node) && hasCompensationActivity(node)) { | ||
return false; | ||
} | ||
if (is(node, 'bpmn:Task') && isForCompensation(node)) { | ||
return false; | ||
} | ||
return outgoing.length === 0; | ||
@@ -53,2 +92,2 @@ } | ||
return { check }; | ||
}; | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
73442
2293