monorepo-next 9.1.1 → 9.2.1

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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monorepo-next",
3
- "version": "9.1.1",
3
+ "version": "9.2.1",
4
4
  "description": "Detach monorepo packages from normal linking",
5
5
  "bin": {
6
6
  "next": "bin/next.js"
@@ -80,8 +80,8 @@
80
80
  "chai-as-promised": "^7.1.1",
81
81
  "common-tags": "^1.8.2",
82
82
  "eslint": "^8.0.0",
83
- "eslint-config-crowdstrike": "^9.0.0",
84
- "eslint-config-crowdstrike-node": "^3.0.0",
83
+ "eslint-config-crowdstrike": "10.1.0",
84
+ "eslint-config-crowdstrike-node": "3.0.1",
85
85
  "eslint-plugin-json-files": "^2.0.0",
86
86
  "eslint-plugin-mocha": "^10.0.0",
87
87
  "eslint-plugin-node": "^11.0.0",
@@ -95,6 +95,6 @@
95
95
  "sinon": "^15.0.0",
96
96
  "sinon-chai": "^3.5.0",
97
97
  "standard-node-template": "3.2.1",
98
- "yargs-help-output": "^2.0.0"
98
+ "yargs-help-output": "^3.0.0"
99
99
  }
100
100
  }
package/src/cycle.js ADDED
@@ -0,0 +1,145 @@
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
+ let dependencies = _package[dependencyType];
100
+
101
+ for (let packageName of Object.keys(dependencies).sort()) {
102
+ let dependencyRange = dependencies[packageName];
103
+ let _package = packages[packageName];
104
+
105
+ _getCycles({
106
+ packages,
107
+ _package,
108
+ dependencyType,
109
+ dependencyRange,
110
+ parent: newGroup,
111
+ branch: newBranch,
112
+ visitedNodes,
113
+ cycles,
114
+ shouldDetectDevDependencies,
115
+ });
116
+ }
117
+ }
118
+ }
119
+
120
+ function getCycles(workspaceMeta, {
121
+ shouldDetectDevDependencies,
122
+ } = {}) {
123
+ let cycles = {};
124
+ let visitedNodes = {};
125
+ let { packages } = workspaceMeta;
126
+
127
+ for (let packageName of Object.keys(packages).sort()) {
128
+ let _package = packages[packageName];
129
+
130
+ _getCycles({
131
+ packages,
132
+ _package,
133
+ branch: [],
134
+ visitedNodes,
135
+ cycles,
136
+ shouldDetectDevDependencies,
137
+ });
138
+ }
139
+
140
+ return Object.keys(cycles).sort();
141
+ }
142
+
143
+ Object.assign(module.exports, {
144
+ getCycles,
145
+ });
@@ -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;