UNPKG

archunit

Version:

ArchUnit TypeScript is an architecture testing library, to specify and assert architecture rules in your TypeScript app

101 lines 4.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.checkCoherence = exports.gatherPositiveViolations = exports.gatherViolations = exports.ViolatingEdge = void 0; class ViolatingEdge { constructor(rule, projectedEdge, isNegated = false) { this.rule = rule; this.projectedEdge = projectedEdge; this.isNegated = isNegated; } } exports.ViolatingEdge = ViolatingEdge; const gatherViolations = (graph, forbidden) => { const violatingEdges = []; for (const edge of graph) { for (const rule of forbidden) { if (edge.sourceLabel === rule.source && edge.targetLabel === rule.target) { violatingEdges.push(new ViolatingEdge(rule, edge, false)); } } } return violatingEdges; }; exports.gatherViolations = gatherViolations; const gatherPositiveViolations = (graph, allowed, nodesOfInterest, ignoreNonListed) => { const violatingEdges = []; for (const edge of graph) { if (ignoreNonListed && !(nodesOfInterest.includes(edge.sourceLabel) && nodesOfInterest.includes(edge.targetLabel))) { continue; } const match = allowed.find((allowedRule) => { return (edge.sourceLabel === allowedRule.source && edge.targetLabel === allowedRule.target); }); if (match === undefined) { violatingEdges.push(new ViolatingEdge(null, edge, false)); } } return violatingEdges; }; exports.gatherPositiveViolations = gatherPositiveViolations; /** * Checks for complete coherence in the architecture, ensuring all nodes are properly connected * according to the defined rules. * * @param graph The projected graph to check * @param allowed List of allowed rules * @param nodes List of nodes that should be checked for coherence * @param options Configuration options for coherence checking * @returns List of violations where coherence rules are broken */ const checkCoherence = (graph, allowed, nodes, options = {}) => { const violations = []; const { ignoreOrphans = false } = options; // Create a map of all allowed source -> target connections const allowedConnections = new Map(); for (const rule of allowed) { if (!allowedConnections.has(rule.source)) { allowedConnections.set(rule.source, []); } allowedConnections.get(rule.source)?.push(rule.target); } // Check for nodes that should have connections but don't for (const node of nodes) { // Skip if this node doesn't have any defined rules if (!allowedConnections.has(node)) { continue; } // Get actual edges for this node const nodeEdges = graph.filter((edge) => edge.sourceLabel === node); // Check that each allowed target is actually connected const expectedTargets = allowedConnections.get(node) || []; for (const expectedTarget of expectedTargets) { const hasConnection = nodeEdges.some((edge) => edge.targetLabel === expectedTarget); if (!hasConnection) { // This is a coherence violation - missing a required connection violations.push(new ViolatingEdge({ source: node, target: expectedTarget }, { sourceLabel: node, targetLabel: expectedTarget, cumulatedEdges: [], }, true)); } } // Check for orphaned nodes (no incoming or outgoing edges) if not ignoring orphans if (!ignoreOrphans && nodeEdges.length === 0) { const incomingEdges = graph.filter((edge) => edge.targetLabel === node); if (incomingEdges.length === 0) { // This node is completely orphaned - no connections at all violations.push(new ViolatingEdge(null, { sourceLabel: node, targetLabel: node, // Self-reference to indicate orphan cumulatedEdges: [], }, true)); } } } return violations; }; exports.checkCoherence = checkCoherence; //# sourceMappingURL=admissible-edges.js.map