Skip to content

Commit

Permalink
Merge pull request #18 from sverweij/feature/add-do-not-follow-option
Browse files Browse the repository at this point in the history
Add 'do not follow' option
  • Loading branch information
sverweij authored Oct 31, 2017
2 parents 1a21d04 + b0681d9 commit daf57bc
Show file tree
Hide file tree
Showing 60 changed files with 678 additions and 110 deletions.
6 changes: 6 additions & 0 deletions .dependency-cruiser-custom.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
"severity": "error",
"from": { "path": "(^test/[^\\/]+/)[^\\.]+\\.spec\\.js" },
"to": { "path": "^test/[^\\/]+/.+", "pathNot": "utl|$1[^\\.]+\\.json$"}
}, {
"name": "prefer-no-lodash",
"comment": "We want to minimize the dependency on lodash a bit - so flag dependencies that go there",
"severity": "info",
"from": {},
"to": { "path": "lodash"}
}, {
"name": "no-dep-on-test",
"severity": "error",
Expand Down
9 changes: 2 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ depgraph:
./bin/dependency-cruise -x "(^node_modules|^fs$$|^path$$)" -T dot -v .dependency-cruiser-custom.json src bin/dependency-cruise | dot -T svg > tmp_deps.svg

depcruise:
./bin/dependency-cruise -x fixtures -v .dependency-cruiser-custom.json src bin/dependency-cruise test
./bin/dependency-cruise -X ^node_modules -x fixtures -v .dependency-cruiser-custom.json src bin/dependency-cruise test

check: lint test depcruise
./bin/dependency-cruise --version # if that runs the cli script works
Expand Down Expand Up @@ -388,12 +388,7 @@ test/extract/dependencyEndsUpAtFrom.spec.js: \

test/extract/extract-composite.spec.js: \
src/extract/index.js \
src/extract/jsonschema.json \
test/extract/maxDepth1.json \
test/extract/maxDepth2.json \
test/extract/maxDepth3.json \
test/extract/maxDepth4.json \
test/extract/maxDepthUnspecified.json
src/extract/jsonschema.json

test/extract/extract.spec.js: \
src/extract/extract.js
Expand Down
12 changes: 7 additions & 5 deletions bin/dependency-cruise
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,22 @@ if (!semver.satisfies(process.versions.node, $package.engines.node)) {
program
.version($package.version)
.option("-i, --info", `shows what languages and extensions
dependency-cruiser supports`)
dependency-cruiser supports`)
.option("-v, --validate [file]", `validate with rules in [file]
(default: .dependency-cruiser.json)`)
(default: .dependency-cruiser.json)`)
.option("-f, --output-to <file>", `file to write output to; - for stdout
(default: -)`)
(default: -)`)
.option("-X, --do-not-follow <regex>", `a regular expression for modules to include,
but not follow further`)
.option("-x, --exclude <regex>", "a regular expression for excluding modules")
.option("-d, --max-depth <n>", `the maximum depth to cruise; 0 <= n <= 99
(default: 0, which means 'infinite depth')`)
.option("-M, --system <items>", `list of module systems (default: amd,cjs,es6)`)
.option("-T, --output-type <type>", `output type - html|dot|err|json
(default: err)`)
(default: err)`)
.option("-P, --prefix <prefix>", "prefix to use for links in the svg reporter")
.option("--init-rules", `write a .dependency-cruiser.json with basic
validations to the current folder.`)
validations to the current folder.`)
.arguments("<files-or-directories>")
.parse(process.argv);

Expand Down
32 changes: 17 additions & 15 deletions doc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,23 @@ let dependenciesInAGraphVizDotScript = depcruise(
These are all the options:
```
{
validate : if true, will attempt to validate with the rules in ruleSet.
Default false.
ruleSet : An object containing the rules to validate against. The rules
should adhere to the [ruleset schema](../src/validate/jsonschema.json)
exclude : regular expression describing which dependencies the function
should not cruise
maxDepth : the maximum depth to cruise; 0 <= n <= 99
(default: 0, which means 'infinite depth')
system : an array of module systems to use for following dependencies;
defaults to ["es6", "cjs", "amd"]
outputType : one of "json", "html", "dot", "csv" or "err". When left
out the function will return a javascript object as dependencies
prefix : a string to insert before links (in dot/ svg output) so with
cruising local dependencies it is possible to point to sources
elsewhere (e.g. in an online repository)
validate : if true, will attempt to validate with the rules in ruleSet.
Default false.
ruleSet : An object containing the rules to validate against. The rules
should adhere to the [ruleset schema](../src/validate/jsonschema.json)
doNotFollow : regular expression describing which dependencies the function
should cruise, but not resolve or follow any further
exclude : regular expression describing which dependencies the function
should not cruise
maxDepth : the maximum depth to cruise; 0 <= n <= 99
(default: 0, which means 'infinite depth')
system : an array of module systems to use for following dependencies;
defaults to ["es6", "cjs", "amd"]
outputType : one of "json", "html", "dot", "csv" or "err". When left
out the function will return a javascript object as dependencies
prefix : a string to insert before links (in dot/ svg output) so with
cruising local dependencies it is possible to point to sources
elsewhere (e.g. in an online repository)
}
```

Expand Down
72 changes: 52 additions & 20 deletions doc/cli.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,56 @@
# dependency-cruiser command line interface

Running with no parameters gets you help:
```
Usage: dependency-cruise [options] <files-or-directories>
Options:
-V, --version output the version number
-i, --info shows what languages and extensions
dependency-cruiser supports
-v, --validate [file] validate with rules in [file]
(default: .dependency-cruiser.json)
-f, --output-to <file> file to write output to; - for stdout
(default: -)
-d, --do-not-follow <regex> a regular expression for modules to include,
but not follow further
-x, --exclude <regex> a regular expression for excluding modules
-M, --system <items> list of module systems (default: amd,cjs,es6)
-T, --output-type <type> output type - html|dot|err|json
(default: err)
-P, --prefix <prefix> prefix to use for links in the svg reporter
--init-rules write a .dependency-cruiser.json with basic
validations to the current folder.
-h, --help output usage information
```

Usage: dependency-cruise [options] <files-or-directories>

Options:

-h, --help output usage information
-V, --version output the version number
-i, --info shows what languages and extensions
dependency-cruiser supports
-v, --validate [file] validate with rules in [file]
(default: .dependency-cruiser.json)
-f, --output-to <file> file to write output to; - for stdout
(default: -)
-x, --exclude <regex> a regular expression for excluding modules
-d, --max-depth <n> the maximum depth to cruise; 0 <= n <= 99
(default: 0, which means 'infinite depth')
-M, --system <items> list of module systems (default: amd,cjs,es6)
-T, --output-type <type> output type - html|dot|err|json
(default:err)
-P --prefix <prefix> prefix to prepend links with (e.g. in the
svg output type)
--init-rules create a .dependency-cruiser.json with basic
validations in the current folder.
-h, --help output usage information
-V, --version output the version number
-i, --info shows what languages and extensions
dependency-cruiser supports
-v, --validate [file] validate with rules in [file]
(default: .dependency-cruiser.json)
-f, --output-to <file> file to write output to; - for stdout
(default: -)
-X, --do-not-follow <regex> a regular expression for modules to include,
but not follow further
-x, --exclude <regex> a regular expression for excluding modules
-d, --max-depth <n> the maximum depth to cruise; 0 <= n <= 99
(default: 0, which means 'infinite depth')
-M, --system <items> list of module systems (default: amd,cjs,es6)
-T, --output-type <type> output type - html|dot|err|json
(default:err)
-P --prefix <prefix> prefix to prepend links with (e.g. in the
svg output type)
--init-rules create a .dependency-cruiser.json with basic
validations in the current folder.

```

