dependency-cruiser 10.8.0 → 10.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +21 -15
- package/src/enrich/derive/metrics/folder.js +1 -2
- package/src/enrich/derive/metrics/get-stability-metrics.js +4 -4
- package/src/enrich/derive/metrics/module.js +13 -14
- package/src/enrich/derive/metrics/utl.js +2 -7
- package/src/enrich/enrich-modules.js +1 -1
- package/src/main/options/normalize.js +28 -0
- package/src/meta.js +1 -1
- package/src/report/dot/dot.template.js +1 -1
- package/src/report/dot/index.js +7 -2
- package/src/report/dot/module-utl.js +47 -19
- package/src/report/dot/prepare-custom-level.js +2 -2
- package/src/report/dot/prepare-flat-level.js +2 -2
- package/src/report/dot/prepare-folder-level.js +2 -2
- package/src/schema/configuration.schema.js +3 -0
- package/src/schema/cruise-result.schema.js +4 -0
- package/src/validate/match-dependency-rule.js +1 -0
- package/src/validate/matchers.js +12 -0
- package/types/baseline-violations.d.ts +1 -1
- package/types/cruise-result.d.ts +9 -48
- package/types/options.d.ts +5 -0
- package/types/reporter-options.d.ts +6 -0
- package/types/restrictions.d.ts +12 -0
- package/types/rule-summary.d.ts +23 -0
- package/types/violations.d.ts +24 -0
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ you can stick on the wall to impress your grandma.
|
|
|
21
21
|
### Install it
|
|
22
22
|
|
|
23
23
|
- `npm install --save-dev dependency-cruiser` to use it as a validator in your project (recommended) or...
|
|
24
|
-
- `npm install --global dependency-cruiser` if you just want to
|
|
24
|
+
- `npm install --global dependency-cruiser` if you just want to inspect multiple projects.
|
|
25
25
|
|
|
26
26
|
### Show stuff to your grandma
|
|
27
27
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.9.0",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -76,7 +76,6 @@
|
|
|
76
76
|
"depcruise:all": "node ./bin/dependency-cruise.js src bin test configs types tools --config",
|
|
77
77
|
"depcruise:baseline": "node ./bin/depcruise-baseline.js src bin test configs types tools",
|
|
78
78
|
"depcruise:explain": "node ./bin/dependency-cruise.js src bin test configs types tools --output-type err-long --config --progress none",
|
|
79
|
-
"depcruise:graph:dev": "node ./bin/dependency-cruise.js bin src --prefix vscode://file/$(pwd)/ --config --output-type dot --progress cli-feedback | dot -T svg | node ./bin/wrap-stream-in-html.js | browser",
|
|
80
79
|
"depcruise:graph:doc": "npm-run-all depcruise:graph:doc:json --parallel depcruise:graph:doc:fmt-* depcruise:graph:doc:samples",
|
|
81
80
|
"depcruise:graph:doc:json": "node ./bin/dependency-cruise.js bin src test --config --output-type json --output-to tmp_graph_deps.json --progress",
|
|
82
81
|
"depcruise:graph:doc:fmt-detail": "./bin/depcruise-fmt.js -T dot -f - tmp_graph_deps.json | dot -T svg | tee doc/real-world-samples/dependency-cruiser-without-node_modules.svg | node bin/wrap-stream-in-html.js > docs/dependency-cruiser-dependency-graph.html",
|
|
@@ -88,7 +87,9 @@
|
|
|
88
87
|
"depcruise:graph:dot": "node ./bin/dependency-cruise.js bin src --config --output-type dot | dot -T svg > tmp_deps.svg",
|
|
89
88
|
"depcruise:graph:fdp": "node ./bin/dependency-cruise.js bin src --config --output-type dot | fdp -GK=0.1 -Gsplines=true -T svg > tmp_deps.svg",
|
|
90
89
|
"depcruise:graph:osage": "node ./bin/dependency-cruise.js bin src --config --output-type dot | osage -Gpack=32 -GpackMode=array2 -T svg > tmp_deps.svg",
|
|
91
|
-
"depcruise:
|
|
90
|
+
"depcruise:graph:view": "node ./bin/dependency-cruise.js bin src --prefix vscode://file/$(pwd)/ --config configs/.dependency-cruiser-show-metrics-config.json --output-type dot --progress cli-feedback | dot -T svg | node ./bin/wrap-stream-in-html.js | browser",
|
|
91
|
+
"depcruise:report": "node ./bin/dependency-cruise.js src bin test configs types --output-type err-html --config configs/.dependency-cruiser-show-metrics-config.json --output-to dependency-violations.html",
|
|
92
|
+
"depcruise:report:view": "node ./bin/dependency-cruise.js src bin test configs types --output-type err-html --config configs/.dependency-cruiser-show-metrics-config.json --output-to - | browser",
|
|
92
93
|
"depcruise:focus": "node ./bin/dependency-cruise.js src bin test configs types --progress --config --output-type text --focus",
|
|
93
94
|
"lint": "npm-run-all --parallel --aggregate-output lint:eslint lint:prettier:check lint:types",
|
|
94
95
|
"lint:eslint": "eslint bin/dependency-cruise.js src test configs tools/**/*.mjs --cache --cache-location .cache/eslint/",
|
|
@@ -151,18 +152,18 @@
|
|
|
151
152
|
"safe-regex": "2.1.1",
|
|
152
153
|
"semver": "^7.3.5",
|
|
153
154
|
"semver-try-require": "^5.0.1",
|
|
154
|
-
"teamcity-service-messages": "0.1.
|
|
155
|
+
"teamcity-service-messages": "0.1.12",
|
|
155
156
|
"tsconfig-paths-webpack-plugin": "3.5.2",
|
|
156
157
|
"wrap-ansi": "^7.0.0"
|
|
157
158
|
},
|
|
158
159
|
"devDependencies": {
|
|
159
|
-
"@babel/core": "7.16.
|
|
160
|
-
"@babel/plugin-transform-modules-commonjs": "7.16.
|
|
161
|
-
"@babel/preset-typescript": "7.16.
|
|
162
|
-
"@swc/core": "1.2.
|
|
163
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
164
|
-
"@typescript-eslint/parser": "5.
|
|
165
|
-
"@vue/compiler-sfc": "3.2.
|
|
160
|
+
"@babel/core": "7.16.5",
|
|
161
|
+
"@babel/plugin-transform-modules-commonjs": "7.16.5",
|
|
162
|
+
"@babel/preset-typescript": "7.16.5",
|
|
163
|
+
"@swc/core": "1.2.120",
|
|
164
|
+
"@typescript-eslint/eslint-plugin": "5.7.0",
|
|
165
|
+
"@typescript-eslint/parser": "5.7.0",
|
|
166
|
+
"@vue/compiler-sfc": "3.2.26",
|
|
166
167
|
"c8": "7.10.0",
|
|
167
168
|
"chai": "4.3.4",
|
|
168
169
|
"chai-json-schema": "1.5.1",
|
|
@@ -172,7 +173,7 @@
|
|
|
172
173
|
"eslint-config-prettier": "8.3.0",
|
|
173
174
|
"eslint-plugin-budapestian": "3.0.1",
|
|
174
175
|
"eslint-plugin-import": "2.25.3",
|
|
175
|
-
"eslint-plugin-mocha": "9.0.0",
|
|
176
|
+
"eslint-plugin-mocha": "^9.0.0",
|
|
176
177
|
"eslint-plugin-node": "11.1.0",
|
|
177
178
|
"eslint-plugin-security": "1.4.0",
|
|
178
179
|
"eslint-plugin-unicorn": "39.0.0",
|
|
@@ -182,12 +183,12 @@
|
|
|
182
183
|
"mocha": "9.1.3",
|
|
183
184
|
"normalize-newline": "^3.0.0",
|
|
184
185
|
"npm-run-all": "4.1.5",
|
|
185
|
-
"prettier": "2.5.
|
|
186
|
+
"prettier": "2.5.1",
|
|
186
187
|
"proxyquire": "2.1.3",
|
|
187
188
|
"shx": "0.3.3",
|
|
188
|
-
"svelte": "3.44.
|
|
189
|
+
"svelte": "3.44.3",
|
|
189
190
|
"symlink-dir": "5.0.1",
|
|
190
|
-
"typescript": "4.5.
|
|
191
|
+
"typescript": "4.5.4",
|
|
191
192
|
"upem": "^7.0.0",
|
|
192
193
|
"vue-template-compiler": "2.6.14",
|
|
193
194
|
"yarn": "1.22.17"
|
|
@@ -219,6 +220,11 @@
|
|
|
219
220
|
"policy": "wanted",
|
|
220
221
|
"because": "version 5 only exports ejs - and we use cjs and don't transpile"
|
|
221
222
|
},
|
|
223
|
+
{
|
|
224
|
+
"package": "eslint-plugin-mocha",
|
|
225
|
+
"policy": "wanted",
|
|
226
|
+
"because": "version 10 dropped support for node 12, which we still do support"
|
|
227
|
+
},
|
|
222
228
|
{
|
|
223
229
|
"package": "normalize-newline",
|
|
224
230
|
"policy": "wanted",
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const getStabilityMetrics = require("./get-stability-metrics");
|
|
2
|
-
const { shouldDeriveMetrics } = require("./utl");
|
|
3
2
|
|
|
4
3
|
module.exports = function deriveMetrics(pModules, pOptions) {
|
|
5
|
-
if (
|
|
4
|
+
if (pOptions.metrics) {
|
|
6
5
|
return { folders: getStabilityMetrics(pModules) };
|
|
7
6
|
}
|
|
8
7
|
return {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable security/detect-object-injection */
|
|
2
2
|
const path = require("path").posix;
|
|
3
|
-
const {
|
|
3
|
+
const { object2Array, getParentFolders } = require("./utl");
|
|
4
4
|
const {
|
|
5
5
|
getAfferentCouplings,
|
|
6
6
|
getEfferentCouplings,
|
|
@@ -63,8 +63,8 @@ function getFolderLevelCouplings(pCouplingArray) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function calculateFolderMetrics(pFolder) {
|
|
66
|
-
const lModuleDependents =
|
|
67
|
-
const lModuleDependencies =
|
|
66
|
+
const lModuleDependents = object2Array(pFolder.dependents);
|
|
67
|
+
const lModuleDependencies = object2Array(pFolder.dependencies);
|
|
68
68
|
const lAfferentCouplings = lModuleDependents.reduce(sumCounts, 0);
|
|
69
69
|
const lEfferentCouplings = lModuleDependencies.reduce(sumCounts, 0);
|
|
70
70
|
|
|
@@ -83,7 +83,7 @@ function calculateFolderMetrics(pFolder) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
module.exports = function getStabilityMetrics(pModules) {
|
|
86
|
-
return
|
|
86
|
+
return object2Array(
|
|
87
87
|
pModules.filter(metricsAreCalculable).reduce((pAllFolders, pModule) => {
|
|
88
88
|
getParentFolders(path.dirname(pModule.source)).forEach(
|
|
89
89
|
(pParentDirectory) =>
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
const { findModuleByName, clearCache } = require("../utl");
|
|
2
2
|
const { metricsAreCalculable } = require("./module-utl");
|
|
3
|
-
const { shouldDeriveMetrics } = require("./utl");
|
|
4
3
|
|
|
5
4
|
module.exports = function deriveModuleMetrics(pModules, pOptions) {
|
|
6
|
-
if (
|
|
7
|
-
|
|
5
|
+
if (pOptions.metrics) {
|
|
6
|
+
const lModules = pModules.map((pModule) => ({
|
|
8
7
|
...pModule,
|
|
9
8
|
...(metricsAreCalculable(pModule)
|
|
10
9
|
? {
|
|
@@ -14,16 +13,16 @@ module.exports = function deriveModuleMetrics(pModules, pOptions) {
|
|
|
14
13
|
}
|
|
15
14
|
: {}),
|
|
16
15
|
}));
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
clearCache();
|
|
17
|
+
return lModules.map((pModule) => ({
|
|
18
|
+
...pModule,
|
|
19
|
+
dependencies: pModule.dependencies.map((pDependency) => ({
|
|
20
|
+
...pDependency,
|
|
21
|
+
instability:
|
|
22
|
+
(findModuleByName(lModules, pDependency.resolved) || {})
|
|
23
|
+
.instability || 0,
|
|
24
|
+
})),
|
|
25
|
+
}));
|
|
27
26
|
}
|
|
28
27
|
return pModules;
|
|
29
28
|
};
|
|
@@ -10,19 +10,14 @@ function getParentFolders(pPath) {
|
|
|
10
10
|
return lReturnValue.reverse();
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function
|
|
13
|
+
function object2Array(pObject) {
|
|
14
14
|
return Object.keys(pObject).map((pKey) => ({
|
|
15
15
|
name: pKey,
|
|
16
16
|
...pObject[pKey],
|
|
17
17
|
}));
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
function shouldDeriveMetrics(pOptions) {
|
|
21
|
-
return pOptions.metrics || pOptions.outputType === "metrics";
|
|
22
|
-
}
|
|
23
|
-
|
|
24
20
|
module.exports = {
|
|
25
21
|
getParentFolders,
|
|
26
|
-
|
|
27
|
-
shouldDeriveMetrics,
|
|
22
|
+
object2Array,
|
|
28
23
|
};
|
|
@@ -19,7 +19,7 @@ module.exports = function enrichModules(pModules, pOptions) {
|
|
|
19
19
|
lModules = deriveOrphans(lModules);
|
|
20
20
|
bus.emit("progress", "analyzing: reachables", { level: busLogLevels.INFO });
|
|
21
21
|
lModules = deriveReachable(lModules, pOptions.ruleSet);
|
|
22
|
-
bus.emit("progress", "analyzing:
|
|
22
|
+
bus.emit("progress", "analyzing: module metrics", {
|
|
23
23
|
level: busLogLevels.INFO,
|
|
24
24
|
});
|
|
25
25
|
lModules = deriveModuleMetrics(lModules, pOptions);
|
|
@@ -66,6 +66,32 @@ function normalizeCollapse(pCollapse) {
|
|
|
66
66
|
return lReturnValue;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
function hasMetricsRule(pRule) {
|
|
70
|
+
return _has(pRule, "to.moreUnstable");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function ruleSetHasMetricsRule(pRuleSet) {
|
|
74
|
+
const lRuleSet = pRuleSet || {};
|
|
75
|
+
return (
|
|
76
|
+
(lRuleSet.forbidden || []).some(hasMetricsRule) ||
|
|
77
|
+
(lRuleSet.allowed || []).some(hasMetricsRule)
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Determines whether (instability) metrics should be calculated
|
|
83
|
+
*
|
|
84
|
+
* @param {import('../../../types/options').ICruiseOptions pOptions
|
|
85
|
+
* @returns Boolean
|
|
86
|
+
*/
|
|
87
|
+
function shouldCalculateMetrics(pOptions) {
|
|
88
|
+
return (
|
|
89
|
+
pOptions.metrics ||
|
|
90
|
+
pOptions.outputType === "metrics" ||
|
|
91
|
+
ruleSetHasMetricsRule(pOptions.ruleSet)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
69
95
|
/**
|
|
70
96
|
*
|
|
71
97
|
* @param {Partial <import('../../../types/options').ICruiseOptions>} pOptions
|
|
@@ -101,6 +127,8 @@ function normalizeCruiseOptions(pOptions) {
|
|
|
101
127
|
lReturnValue.reporterOptions
|
|
102
128
|
);
|
|
103
129
|
}
|
|
130
|
+
lReturnValue.metrics = shouldCalculateMetrics(pOptions);
|
|
131
|
+
|
|
104
132
|
return lReturnValue;
|
|
105
133
|
}
|
|
106
134
|
|
package/src/meta.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var Handlebars=require("handlebars/runtime"),template=Handlebars.template,templates=Handlebars.templates=Handlebars.templates||{};templates["dot.template.hbs"]=template({1:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return null!=(a="function"==typeof(a=null!=(a=a(e,"graphAttrs")||(null!=n?a(n,"graphAttrs"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"graphAttrs",hash:{},data:o,loc:{start:{line:2,column:22},end:{line:2,column:38}}}):a)?a:""},3:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return"node ["+(null!=(a="function"==typeof(a=null!=(a=a(e,"nodeAttrs")||(null!=n?a(n,"nodeAttrs"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"nodeAttrs",hash:{},data:o,loc:{start:{line:3,column:27},end:{line:3,column:42}}}):a)?a:"")+"]"},5:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return"edge ["+(null!=(a="function"==typeof(a=null!=(a=a(e,"edgeAttrs")||(null!=n?a(n,"edgeAttrs"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"edgeAttrs",hash:{},data:o,loc:{start:{line:4,column:27},end:{line:4,column:42}}}):a)?a:"")+"]"},7:function(l,n,e,t,o,a,r){var u=null!=n?n:l.nullContext||{},
|
|
1
|
+
var Handlebars=require("handlebars/runtime"),template=Handlebars.template,templates=Handlebars.templates=Handlebars.templates||{};templates["dot.template.hbs"]=template({1:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return null!=(a="function"==typeof(a=null!=(a=a(e,"graphAttrs")||(null!=n?a(n,"graphAttrs"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"graphAttrs",hash:{},data:o,loc:{start:{line:2,column:22},end:{line:2,column:38}}}):a)?a:""},3:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return"node ["+(null!=(a="function"==typeof(a=null!=(a=a(e,"nodeAttrs")||(null!=n?a(n,"nodeAttrs"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"nodeAttrs",hash:{},data:o,loc:{start:{line:3,column:27},end:{line:3,column:42}}}):a)?a:"")+"]"},5:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return"edge ["+(null!=(a="function"==typeof(a=null!=(a=a(e,"edgeAttrs")||(null!=n?a(n,"edgeAttrs"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"edgeAttrs",hash:{},data:o,loc:{start:{line:4,column:27},end:{line:4,column:42}}}):a)?a:"")+"]"},7:function(l,n,e,t,o,a,r){var u=null!=n?n:l.nullContext||{},i=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]},c=null!=(p=i(e,"if").call(u,null!=n?i(n,"folder"):n,{name:"if",hash:{},fn:l.program(8,o,0,a,r),inverse:l.program(18,o,0,a,r),data:o,loc:{start:{line:7,column:4},end:{line:12,column:11}}}))?p:"",s=null!=(s=i(e,"dependencies")||(null!=n?i(n,"dependencies"):n))?s:l.hooks.helperMissing,o={name:"dependencies",hash:{},fn:l.program(20,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:13,column:4},end:{line:15,column:21}}},p="function"==typeof s?s.call(u,o):s;return null!=(p=!i(e,"dependencies")?l.hooks.blockHelperMissing.call(n,p,o):p)&&(c+=p),c},8:function(l,n,e,t,o,a,r){var u,i,c=null!=n?n:l.nullContext||{},s=l.hooks.helperMissing,p="function",m=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return" "+(null!=(u=m(e,"each").call(c,null!=n?m(n,"path"):n,{name:"each",hash:{},fn:l.program(9,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:8,column:4},end:{line:8,column:201}}}))?u:"")+'"'+(null!=(u=typeof(i=null!=(i=m(e,"source")||(null!=n?m(n,"source"):n))?i:s)==p?i.call(c,{name:"source",hash:{},data:o,loc:{start:{line:9,column:9},end:{line:9,column:21}}}):i)?u:"")+'" [label='+(null!=(u=typeof(i=null!=(i=m(e,"label")||(null!=n?m(n,"label"):n))?i:s)==p?i.call(c,{name:"label",hash:{},data:o,loc:{start:{line:9,column:30},end:{line:9,column:41}}}):i)?u:"")+' tooltip="'+(null!=(u=typeof(i=null!=(i=m(e,"tooltip")||(null!=n?m(n,"tooltip"):n))?i:s)==p?i.call(c,{name:"tooltip",hash:{},data:o,loc:{start:{line:9,column:51},end:{line:9,column:64}}}):i)?u:"")+'" '+(null!=(u=m(e,"if").call(c,null!=n?m(n,"URL"):n,{name:"if",hash:{},fn:l.program(12,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:9,column:66},end:{line:9,column:100}}}))?u:"")+(null!=(u=m(e,"if").call(c,null!=n?m(n,"themeAttrs"):n,{name:"if",hash:{},fn:l.program(14,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:9,column:100},end:{line:9,column:141}}}))?u:"")+"]"+(null!=(u=m(e,"each").call(c,null!=n?m(n,"path"):n,{name:"each",hash:{},fn:l.program(16,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:9,column:142},end:{line:9,column:167}}}))?u:"")+"\n"},9:function(l,n,e,t,o,a,r){var u,i,c=null!=n?n:l.nullContext||{},s=l.hooks.helperMissing,p="function",m=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return'subgraph "cluster_'+(null!=(u=typeof(i=null!=(i=m(e,"aggregateSnippet")||(null!=n?m(n,"aggregateSnippet"):n))?i:s)==p?i.call(c,{name:"aggregateSnippet",hash:{},data:o,loc:{start:{line:8,column:36},end:{line:8,column:58}}}):i)?u:"")+'" {label="'+(null!=(u=typeof(i=null!=(i=m(e,"snippet")||(null!=n?m(n,"snippet"):n))?i:s)==p?i.call(c,{name:"snippet",hash:{},data:o,loc:{start:{line:8,column:68},end:{line:8,column:81}}}):i)?u:"")+'" '+(null!=(u=m(e,"if").call(c,null!=r[2]?m(r[2],"clustersHaveOwnNode"):r[2],{name:"if",hash:{},fn:l.program(10,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:8,column:83},end:{line:8,column:191}}}))?u:"")},10:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return'"'+(null!=(a="function"==typeof(a=null!=(a=a(e,"aggregateSnippet")||(null!=n?a(n,"aggregateSnippet"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"aggregateSnippet",hash:{},data:o,loc:{start:{line:8,column:117},end:{line:8,column:139}}}):a)?a:"")+'" [width="0.05" shape="point" style="invis"] '},12:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return'URL="'+(null!=(a="function"==typeof(a=null!=(a=a(e,"URL")||(null!=n?a(n,"URL"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"URL",hash:{},data:o,loc:{start:{line:9,column:82},end:{line:9,column:91}}}):a)?a:"")+'" '},14:function(l,n,e,t,o){var a=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return null!=(a="function"==typeof(a=null!=(a=a(e,"themeAttrs")||(null!=n?a(n,"themeAttrs"):n))?a:l.hooks.helperMissing)?a.call(null!=n?n:l.nullContext||{},{name:"themeAttrs",hash:{},data:o,loc:{start:{line:9,column:118},end:{line:9,column:134}}}):a)?a:""},16:function(l,n,e,t,o){return" }"},18:function(l,n,e,t,o,a,r){var u,i,c=null!=n?n:l.nullContext||{},s=l.hooks.helperMissing,p="function",m=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return' "'+(null!=(u=typeof(i=null!=(i=m(e,"source")||(null!=n?m(n,"source"):n))?i:s)==p?i.call(c,{name:"source",hash:{},data:o,loc:{start:{line:11,column:5},end:{line:11,column:17}}}):i)?u:"")+'" [label='+(null!=(u=typeof(i=null!=(i=m(e,"label")||(null!=n?m(n,"label"):n))?i:s)==p?i.call(c,{name:"label",hash:{},data:o,loc:{start:{line:11,column:26},end:{line:11,column:37}}}):i)?u:"")+' tooltip="'+(null!=(u=typeof(i=null!=(i=m(e,"tooltip")||(null!=n?m(n,"tooltip"):n))?i:s)==p?i.call(c,{name:"tooltip",hash:{},data:o,loc:{start:{line:11,column:47},end:{line:11,column:60}}}):i)?u:"")+'" '+(null!=(u=m(e,"if").call(c,null!=n?m(n,"URL"):n,{name:"if",hash:{},fn:l.program(12,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:11,column:62},end:{line:11,column:96}}}))?u:"")+(null!=(u=m(e,"if").call(c,null!=n?m(n,"themeAttrs"):n,{name:"if",hash:{},fn:l.program(14,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:11,column:96},end:{line:11,column:137}}}))?u:"")+"]\n"},20:function(l,n,e,t,o,a,r){var u,i,c=null!=n?n:l.nullContext||{},s=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return' "'+(null!=(u=l.lambda(null!=r[1]?s(r[1],"source"):r[1],n))?u:"")+'" -> "'+(null!=(u="function"==typeof(i=null!=(i=s(e,"resolved")||(null!=n?s(n,"resolved"):n))?i:l.hooks.helperMissing)?i.call(c,{name:"resolved",hash:{},data:o,loc:{start:{line:14,column:26},end:{line:14,column:40}}}):i)?u:"")+'"'+(null!=(u=s(e,"if").call(c,null!=n?s(n,"hasExtraAttributes"):n,{name:"if",hash:{},fn:l.program(21,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:14,column:41},end:{line:14,column:193}}}))?u:"")+"\n"},21:function(l,n,e,t,o,a,r){var u,i=null!=n?n:l.nullContext||{},c=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return" ["+(null!=(u=c(e,"if").call(i,null!=(u=null!=n?c(n,"rule"):n)?c(u,"name"):u,{name:"if",hash:{},fn:l.program(22,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:14,column:69},end:{line:14,column:144}}}))?u:"")+(null!=(u=c(e,"if").call(i,null!=n?c(n,"themeAttrs"):n,{name:"if",hash:{},fn:l.program(14,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:14,column:144},end:{line:14,column:185}}}))?u:"")+"]"},22:function(l,n,e,t,o){var a=l.lambda,r=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]};return'xlabel="'+(null!=(l=a(null!=(l=null!=n?r(n,"rule"):n)?r(l,"name"):l,n))?l:"")+'" tooltip="'+(null!=(l=a(null!=(l=null!=n?r(n,"rule"):n)?r(l,"name"):l,n))?l:"")+'" '},compiler:[8,">= 4.3.0"],main:function(l,n,e,t,o,a,r){var u=null!=n?n:l.nullContext||{},i=l.lookupProperty||function(l,n){if(Object.prototype.hasOwnProperty.call(l,n))return l[n]},c='strict digraph "dependency-cruiser output"{\n '+(null!=(p=i(e,"if").call(u,null!=n?i(n,"graphAttrs"):n,{name:"if",hash:{},fn:l.program(1,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:2,column:4},end:{line:2,column:45}}}))?p:"")+"\n "+(null!=(p=i(e,"if").call(u,null!=n?i(n,"nodeAttrs"):n,{name:"if",hash:{},fn:l.program(3,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:3,column:4},end:{line:3,column:50}}}))?p:"")+"\n "+(null!=(p=i(e,"if").call(u,null!=n?i(n,"edgeAttrs"):n,{name:"if",hash:{},fn:l.program(5,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:4,column:4},end:{line:4,column:50}}}))?p:"")+"\n\n",s=null!=(s=i(e,"modules")||(null!=n?i(n,"modules"):n))?s:l.hooks.helperMissing,o={name:"modules",hash:{},fn:l.program(7,o,0,a,r),inverse:l.noop,data:o,loc:{start:{line:6,column:0},end:{line:16,column:12}}},p="function"==typeof s?s.call(u,o):s;return null!=(p=!i(e,"modules")?l.hooks.blockHelperMissing.call(n,p,o):p)&&(c+=p),c+"}\n"},useData:!0,useDepths:!0});
|
package/src/report/dot/index.js
CHANGED
|
@@ -17,7 +17,11 @@ const GRANULARITY2FUNCTION = {
|
|
|
17
17
|
flat: prepareFlatLevel,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
function report(
|
|
20
|
+
function report(
|
|
21
|
+
pResults,
|
|
22
|
+
pGranularity,
|
|
23
|
+
{ theme, collapsePattern, filters, showMetrics }
|
|
24
|
+
) {
|
|
21
25
|
const lTheme = theming.normalizeTheme(theme);
|
|
22
26
|
const lResults = filters
|
|
23
27
|
? {
|
|
@@ -35,7 +39,8 @@ function report(pResults, pGranularity, { theme, collapsePattern, filters }) {
|
|
|
35
39
|
modules: (GRANULARITY2FUNCTION[pGranularity] || prepareCustomLevel)(
|
|
36
40
|
lResults,
|
|
37
41
|
lTheme,
|
|
38
|
-
collapsePattern
|
|
42
|
+
collapsePattern,
|
|
43
|
+
showMetrics
|
|
39
44
|
),
|
|
40
45
|
});
|
|
41
46
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const path = require("path").posix;
|
|
2
|
+
const _has = require("lodash/has");
|
|
2
3
|
const theming = require("./theming");
|
|
3
4
|
|
|
5
|
+
const PROTOCOL_PREFIX_RE = /^[a-z]+:\/\//;
|
|
6
|
+
|
|
4
7
|
function attributizeObject(pObject) {
|
|
5
8
|
return (
|
|
6
9
|
Object.keys(pObject)
|
|
@@ -12,7 +15,9 @@ function attributizeObject(pObject) {
|
|
|
12
15
|
|
|
13
16
|
function extractFirstTransgression(pModule) {
|
|
14
17
|
return {
|
|
15
|
-
...(pModule
|
|
18
|
+
...(_has(pModule, "rules[0]")
|
|
19
|
+
? { ...pModule, tooltip: pModule.rules[0].name }
|
|
20
|
+
: pModule),
|
|
16
21
|
dependencies: pModule.dependencies.map((pDependency) =>
|
|
17
22
|
pDependency.rules
|
|
18
23
|
? {
|
|
@@ -57,20 +62,37 @@ function aggregate(pPathSnippet, pCounter, pPathArray) {
|
|
|
57
62
|
};
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
function
|
|
61
|
-
let
|
|
62
|
-
let lDirectoryName = path.dirname(pModule.source);
|
|
65
|
+
function makeInstabilityString(pModule, pShowMetrics = false) {
|
|
66
|
+
let lInstabilityString = "";
|
|
63
67
|
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
if (pShowMetrics && _has(pModule, "instability") && !pModule.consolidated) {
|
|
69
|
+
lInstabilityString = ` <FONT color="#808080" point-size="8">${Math.round(
|
|
70
|
+
// eslint-disable-next-line no-magic-numbers
|
|
71
|
+
100 * pModule.instability
|
|
72
|
+
)}</FONT>`;
|
|
67
73
|
}
|
|
74
|
+
return lInstabilityString;
|
|
75
|
+
}
|
|
68
76
|
|
|
69
|
-
|
|
77
|
+
function folderify(pShowMetrics) {
|
|
78
|
+
return (pModule) => {
|
|
79
|
+
let lAdditions = {};
|
|
80
|
+
let lDirectoryName = path.dirname(pModule.source);
|
|
70
81
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
if (lDirectoryName !== ".") {
|
|
83
|
+
lAdditions.folder = lDirectoryName;
|
|
84
|
+
lAdditions.path = lDirectoryName.split(path.sep).map(aggregate);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
lAdditions.label = `<${path.basename(
|
|
88
|
+
pModule.source
|
|
89
|
+
)}${makeInstabilityString(pModule, pShowMetrics)}>`;
|
|
90
|
+
lAdditions.tooltip = path.basename(pModule.source);
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
...pModule,
|
|
94
|
+
...lAdditions,
|
|
95
|
+
};
|
|
74
96
|
};
|
|
75
97
|
}
|
|
76
98
|
|
|
@@ -87,7 +109,7 @@ function folderify(pModule) {
|
|
|
87
109
|
* @return {string} prefix and filename concatenated
|
|
88
110
|
*/
|
|
89
111
|
function smartURIConcat(pPrefix, pSource) {
|
|
90
|
-
if (pPrefix.match(
|
|
112
|
+
if (pPrefix.match(PROTOCOL_PREFIX_RE)) {
|
|
91
113
|
return `${pPrefix}${pSource}`;
|
|
92
114
|
} else {
|
|
93
115
|
return path.join(pPrefix, pSource);
|
|
@@ -103,15 +125,21 @@ function addURL(pPrefix) {
|
|
|
103
125
|
});
|
|
104
126
|
}
|
|
105
127
|
|
|
106
|
-
function
|
|
107
|
-
return {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
pModule.source
|
|
111
|
-
)}</B>>`,
|
|
112
|
-
};
|
|
128
|
+
function makeLabel(pModule, pShowMetrics) {
|
|
129
|
+
return `<${path.dirname(pModule.source)}/<BR/><B>${path.basename(
|
|
130
|
+
pModule.source
|
|
131
|
+
)}</B>${makeInstabilityString(pModule, pShowMetrics)}>`;
|
|
113
132
|
}
|
|
114
133
|
|
|
134
|
+
function flatLabel(pShowMetrics) {
|
|
135
|
+
return (pModule) => {
|
|
136
|
+
return {
|
|
137
|
+
...pModule,
|
|
138
|
+
label: makeLabel(pModule, pShowMetrics),
|
|
139
|
+
tooltip: path.basename(pModule.source),
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
}
|
|
115
143
|
module.exports = {
|
|
116
144
|
folderify,
|
|
117
145
|
applyTheme,
|
|
@@ -4,15 +4,15 @@ const compare = require("../../graph-utl/compare");
|
|
|
4
4
|
const stripSelfTransitions = require("../../graph-utl/strip-self-transitions");
|
|
5
5
|
const moduleUtl = require("./module-utl");
|
|
6
6
|
|
|
7
|
-
module.exports = (pResults, pTheme, pCollapsePattern) => {
|
|
7
|
+
module.exports = (pResults, pTheme, pCollapsePattern, pShowMetrics) => {
|
|
8
8
|
return (
|
|
9
9
|
pCollapsePattern
|
|
10
10
|
? consolidateToPattern(pResults.modules, pCollapsePattern)
|
|
11
11
|
: pResults.modules
|
|
12
12
|
)
|
|
13
13
|
.sort(compare.modules)
|
|
14
|
+
.map(moduleUtl.folderify(pShowMetrics))
|
|
14
15
|
.map(moduleUtl.extractFirstTransgression)
|
|
15
|
-
.map(moduleUtl.folderify)
|
|
16
16
|
.map(stripSelfTransitions)
|
|
17
17
|
.map(moduleUtl.applyTheme(pTheme))
|
|
18
18
|
.map(moduleUtl.addURL(_get(pResults, "summary.optionsUsed.prefix", "")));
|
|
@@ -2,10 +2,10 @@ const _get = require("lodash/get");
|
|
|
2
2
|
const compare = require("../../graph-utl/compare");
|
|
3
3
|
const moduleUtl = require("./module-utl");
|
|
4
4
|
|
|
5
|
-
module.exports = (pResults, pTheme) => {
|
|
5
|
+
module.exports = (pResults, pTheme, _, pShowMetrics) => {
|
|
6
6
|
return pResults.modules
|
|
7
7
|
.sort(compare.modules)
|
|
8
|
-
.map(moduleUtl.flatLabel)
|
|
8
|
+
.map(moduleUtl.flatLabel(pShowMetrics))
|
|
9
9
|
.map(moduleUtl.extractFirstTransgression)
|
|
10
10
|
.map(moduleUtl.applyTheme(pTheme))
|
|
11
11
|
.map(moduleUtl.addURL(_get(pResults, "summary.optionsUsed.prefix", "")));
|
|
@@ -4,11 +4,11 @@ const compare = require("../../graph-utl/compare");
|
|
|
4
4
|
const stripSelfTransitions = require("../../graph-utl/strip-self-transitions");
|
|
5
5
|
const moduleUtl = require("./module-utl");
|
|
6
6
|
|
|
7
|
-
module.exports = (pResults, pTheme) => {
|
|
7
|
+
module.exports = (pResults, pTheme, _, pShowMetrics) => {
|
|
8
8
|
return consolidateToFolder(pResults.modules)
|
|
9
9
|
.sort(compare.modules)
|
|
10
10
|
.map(moduleUtl.extractFirstTransgression)
|
|
11
|
-
.map(moduleUtl.folderify)
|
|
11
|
+
.map(moduleUtl.folderify(pShowMetrics))
|
|
12
12
|
.map(stripSelfTransitions)
|
|
13
13
|
.map(moduleUtl.applyTheme(pTheme))
|
|
14
14
|
.map(moduleUtl.addURL(_get(pResults, "summary.optionsUsed.prefix", "")));
|
|
@@ -168,6 +168,7 @@ module.exports = {
|
|
|
168
168
|
licenseNot: { $ref: "#/definitions/REAsStringsType" },
|
|
169
169
|
via: { $ref: "#/definitions/REAsStringsType" },
|
|
170
170
|
viaNot: { $ref: "#/definitions/REAsStringsType" },
|
|
171
|
+
moreUnstable: { type: "boolean" },
|
|
171
172
|
},
|
|
172
173
|
},
|
|
173
174
|
DependentsModuleRestrictionType: {
|
|
@@ -348,6 +349,7 @@ module.exports = {
|
|
|
348
349
|
},
|
|
349
350
|
},
|
|
350
351
|
},
|
|
352
|
+
metrics: { type: "boolean" },
|
|
351
353
|
baseDir: { type: "string" },
|
|
352
354
|
},
|
|
353
355
|
},
|
|
@@ -426,6 +428,7 @@ module.exports = {
|
|
|
426
428
|
properties: {
|
|
427
429
|
collapsePattern: { $ref: "#/definitions/REAsStringsType" },
|
|
428
430
|
filters: { $ref: "#/definitions/ReporterFiltersType" },
|
|
431
|
+
showMetrics: { type: "boolean" },
|
|
429
432
|
theme: { $ref: "#/definitions/DotThemeType" },
|
|
430
433
|
},
|
|
431
434
|
},
|
|
@@ -127,6 +127,7 @@ module.exports = {
|
|
|
127
127
|
type: "array",
|
|
128
128
|
items: { $ref: "#/definitions/RuleSummaryType" },
|
|
129
129
|
},
|
|
130
|
+
instability: { type: "number" },
|
|
130
131
|
},
|
|
131
132
|
},
|
|
132
133
|
DependencyTypeType: {
|
|
@@ -357,6 +358,7 @@ module.exports = {
|
|
|
357
358
|
licenseNot: { $ref: "#/definitions/REAsStringsType" },
|
|
358
359
|
via: { $ref: "#/definitions/REAsStringsType" },
|
|
359
360
|
viaNot: { $ref: "#/definitions/REAsStringsType" },
|
|
361
|
+
moreUnstable: { type: "boolean" },
|
|
360
362
|
},
|
|
361
363
|
},
|
|
362
364
|
DependentsModuleRestrictionType: {
|
|
@@ -496,6 +498,7 @@ module.exports = {
|
|
|
496
498
|
},
|
|
497
499
|
},
|
|
498
500
|
},
|
|
501
|
+
metrics: { type: "boolean" },
|
|
499
502
|
baseDir: { type: "string" },
|
|
500
503
|
args: { type: "string" },
|
|
501
504
|
rulesFile: { type: "string" },
|
|
@@ -603,6 +606,7 @@ module.exports = {
|
|
|
603
606
|
properties: {
|
|
604
607
|
collapsePattern: { $ref: "#/definitions/REAsStringsType" },
|
|
605
608
|
filters: { $ref: "#/definitions/ReporterFiltersType" },
|
|
609
|
+
showMetrics: { type: "boolean" },
|
|
606
610
|
theme: { $ref: "#/definitions/DotThemeType" },
|
|
607
611
|
},
|
|
608
612
|
},
|
|
@@ -40,6 +40,7 @@ function match(pFrom, pTo) {
|
|
|
40
40
|
matchers.toExoticRequireNot(pRule, pTo) &&
|
|
41
41
|
matchers.toVia(pRule, pTo) &&
|
|
42
42
|
matchers.toViaNot(pRule, pTo) &&
|
|
43
|
+
matchers.toIsMoreUnstable(pRule, pFrom, pTo) &&
|
|
43
44
|
// preCompilationOnly is not a mandatory attribute, but if the attribute
|
|
44
45
|
// is in the rule but not in the dependency there won't be a match
|
|
45
46
|
// anyway, so we can use the default propertyEquals method regardless
|
package/src/validate/matchers.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const _has = require("lodash/has");
|
|
1
2
|
const { intersects } = require("../utl/array-util");
|
|
2
3
|
|
|
3
4
|
function fromPath(pRule, pModule) {
|
|
@@ -123,6 +124,16 @@ function toVia(pRule, pDependency) {
|
|
|
123
124
|
);
|
|
124
125
|
}
|
|
125
126
|
|
|
127
|
+
function toIsMoreUnstable(pRule, pFrom, pTo) {
|
|
128
|
+
if (_has(pRule, "to.moreUnstable")) {
|
|
129
|
+
return (
|
|
130
|
+
(pRule.to.moreUnstable && pFrom.instability < pTo.instability) ||
|
|
131
|
+
(!pRule.to.moreUnstable && pFrom.instability >= pTo.instability)
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
|
|
126
137
|
module.exports = {
|
|
127
138
|
_replaceGroupPlaceholders,
|
|
128
139
|
fromPath,
|
|
@@ -141,4 +152,5 @@ module.exports = {
|
|
|
141
152
|
toExoticRequireNot,
|
|
142
153
|
toVia,
|
|
143
154
|
toViaNot,
|
|
155
|
+
toIsMoreUnstable,
|
|
144
156
|
};
|
package/types/cruise-result.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { ICruiseOptions } from "./options";
|
|
2
2
|
import { IFlattenedRuleSet } from "./rule-set";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
SeverityType,
|
|
7
|
-
ProtocolType,
|
|
8
|
-
} from "./shared-types";
|
|
3
|
+
import { DependencyType, ModuleSystemType, ProtocolType } from "./shared-types";
|
|
4
|
+
import { IViolation } from "./violations";
|
|
5
|
+
import { IRuleSummary } from "./rule-summary";
|
|
9
6
|
|
|
10
7
|
export interface ICruiseResult {
|
|
11
8
|
/**
|
|
@@ -224,27 +221,11 @@ export interface IDependency {
|
|
|
224
221
|
* will be in the 'rule' object at the same level.
|
|
225
222
|
*/
|
|
226
223
|
valid: boolean;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* If there was a rule violation (valid === false), this object contains the name of the
|
|
231
|
-
* rule and severity of violating it.
|
|
232
|
-
*/
|
|
233
|
-
export interface IRuleSummary {
|
|
234
224
|
/**
|
|
235
|
-
*
|
|
236
|
-
* '
|
|
225
|
+
* the (de-normalized) instability of the dependency - also available in
|
|
226
|
+
* the module on the 'to' side of this dependency
|
|
237
227
|
*/
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* How severe a violation of a rule is. The 'error' severity will make some reporters return
|
|
241
|
-
* a non-zero exit code, so if you want e.g. a build to stop when there's a rule violated:
|
|
242
|
-
* use that. The absence of the 'ignore' severity here is by design; ignored rules don't
|
|
243
|
-
* show up in the output.
|
|
244
|
-
*
|
|
245
|
-
* Severity to use when a dependency is not in the 'allowed' set of rules. Defaults to 'warn'
|
|
246
|
-
*/
|
|
247
|
-
severity: SeverityType;
|
|
228
|
+
instability: number;
|
|
248
229
|
}
|
|
249
230
|
|
|
250
231
|
export interface IReachable {
|
|
@@ -389,29 +370,6 @@ export interface IWebpackConfig {
|
|
|
389
370
|
*/
|
|
390
371
|
export type WebpackEnvType = { [key: string]: any } | string;
|
|
391
372
|
|
|
392
|
-
export interface IViolation {
|
|
393
|
-
/**
|
|
394
|
-
* The violated rule
|
|
395
|
-
*/
|
|
396
|
-
rule: IRuleSummary;
|
|
397
|
-
/**
|
|
398
|
-
* The from part of the dependency this violation is about
|
|
399
|
-
*/
|
|
400
|
-
from: string;
|
|
401
|
-
/**
|
|
402
|
-
* The to part of the dependency this violation is about
|
|
403
|
-
*/
|
|
404
|
-
to: string;
|
|
405
|
-
/**
|
|
406
|
-
* The circular path if the violation is about circularity
|
|
407
|
-
*/
|
|
408
|
-
cycle?: string[];
|
|
409
|
-
/**
|
|
410
|
-
* The path from the from to the to if the violation is transitive
|
|
411
|
-
*/
|
|
412
|
-
via?: string[];
|
|
413
|
-
}
|
|
414
|
-
|
|
415
373
|
export interface IFolder {
|
|
416
374
|
/**
|
|
417
375
|
* The name of the folder. FOlder names are normalized to posix (so
|
|
@@ -455,3 +413,6 @@ export interface IFolder {
|
|
|
455
413
|
*/
|
|
456
414
|
instability?: number;
|
|
457
415
|
}
|
|
416
|
+
|
|
417
|
+
export * from "./violations";
|
|
418
|
+
export * from "./rule-summary";
|
package/types/options.d.ts
CHANGED
|
@@ -239,4 +239,9 @@ export interface ICruiseOptions {
|
|
|
239
239
|
*/
|
|
240
240
|
type: ProgressType;
|
|
241
241
|
};
|
|
242
|
+
/**
|
|
243
|
+
* When this flag is set to true, dependency-cruiser will calculate (stability) metrics
|
|
244
|
+
* for all modules and folders. Defaults to false.
|
|
245
|
+
*/
|
|
246
|
+
metrics?: boolean;
|
|
242
247
|
}
|
|
@@ -58,6 +58,12 @@ export interface IDotReporterOptions {
|
|
|
58
58
|
* goal of the report)
|
|
59
59
|
*/
|
|
60
60
|
filters?: IReporterFiltersType;
|
|
61
|
+
/**
|
|
62
|
+
* When passed the value 'true', shows instability metrics in the
|
|
63
|
+
* output if dependency-cruiser calculated them. Doesn't show them
|
|
64
|
+
* in all other cases. Defaults to false",
|
|
65
|
+
*/
|
|
66
|
+
showMetrics?: boolean;
|
|
61
67
|
/**
|
|
62
68
|
* A bunch of criteria to (conditionally) theme the dot output
|
|
63
69
|
*/
|
package/types/restrictions.d.ts
CHANGED
|
@@ -92,6 +92,18 @@ export interface IToRestriction extends IBaseRestrictionType {
|
|
|
92
92
|
* licenses. E.g. to flag everyting non MIT use "MIT" here
|
|
93
93
|
*/
|
|
94
94
|
licenseNot?: string | string[];
|
|
95
|
+
/**
|
|
96
|
+
* When set to true moreUnstable matches for any dependency that has a higher
|
|
97
|
+
* Instability than the module that depends on it. When set to false it matches
|
|
98
|
+
* when the opposite is true; the dependency has an equal or lower Instability.
|
|
99
|
+
*
|
|
100
|
+
* This attribute is useful when you want to check against Robert C. Martin's
|
|
101
|
+
* stable dependency * principle. See online documentation for examples and
|
|
102
|
+
* details.
|
|
103
|
+
*
|
|
104
|
+
* Leave this out when you don't care either way.
|
|
105
|
+
*/
|
|
106
|
+
moreUnstable?: boolean;
|
|
95
107
|
}
|
|
96
108
|
|
|
97
109
|
export interface IReachabilityToRestrictionType extends IBaseRestrictionType {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SeverityType } from "./shared-types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* If there was a rule violation (valid === false), this object contains the name of the
|
|
5
|
+
* rule and severity of violating it.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface IRuleSummary {
|
|
9
|
+
/**
|
|
10
|
+
* The (short, eslint style) name of the violated rule. Typically something like
|
|
11
|
+
* 'no-core-punycode' or 'no-outside-deps'.
|
|
12
|
+
*/
|
|
13
|
+
name: string;
|
|
14
|
+
/**
|
|
15
|
+
* How severe a violation of a rule is. The 'error' severity will make some reporters return
|
|
16
|
+
* a non-zero exit code, so if you want e.g. a build to stop when there's a rule violated:
|
|
17
|
+
* use that. The absence of the 'ignore' severity here is by design; ignored rules don't
|
|
18
|
+
* show up in the output.
|
|
19
|
+
*
|
|
20
|
+
* Severity to use when a dependency is not in the 'allowed' set of rules. Defaults to 'warn'
|
|
21
|
+
*/
|
|
22
|
+
severity: SeverityType;
|
|
23
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IRuleSummary } from "./rule-summary";
|
|
2
|
+
|
|
3
|
+
export interface IViolation {
|
|
4
|
+
/**
|
|
5
|
+
* The violated rule
|
|
6
|
+
*/
|
|
7
|
+
rule: IRuleSummary;
|
|
8
|
+
/**
|
|
9
|
+
* The from part of the dependency this violation is about
|
|
10
|
+
*/
|
|
11
|
+
from: string;
|
|
12
|
+
/**
|
|
13
|
+
* The to part of the dependency this violation is about
|
|
14
|
+
*/
|
|
15
|
+
to: string;
|
|
16
|
+
/**
|
|
17
|
+
* The circular path if the violation is about circularity
|
|
18
|
+
*/
|
|
19
|
+
cycle?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* The path from the from to the to if the violation is transitive
|
|
22
|
+
*/
|
|
23
|
+
via?: string[];
|
|
24
|
+
}
|