UNPKG

dependency-cruiser

Version:

Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.

141 lines (130 loc) 3.34 kB
import isSameViolation from "./is-same-violation.mjs"; import { findRuleByName } from "#graph-utl/rule-set.mjs"; import { compareViolations } from "#graph-utl/compare.mjs"; import { uniqWith } from "#utl/array-util.mjs"; function cutNonTransgressions(pModule) { return { ...pModule, dependencies: pModule.dependencies.filter( (pDependency) => pDependency.valid === false, ), }; } function toDependencyViolationSummary(pRule, pModule, pDependency, pRuleSet) { let lReturnValue = { type: "dependency", from: pModule.source, to: pDependency.resolved, rule: pRule, }; if ( Object.hasOwn(pDependency, "cycle") && findRuleByName(pRuleSet, pRule.name)?.to?.circular ) { lReturnValue = { ...lReturnValue, type: "cycle", cycle: pDependency.cycle, }; } if ( Object.hasOwn(pModule, "instability") && Object.hasOwn(pDependency, "instability") && Object.hasOwn( findRuleByName(pRuleSet, pRule.name)?.to ?? {}, "moreUnstable", ) ) { lReturnValue = { ...lReturnValue, type: "instability", metrics: { from: { instability: pModule.instability }, to: { instability: pDependency.instability }, }, }; } return lReturnValue; } /** * Takes an array of dependencies, and extracts the violations from it. * * Each violation has a from a to and the violated rule () e.g. * { * from: "./here.js", * to: "./there.js", * rule: { * name: "some-rule", * severity: "warn" * } * } * * @param {any} pModules an array of modules * @param {any} pRuleSet? a rule set * @return {any} an array of violations */ function extractDependencyViolations(pModules, pRuleSet) { return pModules .map(cutNonTransgressions) .filter((pModule) => pModule.dependencies.length > 0) .map((pModule) => pModule.dependencies.map((pDependency) => pDependency.rules.map((pRule) => toDependencyViolationSummary(pRule, pModule, pDependency, pRuleSet), ), ), ) .flat(Infinity); } function toModuleViolationSummary(pRule, pModule, pRuleSet) { let lReturnValue = [ { type: "module", from: pModule.source, to: pModule.source, rule: pRule }, ]; if (pModule.reaches && findRuleByName(pRuleSet, pRule.name)?.to?.reachable) { lReturnValue = pModule.reaches .filter((pReachable) => pReachable.asDefinedInRule === pRule.name) .reduce( (pAll, pReachable) => pAll.concat( pReachable.modules.map((pReachableModule) => ({ to: pReachableModule.source, via: pReachableModule.via, })), ), [], ) .map((pToModule) => ({ type: "reachability", from: pModule.source, to: pToModule.to, rule: pRule, via: pToModule.via, })); } return lReturnValue; } function extractModuleViolations(pModules, pRuleSet) { return pModules .filter((pModule) => pModule.valid === false) .reduce( (pAllModules, pModule) => pAllModules.concat( pModule.rules.reduce( (pAllRules, pRule) => pAllRules.concat( toModuleViolationSummary(pRule, pModule, pRuleSet), ), [], ), ), [], ); } export default function summarizeModules(pModules, pRuleSet) { return uniqWith( extractDependencyViolations(pModules, pRuleSet) .concat(extractModuleViolations(pModules, pRuleSet)) .sort(compareViolations), isSameViolation, ); }