## Output formats

Expand Down Expand Up @@ -67,9 +91,17 @@ If you supply `csv` it will write the dependency matrix to a comma
separated file - so you can import it into a spreadsheet program
and analyze from there.

## `--do-not-follow`: don't cruise modules adhering to this pattern any further
If you _do_ want to see certain modules in your reports, but are not interested
in these modules' dependencies, you'd pass the regular expression for those
modules to the `--do-not-follow` (short: `-d`) option. A typical pattern you'd
use with this is "node_modules":

## `--exclude`: exclude modules from being cruised
```sh
dependency-cruise -d "node_modules" -T html -f deps-with-unfollowed-node_modules.html src
```

## `--exclude`: exclude modules from being cruised
If you don't want to see certain modules in your report (or not have them
validated), you can exclude them by passing a regular expression to the
`--exclude` (short: `-x`) option. E.g. to exclude `node_modules` from being
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"main": "src/main/index.js",
"scripts": {
"depcruise": "./bin/dependency-cruise -x fixtures -v .dependency-cruiser-custom.json src bin/dependency-cruise test",
"depcruise": "./bin/dependency-cruise -X ^node_modules -x fixtures -v .dependency-cruiser-custom.json src bin/dependency-cruise test",
"lint": "eslint bin src test",
"lint:fix": "eslint --fix bin src test",
"nsp": "nsp check",
Expand Down
1 change: 1 addition & 0 deletions src/cli/normalizeOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function determineRulesFileName(pValidate) {
*/
module.exports = (pOptions) => {
pOptions = _.defaults(pOptions, {
doNotFollow: "",
exclude: "",
outputTo: "-",
outputType: "err",
Expand Down
9 changes: 5 additions & 4 deletions src/cli/validateParameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ function validateSystems(pSystem) {
}
}

function validateExcludePattern(pExclude) {
if (Boolean(pExclude) && !safeRegex(pExclude)) {
function isSafeRegExp(pPattern) {
if (Boolean(pPattern) && !safeRegex(pPattern)) {
throw Error(
`The exclude pattern '${pExclude}' will probably run very slowly - cowardly refusing to run.\n`
`The pattern '${pPattern}' will probably run very slowly - cowardly refusing to run.\n`
);
}
}
Expand Down Expand Up @@ -62,7 +62,8 @@ module.exports = (pFileDirArray, pOptions) => {
pFileDirArray.forEach(validateFileExistence);
if (Boolean(pOptions)) {
validateSystems(pOptions.system);
validateExcludePattern(pOptions.exclude);
isSafeRegExp(pOptions.exclude);
isSafeRegExp(pOptions.doNotFollow);
validateOutputType(pOptions.outputType);
validateMaxDepth(pOptions.maxDepth);
validateValidation(pOptions);
Expand Down
7 changes: 6 additions & 1 deletion src/extract/extract.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,17 @@ module.exports = (pFileName, pOptions) => {
pOptions.baseDir,
path.join(pOptions.baseDir, path.dirname(pFileName))
);
const lMatchesDoNotFollow = Boolean(pOptions.doNotFollow)
? RegExp(pOptions.doNotFollow, "g").test(lResolved.resolved)
: false;

return Object.assign(
lResolved,
{
module : pDependency.moduleName,
moduleSystem : pDependency.moduleSystem
moduleSystem : pDependency.moduleSystem,
followable : lResolved.followable && !lMatchesDoNotFollow,
matchesDoNotFollow : lMatchesDoNotFollow
}
);
}
Expand Down
4 changes: 3 additions & 1 deletion src/extract/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function extractRecursive (pFileName, pOptions, pVisited, pDepth) {
: [];

return lDependencies
.filter(pDep => pDep.followable)
.filter(pDep => pDep.followable && !pDep.matchesDoNotFollow)
.reduce(
(pAll, pDep) => {
if (!pVisited.has(pDep.resolved)){
Expand Down Expand Up @@ -65,6 +65,7 @@ function toDependencyToSource(pToListItem) {
followable : pToListItem.followable,
coreModule : pToListItem.coreModule,
couldNotResolve : pToListItem.couldNotResolve,
matchesDoNotFollow: pToListItem.matchesDoNotFollow,
dependencyTypes : pToListItem.dependencyTypes,
dependencies : []
};
Expand All @@ -85,6 +86,7 @@ function makeOptionsPresentable(pOptions) {
const SHARABLE_OPTIONS = [
"rulesFile",
"outputTo",
"doNotFollow",
"exclude",
"maxDepth",
"system",
Expand Down
16 changes: 14 additions & 2 deletions src/extract/jsonschema.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@
},
"followable": {
"type": "boolean",
"description": "Whether or not this is a dependency that can be followed any further. This will be 'false' for for core modules, json, and modules that could not be resolved to a file."
"description": "Whether or not this is a dependency that can be followed any further. This will be 'false' for for core modules, json, modules that could not be resolved to a file and modules that weren't followed because it matches the doNotFollow expression."
},
"matchesDoNotFollow": {
"type": "boolean",
"description": "'true' if the file name of this module matches the doNotFollow regular expression"
},
"coreModule": {
"type": "boolean",
Expand Down Expand Up @@ -99,7 +103,11 @@
},
"followable": {
"type": "boolean",
"description": "Whether or not this is a dependency that can be followed any further. This is the case for core modules, json, and modules that could not be resolved to a file."
"description": "Whether or not this is a dependency that can be followed any further. This will be 'false' for for core modules, json, modules that could not be resolved to a file and modules that weren't followed because it matches the doNotFollow expression."
},
"matchesDoNotFollow": {
"type": "boolean",
"description": "'true' if the file name of this module matches the doNotFollow regular expression"
},
"couldNotResolve": {
"type": "boolean",
Expand Down Expand Up @@ -206,6 +214,10 @@
"type": "string",
"description": "File the output was written to ('-' for stdout)"
},
"doNotFollow": {
"type": "string",
"description": "The regular expression used for preventing modules from being cruised any further"
},
"exclude": {
"type": "string",
"description": "The regular expression used for excluding modules from being cruised"
Expand Down
2 changes: 1 addition & 1 deletion src/report/csvReporter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";

const Handlebars = require("handlebars/dist/cjs/handlebars.runtime");
const Handlebars = require("handlebars/runtime");
const dependencyToIncidenceTransformer = require("./dependencyToIncidenceTransformer");

require("./csv.template");
Expand Down
8 changes: 4 additions & 4 deletions src/report/dot.template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ digraph "dependency-cruiser output"{
overlap=false
nodesep=0.16
fontname="Helvetica-bold"
fontsize="9"
fontsize=9
style="rounded,bold"
compound=true
node [shape=box style="rounded, filled" fillcolor="#ffffcc" height=0.2 fontname=Helvetica fontsize=9]
edge [color=black arrowhead=normal fontname="Helvetica" fontsize="9"]
edge [color=black arrowhead=normal fontname=Helvetica fontsize=9]

{{#each things}}
{{#if folder}}
{{#each path}}subgraph "cluster_{{{aggregateSnippet}}}" {label="{{{snippet}}}" {{/each~}}
"{{{source}}}"
{{~#if couldNotResolve}} [label="{{{label}}}" color="red" fontcolor="red"]
{{~else}} [label="{{{label}}}" URL="{{{prefix}}}{{{source}}}"]
{{~else}} {{~#if matchesDoNotFollow}} [label="{{{label}}}" shape="folder" URL="{{{prefix}}}{{{source}}}"]{{~else}} [label="{{{label}}}" URL="{{{prefix}}}{{{source}}}"]{{~/if}}
{{~/if}}{{~#each path}} }{{/each}}
{{else}}
"{{{source}}}"
{{~#if coreModule}} [color="grey" fontcolor="grey"]
{{~else}}
{{~#if couldNotResolve}} [color="red" fontcolor="red"]
{{~else}} [URL="{{{prefix}}}{{{source}}}"]
{{~else}} {{~#if matchesDoNotFollow}} [shape="folder" URL="{{{prefix}}}{{{source}}}"]{{~else}} [URL="{{{prefix}}}{{{source}}}"]{{~/if}}
{{~/if}}{{/if}}
{{/if}}
{{/each}}
Expand Down
Loading

0 comments on commit daf57bc

Please sign in to comment.