monorepo-next 9.1.1 → 9.2.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 +11 -0
- package/bin/commands/cycles.js +26 -0
- package/package.json +1 -1
- package/src/cycle.js +140 -0
- package/src/detect-circular-references.js +26 -0
package/README.md
CHANGED
@@ -23,6 +23,7 @@ Commands:
|
|
23
23
|
resume normal linking [aliases: a]
|
24
24
|
next changed-files [packages..] list changed files
|
25
25
|
next changed list changed packages
|
26
|
+
next cycles detect circular references
|
26
27
|
next defrag synchronize all dependency version
|
27
28
|
discrepancies
|
28
29
|
next detach [package] detach a package from normal linking
|
@@ -73,6 +74,16 @@ Options:
|
|
73
74
|
external dev dep, don't count it towards a package
|
74
75
|
change. [boolean] [default: false]
|
75
76
|
|
77
|
+
next cycles
|
78
|
+
|
79
|
+
detect circular references
|
80
|
+
|
81
|
+
Options:
|
82
|
+
--help Show help [boolean]
|
83
|
+
--version Show version number [boolean]
|
84
|
+
--detect-dev-dependencies, --dev alert when there is a devDependency in the
|
85
|
+
loop [boolean] [default: false]
|
86
|
+
|
76
87
|
next defrag
|
77
88
|
|
78
89
|
synchronize all dependency version discrepancies
|
@@ -0,0 +1,26 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
command: 'cycles',
|
5
|
+
describe: 'detect circular references',
|
6
|
+
builder: {
|
7
|
+
'detect-dev-dependencies': {
|
8
|
+
describe: 'alert when there is a devDependency in the loop',
|
9
|
+
alias: ['dev'],
|
10
|
+
type: 'boolean',
|
11
|
+
default: false,
|
12
|
+
},
|
13
|
+
},
|
14
|
+
async handler(argv) {
|
15
|
+
const detectCircularReferences = require('../../src/detect-circular-references');
|
16
|
+
|
17
|
+
let cycles = await detectCircularReferences({
|
18
|
+
...argv,
|
19
|
+
shouldDetectDevDependencies: argv['detect-dev-dependencies'],
|
20
|
+
});
|
21
|
+
|
22
|
+
for (let cycle of cycles) {
|
23
|
+
console.log(cycle);
|
24
|
+
}
|
25
|
+
},
|
26
|
+
};
|
package/package.json
CHANGED
package/src/cycle.js
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const dependencyTypes = require('./dependency-types');
|
4
|
+
|
5
|
+
function createPackageNode({
|
6
|
+
packageName,
|
7
|
+
dependencyType,
|
8
|
+
dependencyRange,
|
9
|
+
parent,
|
10
|
+
branch,
|
11
|
+
}) {
|
12
|
+
let group = {
|
13
|
+
parent,
|
14
|
+
dependencyType,
|
15
|
+
dependencyRange,
|
16
|
+
isCycle: false,
|
17
|
+
packageName,
|
18
|
+
};
|
19
|
+
|
20
|
+
let newBranch = [...branch, group].filter(Boolean);
|
21
|
+
|
22
|
+
return {
|
23
|
+
newGroup: group,
|
24
|
+
newBranch,
|
25
|
+
};
|
26
|
+
}
|
27
|
+
|
28
|
+
function findGroupInBranchByPackageName(branch, packageName) {
|
29
|
+
let _i = -1;
|
30
|
+
|
31
|
+
for (let i = 0; i < branch.length; i++) {
|
32
|
+
if (branch[i].packageName === packageName) {
|
33
|
+
_i = i;
|
34
|
+
|
35
|
+
break;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
return _i;
|
40
|
+
}
|
41
|
+
|
42
|
+
function _getCycles({
|
43
|
+
packages,
|
44
|
+
_package,
|
45
|
+
dependencyType,
|
46
|
+
dependencyRange,
|
47
|
+
parent,
|
48
|
+
branch,
|
49
|
+
visitedNodes,
|
50
|
+
cycles,
|
51
|
+
shouldDetectDevDependencies,
|
52
|
+
}) {
|
53
|
+
let visitedNode = visitedNodes[_package.packageName];
|
54
|
+
|
55
|
+
if (visitedNode) {
|
56
|
+
let i = findGroupInBranchByPackageName(branch, _package.packageName);
|
57
|
+
|
58
|
+
let isCycle = i !== -1;
|
59
|
+
|
60
|
+
let existingGroup = {
|
61
|
+
parent,
|
62
|
+
dependencyType,
|
63
|
+
dependencyRange,
|
64
|
+
isCycle,
|
65
|
+
packageName: visitedNode,
|
66
|
+
};
|
67
|
+
|
68
|
+
if (isCycle) {
|
69
|
+
let newBranch = [...branch.slice(i), existingGroup];
|
70
|
+
|
71
|
+
let cycle = newBranch.map(({ dependencyType, packageName }) => {
|
72
|
+
return [dependencyType, packageName];
|
73
|
+
});
|
74
|
+
|
75
|
+
cycles[cycle.flat().slice(1).join(' < ')] = existingGroup;
|
76
|
+
}
|
77
|
+
|
78
|
+
return;
|
79
|
+
}
|
80
|
+
|
81
|
+
let {
|
82
|
+
newGroup,
|
83
|
+
newBranch,
|
84
|
+
} = createPackageNode({
|
85
|
+
packageName: _package.packageName,
|
86
|
+
dependencyType,
|
87
|
+
dependencyRange,
|
88
|
+
parent,
|
89
|
+
branch,
|
90
|
+
});
|
91
|
+
|
92
|
+
visitedNodes[_package.packageName] = newGroup.packageName;
|
93
|
+
|
94
|
+
for (let dependencyType of dependencyTypes) {
|
95
|
+
if (!shouldDetectDevDependencies && dependencyType === 'devDependencies') {
|
96
|
+
continue;
|
97
|
+
}
|
98
|
+
|
99
|
+
for (let [packageName, dependencyRange] of Object.entries(_package[dependencyType])) {
|
100
|
+
let _package = packages[packageName];
|
101
|
+
|
102
|
+
_getCycles({
|
103
|
+
packages,
|
104
|
+
_package,
|
105
|
+
dependencyType,
|
106
|
+
dependencyRange,
|
107
|
+
parent: newGroup,
|
108
|
+
branch: newBranch,
|
109
|
+
visitedNodes,
|
110
|
+
cycles,
|
111
|
+
shouldDetectDevDependencies,
|
112
|
+
});
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
function getCycles(workspaceMeta, {
|
118
|
+
shouldDetectDevDependencies,
|
119
|
+
} = {}) {
|
120
|
+
let cycles = {};
|
121
|
+
let visitedNodes = {};
|
122
|
+
let { packages } = workspaceMeta;
|
123
|
+
|
124
|
+
for (let _package of Object.values(packages)) {
|
125
|
+
_getCycles({
|
126
|
+
packages,
|
127
|
+
_package,
|
128
|
+
branch: [],
|
129
|
+
visitedNodes,
|
130
|
+
cycles,
|
131
|
+
shouldDetectDevDependencies,
|
132
|
+
});
|
133
|
+
}
|
134
|
+
|
135
|
+
return Object.keys(cycles);
|
136
|
+
}
|
137
|
+
|
138
|
+
Object.assign(module.exports, {
|
139
|
+
getCycles,
|
140
|
+
});
|
@@ -0,0 +1,26 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const buildDepGraph = require('./build-dep-graph');
|
4
|
+
const { getCycles } = require('./cycle');
|
5
|
+
const {
|
6
|
+
getWorkspaceCwd,
|
7
|
+
} = require('./git');
|
8
|
+
|
9
|
+
const { builder } = require('../bin/commands/cycles');
|
10
|
+
|
11
|
+
async function detectCircularReferences({
|
12
|
+
cwd = process.cwd(),
|
13
|
+
shouldDetectDevDependencies = builder['detect-dev-dependencies'].default,
|
14
|
+
} = {}) {
|
15
|
+
let workspaceCwd = await getWorkspaceCwd(cwd);
|
16
|
+
|
17
|
+
let workspaceMeta = await buildDepGraph({ workspaceCwd });
|
18
|
+
|
19
|
+
let cycles = getCycles(workspaceMeta, {
|
20
|
+
shouldDetectDevDependencies,
|
21
|
+
});
|
22
|
+
|
23
|
+
return cycles;
|
24
|
+
}
|
25
|
+
|
26
|
+
module.exports = detectCircularReferences;
|