dependency-cruiser
Advanced tools
Comparing version 1.2.0 to 1.2.1
@@ -24,9 +24,13 @@ { | ||
"forbidden": [{ | ||
"name": "no-dep-on-test", | ||
"level": "error", | ||
"from": "^src", | ||
"to": "^test" | ||
},{ | ||
"name": "no-external-to-here", | ||
"level": "information", | ||
"from": "node_modules", | ||
"to": "^(src|test|lib)", | ||
"comment": "you never know" | ||
"comment": "you never know..." | ||
}] | ||
} |
@@ -11,2 +11,4 @@ # Daphne's dependencies | ||
"forbidden":[{ | ||
"name": "sub-not-allowed", | ||
"level": "error", | ||
"from": ".+", | ||
@@ -38,6 +40,9 @@ "to": "sub" | ||
dependency-cruise -T err -v test/fixtures | ||
Dependency-cruiser found the following illegal dependencies: | ||
test/fixtures/cjs/root_one.js => test/fixtures/cjs/sub/dir.js | ||
test/fixtures/cjs/sub/dir.js => test/fixtures/cjs/sub/depindir.js | ||
test/fixtures/cjs/two_only_one.js => test/fixtures/cjs/sub/dir.js | ||
error sub-not-allowed: test/fixtures/cjs/root_one.js => test/fixtures/cjs/sub/dir.js | ||
error sub-not-allowed: test/fixtures/cjs/sub/dir.js => test/fixtures/cjs/sub/depindir.js | ||
error sub-not-allowed: test/fixtures/cjs/two_only_one.js => test/fixtures/cjs/sub/dir.js | ||
3 violations found | ||
make: *** [dependency-cruise] Error 3 | ||
@@ -44,0 +49,0 @@ ``` |
{ | ||
"name": "dependency-cruiser", | ||
"version": "1.2.0", | ||
"version": "1.2.1", | ||
"description": "Visualize and validate javascript dependencies. With your rules. ES6, CommonJS, AMD", | ||
@@ -51,2 +51,3 @@ "bin": { | ||
"acorn": "4.0.3", | ||
"chalk": "1.1.3", | ||
"commander": "2.9.0", | ||
@@ -53,0 +54,0 @@ "handlebars": "4.0.6", |
@@ -59,3 +59,3 @@ # Dependency cruiser ![Dependency cruiser](https://raw.githubusercontent.com/sverweij/dependency-cruiser/master/doc/assets/ZKH-Dependency-recolored-160.png) | ||
Supplying `dot` as output type will make dependency-cruiser write | ||
a GraphViz dot format directed graph. Typical use is in concert | ||
a GraphViz dot format directed graph. Typical use is in concert | ||
with _GraphViz dot_: | ||
@@ -128,2 +128,16 @@ | ||
You can optionally specify a name and an error level ('error', 'warning' (the | ||
default) and 'information') with them that will appear in some reporters: | ||
```json | ||
{ | ||
"forbidden": [{ | ||
"name": "no-src-to-test", | ||
"level": "error", | ||
"from": "^src", | ||
"to": "^test" | ||
}] | ||
} | ||
``` | ||
A more elaborate configuration: | ||
@@ -136,3 +150,3 @@ - modules in `src` can get stuff from `src` and `node_modules` | ||
can't have dependencies to any module. | ||
- modules with the pattern `no-external-deps-plz` can't have | ||
- modules with the pattern `externalDependencyLess\.js` can't have | ||
dependencies to stuff in `node_modules`. | ||
@@ -158,12 +172,18 @@ | ||
"from": "^src", | ||
"to": "^test" | ||
"to": "^test", | ||
"name": "no-src-to-test", | ||
"level": "error" | ||
},{ | ||
"from": "no-deps-at-all-plz", | ||
"to": ".+" | ||
"from": "dependencyless\\.js", | ||
"to": ".+", | ||
"comment": "level & name default to 'level' and 'unnamed'" | ||
},{ | ||
"from": "no-external-deps-plz", | ||
"to": "node_modules" | ||
"from": "externalDependencyLess\\.js", | ||
"to": "node_modules", | ||
"level": "warning" | ||
},{ | ||
"from": "node_modules", | ||
"to": "^(src|test|lib)", | ||
"name": "external-depends-on-you", | ||
"level": "error", | ||
"comment": "well, you never know ..." | ||
@@ -170,0 +190,0 @@ } |
@@ -42,6 +42,8 @@ "use strict"; | ||
function calculateExitCode(pDependencyList, pOutputType) { | ||
const ERROR_CHROME_OFFSET = 5; | ||
if (pOutputType !== "err") { | ||
return 0; | ||
} | ||
return pDependencyList.split('\n').length - 1; | ||
return pDependencyList.split('\n').length - ERROR_CHROME_OFFSET; | ||
} | ||
@@ -48,0 +50,0 @@ |
@@ -87,9 +87,11 @@ "use strict"; | ||
return { | ||
module : pDependency.moduleName, | ||
resolved : lResolved.resolved, | ||
moduleSystem : pDependency.moduleSystem, | ||
coreModule : lResolved.coreModule, | ||
followable : lResolved.followable, | ||
valid : validator.validate( | ||
return Object.assign( | ||
{ | ||
module : pDependency.moduleName, | ||
resolved : lResolved.resolved, | ||
moduleSystem : pDependency.moduleSystem, | ||
coreModule : lResolved.coreModule, | ||
followable : lResolved.followable | ||
}, | ||
validator.validate( | ||
pOptions.validate, | ||
@@ -100,3 +102,3 @@ pOptions.rulesFile, | ||
) | ||
}; | ||
); | ||
} | ||
@@ -103,0 +105,0 @@ ) |
"use strict"; | ||
const Handlebars = require("handlebars/dist/cjs/handlebars.runtime"); | ||
const chalk = require('chalk'); | ||
require("./err.template"); | ||
const LEVEL2CHALK = { | ||
'error' : chalk.red, | ||
'warning' : chalk.yellow, | ||
'information' : chalk.cyan | ||
}; | ||
function formatError(pErr) { | ||
return `${LEVEL2CHALK[pErr.rule.level](pErr.rule.level)} ${pErr.rule.name}: ` + | ||
`${chalk.bold(pErr.source)} => ${chalk.bold(pErr.resolved)}`; | ||
} | ||
function cutNonTransgressions(pSourceEntry) { | ||
@@ -14,11 +23,25 @@ return { | ||
function addSource(pSource) { | ||
return pDependency => Object.assign(pDependency, {source: pSource}); | ||
} | ||
function render(pInput) { | ||
return Handlebars.templates['err.template.hbs']( | ||
{ | ||
"things" : | ||
pInput | ||
.map(cutNonTransgressions) | ||
.filter(pDep => pDep.dependencies.length > 0) | ||
.sort((pOne, pTwo) => pOne.source > pTwo.source ? 1 : -1) | ||
} | ||
let lViolations = pInput | ||
.map(cutNonTransgressions) | ||
.filter(pDep => pDep.dependencies.length > 0) | ||
.sort((pOne, pTwo) => pOne.source > pTwo.source ? 1 : -1) | ||
.reduce( | ||
(pAll, pThis) => pAll.concat(pThis.dependencies.map(addSource(pThis.source))), | ||
[] | ||
); | ||
if (lViolations.length === 0){ | ||
return ""; | ||
} | ||
return lViolations.reduce( | ||
(pAll, pThis) => `${pAll} ${formatError(pThis)}\n`, | ||
"\n" | ||
).concat( | ||
chalk.red(`\n ${lViolations.length} violations found\n\n`) | ||
); | ||
@@ -25,0 +48,0 @@ } |
"use strict"; | ||
const _ = require("lodash"); | ||
const fs = require("fs"); | ||
const safeRegex = require('safe-regex'); | ||
const _ = require("lodash"); | ||
const fs = require("fs"); | ||
const ruleSetValidator = require('./ruleSetValidator'); | ||
const ruleSetNormalizer = require('./ruleSetNormalizer'); | ||
function checkRuleSafety(pRule) { | ||
if ( | ||
!( | ||
safeRegex(pRule.from) && | ||
safeRegex(pRule.to) | ||
) | ||
){ | ||
throw new Error( | ||
`rule ${JSON.stringify(pRule, null, "")} has an unsafe regular expression. Bailing out.\n` | ||
); | ||
} | ||
} | ||
function validateRuleSet(pRuleSet) { | ||
if (pRuleSet.hasOwnProperty("allowed")){ | ||
pRuleSet.allowed.forEach(checkRuleSafety); | ||
} | ||
if (pRuleSet.hasOwnProperty("forbidden")){ | ||
pRuleSet.forbidden.forEach(checkRuleSafety); | ||
} | ||
} | ||
const readRules = _.memoize( | ||
@@ -33,8 +12,7 @@ pRuleSetFile => { | ||
validateRuleSet(lRetval); | ||
return lRetval; | ||
ruleSetValidator.validate(lRetval); | ||
return ruleSetNormalizer.normalize(lRetval); | ||
} | ||
); | ||
function matchRule(pFrom, pTo) { | ||
@@ -45,11 +23,29 @@ return pRule => pFrom.match(pRule.from) && pTo.match(pRule.to); | ||
function validateAgainstRules(pRuleSet, pFrom, pTo) { | ||
let lRetval = true; | ||
let lMatchedRule = {}; | ||
if (pRuleSet.hasOwnProperty("allowed")){ | ||
lRetval = lRetval && pRuleSet.allowed.some(matchRule(pFrom, pTo)); | ||
lMatchedRule = pRuleSet.allowed.find(matchRule(pFrom, pTo)); | ||
if (!Boolean(lMatchedRule)){ | ||
return { | ||
valid: false, | ||
rule: { | ||
level: "warning", | ||
name: "not-in-allowed" | ||
} | ||
}; | ||
} | ||
} | ||
if (pRuleSet.hasOwnProperty("forbidden")){ | ||
lRetval = lRetval && !(pRuleSet.forbidden.some(matchRule(pFrom, pTo))); | ||
lMatchedRule = pRuleSet.forbidden.find(matchRule(pFrom, pTo)); | ||
if (Boolean(lMatchedRule)){ | ||
return { | ||
valid: false, | ||
rule: { | ||
level: lMatchedRule.level, | ||
name : lMatchedRule.name | ||
} | ||
}; | ||
} | ||
} | ||
return lRetval; | ||
return {valid:true}; | ||
} | ||
@@ -59,3 +55,3 @@ | ||
if (!pValidate) { | ||
return true; | ||
return {valid:true}; | ||
} | ||
@@ -62,0 +58,0 @@ return validateAgainstRules(readRules(pRuleSetFile), pFrom, pTo); |
@@ -19,3 +19,7 @@ [ | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -28,3 +32,7 @@ { | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
@@ -42,3 +50,7 @@ ] | ||
"followable": false, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
@@ -56,3 +68,7 @@ ] | ||
"followable": false, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
@@ -70,3 +86,7 @@ ] | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -79,3 +99,7 @@ { | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -88,3 +112,7 @@ { | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -97,3 +125,7 @@ { | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -106,3 +138,7 @@ { | ||
"followable": false, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -115,3 +151,7 @@ { | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
@@ -129,3 +169,7 @@ ] | ||
"followable": false, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
@@ -143,3 +187,7 @@ ] | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -152,3 +200,7 @@ { | ||
"followable": false, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
@@ -166,3 +218,7 @@ ] | ||
"followable": false, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
@@ -180,3 +236,7 @@ ] | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -189,3 +249,7 @@ { | ||
"followable": false, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -198,3 +262,7 @@ { | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
}, | ||
@@ -207,3 +275,7 @@ { | ||
"followable": false, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
@@ -221,6 +293,10 @@ ] | ||
"followable": true, | ||
"valid": false | ||
"valid": false, | ||
"rule": { | ||
"level": "warning", | ||
"name": "unnamed" | ||
} | ||
} | ||
] | ||
} | ||
] | ||
] |
@@ -7,2 +7,4 @@ { | ||
"forbidden":[{ | ||
"name": "sub-not-allowed", | ||
"level": "error", | ||
"from": ".+", | ||
@@ -9,0 +11,0 @@ "to": "sub" |
@@ -6,3 +6,3 @@ "use strict"; | ||
const NUMBER_OF_INVALID_DEPS_IN_FIXTURE = 21; | ||
const NUMBER_OF_INVALID_DEPS_IN_FIXTURE = 24; | ||
@@ -9,0 +9,0 @@ describe("err reporter", () => { |
@@ -14,3 +14,3 @@ "use strict"; | ||
) | ||
).to.equal(true); | ||
).to.deep.equal({valid: true}); | ||
}); | ||
@@ -26,5 +26,17 @@ | ||
) | ||
).to.equal(true); | ||
).to.deep.equal({valid: true}); | ||
}); | ||
it("is ok with the 'everything allowed' validation", () => { | ||
expect( | ||
validator.validate( | ||
true, | ||
"./test/fixtures/rules.impossible-to-match-allowed.json", | ||
"koos koets", | ||
"robby van de kerkhof" | ||
) | ||
).to.deep.equal({valid: false, rule: {level: "warning", "name": "not-in-allowed"}}); | ||
}); | ||
it("is ok with the 'nothing allowed' validation", () => { | ||
@@ -38,3 +50,3 @@ expect( | ||
) | ||
).to.equal(false); | ||
).to.deep.equal({valid: false, rule: {level: 'warning', name: 'unnamed'}}); | ||
}); | ||
@@ -50,3 +62,3 @@ | ||
) | ||
).to.equal(true); | ||
).to.deep.equal({valid: true}); | ||
}); | ||
@@ -62,3 +74,3 @@ | ||
) | ||
).to.equal(false); | ||
).to.deep.equal({valid: false, rule: {level: 'warning', name: 'unnamed'}}); | ||
}); | ||
@@ -74,3 +86,3 @@ | ||
); | ||
expect("not to be here").to.equal("still here, though"); | ||
expect("not to be here").to.deep.equal("still here, though"); | ||
} catch (e) { | ||
@@ -77,0 +89,0 @@ expect(e).to.deep.equal( |
Sorry, the diff of this file is not supported yet
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
469178
149
3686
208
8
+ Addedchalk@1.1.3
+ Addedansi-regex@2.1.1(transitive)
+ Addedansi-styles@2.2.1(transitive)
+ Addedchalk@1.1.3(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedhas-ansi@2.0.0(transitive)
+ Addedstrip-ansi@3.0.1(transitive)
+ Addedsupports-color@2.0.0(transitive)