@teambit/component-issues 0.0.170 → 0.0.172
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/circular-dependencies.ts +1 -1
- package/dist/circular-dependencies.js +1 -1
- package/dist/circular-dependencies.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/render-cycles.d.ts +5 -0
- package/dist/render-cycles.js +151 -0
- package/dist/render-cycles.js.map +1 -0
- package/index.ts +1 -0
- package/package.json +3 -3
- package/render-cycles.ts +153 -0
package/circular-dependencies.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ComponentIssue, formatTitle } from './component-issue';
|
|
|
2
2
|
|
|
3
3
|
export class CircularDependencies extends ComponentIssue {
|
|
4
4
|
description = 'circular dependencies';
|
|
5
|
-
solution = 'run `bit
|
|
5
|
+
solution = 'run `bit deps circular` to get the component-ids participating in the circular';
|
|
6
6
|
data: boolean;
|
|
7
7
|
isTagBlocker = true;
|
|
8
8
|
outputForCLI() {
|
|
@@ -13,7 +13,7 @@ function _componentIssue() {
|
|
|
13
13
|
}
|
|
14
14
|
class CircularDependencies extends _componentIssue().ComponentIssue {
|
|
15
15
|
description = 'circular dependencies';
|
|
16
|
-
solution = 'run `bit
|
|
16
|
+
solution = 'run `bit deps circular` to get the component-ids participating in the circular';
|
|
17
17
|
isTagBlocker = true;
|
|
18
18
|
outputForCLI() {
|
|
19
19
|
return (0, _componentIssue().formatTitle)(this.descriptionWithSolution, false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_componentIssue","data","require","CircularDependencies","ComponentIssue","description","solution","isTagBlocker","outputForCLI","formatTitle","descriptionWithSolution","exports"],"sources":["circular-dependencies.ts"],"sourcesContent":["import { ComponentIssue, formatTitle } from './component-issue';\n\nexport class CircularDependencies extends ComponentIssue {\n description = 'circular dependencies';\n solution = 'run `bit
|
|
1
|
+
{"version":3,"names":["_componentIssue","data","require","CircularDependencies","ComponentIssue","description","solution","isTagBlocker","outputForCLI","formatTitle","descriptionWithSolution","exports"],"sources":["circular-dependencies.ts"],"sourcesContent":["import { ComponentIssue, formatTitle } from './component-issue';\n\nexport class CircularDependencies extends ComponentIssue {\n description = 'circular dependencies';\n solution = 'run `bit deps circular` to get the component-ids participating in the circular';\n data: boolean;\n isTagBlocker = true;\n outputForCLI() {\n return formatTitle(this.descriptionWithSolution, false);\n }\n}\n"],"mappings":";;;;;;AAAA,SAAAA,gBAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,eAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEO,MAAME,oBAAoB,SAASC,gCAAc,CAAC;EACvDC,WAAW,GAAG,uBAAuB;EACrCC,QAAQ,GAAG,gFAAgF;EAE3FC,YAAY,GAAG,IAAI;EACnBC,YAAYA,CAAA,EAAG;IACb,OAAO,IAAAC,6BAAW,EAAC,IAAI,CAACC,uBAAuB,EAAE,KAAK,CAAC;EACzD;AACF;AAACC,OAAA,CAAAR,oBAAA,GAAAA,oBAAA","ignoreList":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export { ISSUE_FORMAT_SPACE as MISSING_DEPS_SPACE, ComponentIssue } from './comp
|
|
|
3
3
|
export { UntrackedFileDependencyEntry, MISSING_NESTED_DEPS_SPACE } from './untracked-dependencies';
|
|
4
4
|
export { RelativeComponentsAuthoredEntry } from './relative-components-authored';
|
|
5
5
|
export type { MissingPackagesData } from './missing-packages-dependencies-on-fs';
|
|
6
|
+
export { renderCycles } from './render-cycles';
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,12 @@ Object.defineProperty(exports, "UntrackedFileDependencyEntry", {
|
|
|
51
51
|
return _untrackedDependencies().UntrackedFileDependencyEntry;
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
|
+
Object.defineProperty(exports, "renderCycles", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _renderCycles().renderCycles;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
54
60
|
function _issuesList() {
|
|
55
61
|
const data = require("./issues-list");
|
|
56
62
|
_issuesList = function () {
|
|
@@ -79,5 +85,12 @@ function _relativeComponentsAuthored() {
|
|
|
79
85
|
};
|
|
80
86
|
return data;
|
|
81
87
|
}
|
|
88
|
+
function _renderCycles() {
|
|
89
|
+
const data = require("./render-cycles");
|
|
90
|
+
_renderCycles = function () {
|
|
91
|
+
return data;
|
|
92
|
+
};
|
|
93
|
+
return data;
|
|
94
|
+
}
|
|
82
95
|
|
|
83
96
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_issuesList","data","require","_componentIssue","_untrackedDependencies","_relativeComponentsAuthored"],"sources":["index.ts"],"sourcesContent":["export { IssuesList, IssuesClasses, IssuesNames } from './issues-list';\nexport { ISSUE_FORMAT_SPACE as MISSING_DEPS_SPACE, ComponentIssue } from './component-issue';\nexport { UntrackedFileDependencyEntry, MISSING_NESTED_DEPS_SPACE } from './untracked-dependencies';\nexport { RelativeComponentsAuthoredEntry } from './relative-components-authored';\nexport type { MissingPackagesData } from './missing-packages-dependencies-on-fs';\n"],"mappings":"
|
|
1
|
+
{"version":3,"names":["_issuesList","data","require","_componentIssue","_untrackedDependencies","_relativeComponentsAuthored","_renderCycles"],"sources":["index.ts"],"sourcesContent":["export { IssuesList, IssuesClasses, IssuesNames } from './issues-list';\nexport { ISSUE_FORMAT_SPACE as MISSING_DEPS_SPACE, ComponentIssue } from './component-issue';\nexport { UntrackedFileDependencyEntry, MISSING_NESTED_DEPS_SPACE } from './untracked-dependencies';\nexport { RelativeComponentsAuthoredEntry } from './relative-components-authored';\nexport type { MissingPackagesData } from './missing-packages-dependencies-on-fs';\nexport { renderCycles } from './render-cycles';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAAA,YAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,WAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAE,gBAAA;EAAA,MAAAF,IAAA,GAAAC,OAAA;EAAAC,eAAA,YAAAA,CAAA;IAAA,OAAAF,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAG,uBAAA;EAAA,MAAAH,IAAA,GAAAC,OAAA;EAAAE,sBAAA,YAAAA,CAAA;IAAA,OAAAH,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAI,4BAAA;EAAA,MAAAJ,IAAA,GAAAC,OAAA;EAAAG,2BAAA,YAAAA,CAAA;IAAA,OAAAJ,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA,SAAAK,cAAA;EAAA,MAAAL,IAAA,GAAAC,OAAA;EAAAI,aAAA,YAAAA,CAAA;IAAA,OAAAL,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA","ignoreList":[]}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.renderCycles = renderCycles;
|
|
7
|
+
function _chalk() {
|
|
8
|
+
const data = _interopRequireDefault(require("chalk"));
|
|
9
|
+
_chalk = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
+
const MAX_HORIZONTAL_WIDTH = 90;
|
|
16
|
+
const ARROW = ' ───> ';
|
|
17
|
+
const ARROW_LEN = 8;
|
|
18
|
+
function shortenNames(cycle) {
|
|
19
|
+
// cycle has the first element duplicated at the end; work with unique entries
|
|
20
|
+
const unique = cycle.slice(0, -1);
|
|
21
|
+
|
|
22
|
+
// extract scope: everything up to and including the last '/' before the component name
|
|
23
|
+
// e.g. "my-org.scope/ui/button@0.0.1" → scope "my-org.scope/ui", name "button", ver "0.0.1"
|
|
24
|
+
const parsed = unique.map(id => {
|
|
25
|
+
const atIdx = id.lastIndexOf('@');
|
|
26
|
+
const version = atIdx > 0 ? id.slice(atIdx + 1) : undefined;
|
|
27
|
+
const withoutVer = atIdx > 0 ? id.slice(0, atIdx) : id;
|
|
28
|
+
const slashIdx = withoutVer.lastIndexOf('/');
|
|
29
|
+
const scope = slashIdx > 0 ? withoutVer.slice(0, slashIdx) : undefined;
|
|
30
|
+
const name = slashIdx > 0 ? withoutVer.slice(slashIdx + 1) : withoutVer;
|
|
31
|
+
return {
|
|
32
|
+
scope,
|
|
33
|
+
name,
|
|
34
|
+
version
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// common scope: only if ALL entries share the same scope
|
|
39
|
+
const scopes = new Set(parsed.map(p => p.scope));
|
|
40
|
+
const commonScope = scopes.size === 1 ? parsed[0].scope : undefined;
|
|
41
|
+
|
|
42
|
+
// common version: only if ALL entries share the same version
|
|
43
|
+
const versions = new Set(parsed.map(p => p.version));
|
|
44
|
+
const commonVersion = versions.size === 1 ? parsed[0].version : undefined;
|
|
45
|
+
const names = parsed.map(p => {
|
|
46
|
+
let display = commonScope ? p.name : p.scope ? `${p.scope}/${p.name}` : p.name;
|
|
47
|
+
if (!commonVersion && p.version) {
|
|
48
|
+
display += `@${p.version}`;
|
|
49
|
+
}
|
|
50
|
+
return display;
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
names,
|
|
54
|
+
scope: commonScope,
|
|
55
|
+
version: commonVersion
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function renderHeader(cycleIndex, totalCycles, componentCount, scope, version) {
|
|
59
|
+
const isSelf = componentCount === 1;
|
|
60
|
+
let header = '';
|
|
61
|
+
if (totalCycles > 1 && cycleIndex !== undefined) {
|
|
62
|
+
header += `Cycle ${cycleIndex + 1} of ${totalCycles}`;
|
|
63
|
+
} else {
|
|
64
|
+
header += 'Cycle';
|
|
65
|
+
}
|
|
66
|
+
header += isSelf ? ' - self-dependency' : ` - ${componentCount} components`;
|
|
67
|
+
if (scope) header += ` (scope: ${scope})`;
|
|
68
|
+
if (version) header += ` @${version}`;
|
|
69
|
+
return _chalk().default.bold(header);
|
|
70
|
+
}
|
|
71
|
+
function renderSelfCycle(name) {
|
|
72
|
+
return ` ${_chalk().default.cyan(name)} ⟲`;
|
|
73
|
+
}
|
|
74
|
+
function renderHorizontal(names) {
|
|
75
|
+
// build chain: name0 ───> name1 ───> name2
|
|
76
|
+
const chainParts = [];
|
|
77
|
+
const plainParts = [];
|
|
78
|
+
for (let i = 0; i < names.length; i++) {
|
|
79
|
+
chainParts.push(_chalk().default.cyan(names[i]));
|
|
80
|
+
plainParts.push(names[i]);
|
|
81
|
+
if (i < names.length - 1) {
|
|
82
|
+
chainParts.push(_chalk().default.dim(ARROW));
|
|
83
|
+
plainParts.push(ARROW);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const chainStr = chainParts.join('');
|
|
87
|
+
const plainLen = plainParts.join('').length;
|
|
88
|
+
|
|
89
|
+
// the last segment connects to the closing edge: ───┘
|
|
90
|
+
const closingSuffix = _chalk().default.red(' ───┘');
|
|
91
|
+
const closingSuffixLen = 6; // " ───┘"
|
|
92
|
+
|
|
93
|
+
const totalWidth = plainLen + closingSuffixLen;
|
|
94
|
+
|
|
95
|
+
// top bar spans from above ▼ (column 0) to the ┐ (at totalWidth - 1)
|
|
96
|
+
const topBar = _chalk().default.red('┌') + _chalk().default.red('─'.repeat(totalWidth - 2)) + _chalk().default.red('┐');
|
|
97
|
+
const sideLine = ' '.repeat(totalWidth - 1) + _chalk().default.red('│');
|
|
98
|
+
const entryArrow = _chalk().default.red('▼') + ' '.repeat(totalWidth - 2) + _chalk().default.red('│');
|
|
99
|
+
const lines = [topBar, sideLine, entryArrow, chainStr + closingSuffix];
|
|
100
|
+
return lines.join('\n');
|
|
101
|
+
}
|
|
102
|
+
function renderVertical(names) {
|
|
103
|
+
const lines = [];
|
|
104
|
+
for (let i = 0; i < names.length; i++) {
|
|
105
|
+
lines.push(_chalk().default.cyan(names[i]));
|
|
106
|
+
if (i < names.length - 1) {
|
|
107
|
+
lines.push(_chalk().default.dim(' │'));
|
|
108
|
+
lines.push(_chalk().default.dim(' ▼'));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// back-edge to start
|
|
112
|
+
lines.push(_chalk().default.red(` ╰───▶ `) + _chalk().default.cyan(names[0]) + _chalk().default.dim(' (back to start)'));
|
|
113
|
+
return lines.join('\n');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Render an array of cycles (each cycle is an array of component-id strings with the
|
|
118
|
+
* first element duplicated at the end) into a human-readable string with ASCII diagrams.
|
|
119
|
+
*/
|
|
120
|
+
function renderCycles(cycles) {
|
|
121
|
+
if (!cycles.length) {
|
|
122
|
+
return 'No circular dependencies found';
|
|
123
|
+
}
|
|
124
|
+
const totalCycles = cycles.length;
|
|
125
|
+
const blocks = cycles.map((cycle, idx) => {
|
|
126
|
+
const componentCount = cycle.length - 1; // last entry is duplicate of first
|
|
127
|
+
const {
|
|
128
|
+
names,
|
|
129
|
+
scope,
|
|
130
|
+
version
|
|
131
|
+
} = shortenNames(cycle);
|
|
132
|
+
const cycleIndex = totalCycles > 1 ? idx : undefined;
|
|
133
|
+
const header = renderHeader(cycleIndex, totalCycles, componentCount, scope, version);
|
|
134
|
+
let body;
|
|
135
|
+
if (componentCount === 1) {
|
|
136
|
+
body = renderSelfCycle(names[0]);
|
|
137
|
+
} else {
|
|
138
|
+
const chainPlainLen = names.reduce((sum, n) => sum + n.length, 0) + (names.length - 1) * ARROW_LEN;
|
|
139
|
+
const horizontalWidth = chainPlainLen + 6; // + closing " ───┘"
|
|
140
|
+
if (horizontalWidth <= MAX_HORIZONTAL_WIDTH) {
|
|
141
|
+
body = renderHorizontal(names);
|
|
142
|
+
} else {
|
|
143
|
+
body = renderVertical(names);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return `${header}\n\n${body}`;
|
|
147
|
+
});
|
|
148
|
+
return '\n' + blocks.join('\n\n') + '\n';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
//# sourceMappingURL=render-cycles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_chalk","data","_interopRequireDefault","require","e","__esModule","default","MAX_HORIZONTAL_WIDTH","ARROW","ARROW_LEN","shortenNames","cycle","unique","slice","parsed","map","id","atIdx","lastIndexOf","version","undefined","withoutVer","slashIdx","scope","name","scopes","Set","p","commonScope","size","versions","commonVersion","names","display","renderHeader","cycleIndex","totalCycles","componentCount","isSelf","header","chalk","bold","renderSelfCycle","cyan","renderHorizontal","chainParts","plainParts","i","length","push","dim","chainStr","join","plainLen","closingSuffix","red","closingSuffixLen","totalWidth","topBar","repeat","sideLine","entryArrow","lines","renderVertical","renderCycles","cycles","blocks","idx","body","chainPlainLen","reduce","sum","n","horizontalWidth"],"sources":["render-cycles.ts"],"sourcesContent":["import chalk from 'chalk';\n\nconst MAX_HORIZONTAL_WIDTH = 90;\nconst ARROW = ' ───> ';\nconst ARROW_LEN = 8;\n\ntype ShortenedInfo = {\n names: string[];\n scope: string | undefined;\n version: string | undefined;\n};\n\nfunction shortenNames(cycle: string[]): ShortenedInfo {\n // cycle has the first element duplicated at the end; work with unique entries\n const unique = cycle.slice(0, -1);\n\n // extract scope: everything up to and including the last '/' before the component name\n // e.g. \"my-org.scope/ui/button@0.0.1\" → scope \"my-org.scope/ui\", name \"button\", ver \"0.0.1\"\n const parsed = unique.map((id) => {\n const atIdx = id.lastIndexOf('@');\n const version = atIdx > 0 ? id.slice(atIdx + 1) : undefined;\n const withoutVer = atIdx > 0 ? id.slice(0, atIdx) : id;\n const slashIdx = withoutVer.lastIndexOf('/');\n const scope = slashIdx > 0 ? withoutVer.slice(0, slashIdx) : undefined;\n const name = slashIdx > 0 ? withoutVer.slice(slashIdx + 1) : withoutVer;\n return { scope, name, version };\n });\n\n // common scope: only if ALL entries share the same scope\n const scopes = new Set(parsed.map((p) => p.scope));\n const commonScope = scopes.size === 1 ? parsed[0].scope : undefined;\n\n // common version: only if ALL entries share the same version\n const versions = new Set(parsed.map((p) => p.version));\n const commonVersion = versions.size === 1 ? parsed[0].version : undefined;\n\n const names = parsed.map((p) => {\n let display = commonScope ? p.name : p.scope ? `${p.scope}/${p.name}` : p.name;\n if (!commonVersion && p.version) {\n display += `@${p.version}`;\n }\n return display;\n });\n\n return { names, scope: commonScope, version: commonVersion };\n}\n\nfunction renderHeader(\n cycleIndex: number | undefined,\n totalCycles: number,\n componentCount: number,\n scope: string | undefined,\n version: string | undefined\n): string {\n const isSelf = componentCount === 1;\n let header = '';\n\n if (totalCycles > 1 && cycleIndex !== undefined) {\n header += `Cycle ${cycleIndex + 1} of ${totalCycles}`;\n } else {\n header += 'Cycle';\n }\n\n header += isSelf ? ' - self-dependency' : ` - ${componentCount} components`;\n\n if (scope) header += ` (scope: ${scope})`;\n if (version) header += ` @${version}`;\n\n return chalk.bold(header);\n}\n\nfunction renderSelfCycle(name: string): string {\n return ` ${chalk.cyan(name)} ⟲`;\n}\n\nfunction renderHorizontal(names: string[]): string {\n // build chain: name0 ───> name1 ───> name2\n const chainParts: string[] = [];\n const plainParts: string[] = [];\n for (let i = 0; i < names.length; i++) {\n chainParts.push(chalk.cyan(names[i]));\n plainParts.push(names[i]);\n if (i < names.length - 1) {\n chainParts.push(chalk.dim(ARROW));\n plainParts.push(ARROW);\n }\n }\n\n const chainStr = chainParts.join('');\n const plainLen = plainParts.join('').length;\n\n // the last segment connects to the closing edge: ───┘\n const closingSuffix = chalk.red(' ───┘');\n const closingSuffixLen = 6; // \" ───┘\"\n\n const totalWidth = plainLen + closingSuffixLen;\n\n // top bar spans from above ▼ (column 0) to the ┐ (at totalWidth - 1)\n const topBar = chalk.red('┌') + chalk.red('─'.repeat(totalWidth - 2)) + chalk.red('┐');\n const sideLine = ' '.repeat(totalWidth - 1) + chalk.red('│');\n const entryArrow = chalk.red('▼') + ' '.repeat(totalWidth - 2) + chalk.red('│');\n\n const lines = [topBar, sideLine, entryArrow, chainStr + closingSuffix];\n return lines.join('\\n');\n}\n\nfunction renderVertical(names: string[]): string {\n const lines: string[] = [];\n for (let i = 0; i < names.length; i++) {\n lines.push(chalk.cyan(names[i]));\n if (i < names.length - 1) {\n lines.push(chalk.dim(' │'));\n lines.push(chalk.dim(' ▼'));\n }\n }\n // back-edge to start\n lines.push(chalk.red(` ╰───▶ `) + chalk.cyan(names[0]) + chalk.dim(' (back to start)'));\n return lines.join('\\n');\n}\n\n/**\n * Render an array of cycles (each cycle is an array of component-id strings with the\n * first element duplicated at the end) into a human-readable string with ASCII diagrams.\n */\nexport function renderCycles(cycles: string[][]): string {\n if (!cycles.length) {\n return 'No circular dependencies found';\n }\n const totalCycles = cycles.length;\n const blocks = cycles.map((cycle, idx) => {\n const componentCount = cycle.length - 1; // last entry is duplicate of first\n const { names, scope, version } = shortenNames(cycle);\n const cycleIndex = totalCycles > 1 ? idx : undefined;\n const header = renderHeader(cycleIndex, totalCycles, componentCount, scope, version);\n\n let body: string;\n if (componentCount === 1) {\n body = renderSelfCycle(names[0]);\n } else {\n const chainPlainLen = names.reduce((sum, n) => sum + n.length, 0) + (names.length - 1) * ARROW_LEN;\n const horizontalWidth = chainPlainLen + 6; // + closing \" ───┘\"\n if (horizontalWidth <= MAX_HORIZONTAL_WIDTH) {\n body = renderHorizontal(names);\n } else {\n body = renderVertical(names);\n }\n }\n\n return `${header}\\n\\n${body}`;\n });\n\n return '\\n' + blocks.join('\\n\\n') + '\\n';\n}\n"],"mappings":"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","ignoreList":[]}
|
package/index.ts
CHANGED
|
@@ -3,3 +3,4 @@ export { ISSUE_FORMAT_SPACE as MISSING_DEPS_SPACE, ComponentIssue } from './comp
|
|
|
3
3
|
export { UntrackedFileDependencyEntry, MISSING_NESTED_DEPS_SPACE } from './untracked-dependencies';
|
|
4
4
|
export { RelativeComponentsAuthoredEntry } from './relative-components-authored';
|
|
5
5
|
export type { MissingPackagesData } from './missing-packages-dependencies-on-fs';
|
|
6
|
+
export { renderCycles } from './render-cycles';
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teambit/component-issues",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.172",
|
|
4
4
|
"homepage": "https://bit.cloud/teambit/component/component-issues",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"componentId": {
|
|
7
7
|
"scope": "teambit.component",
|
|
8
8
|
"name": "component-issues",
|
|
9
|
-
"version": "0.0.
|
|
9
|
+
"version": "0.0.172"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"chalk": "4.1.2",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@types/mocha": "9.1.0",
|
|
17
17
|
"chai": "5.2.1",
|
|
18
|
-
"@teambit/node.envs.node-babel-mocha": "0.2.
|
|
18
|
+
"@teambit/node.envs.node-babel-mocha": "0.2.9"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {},
|
|
21
21
|
"license": "Apache-2.0",
|
package/render-cycles.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
const MAX_HORIZONTAL_WIDTH = 90;
|
|
4
|
+
const ARROW = ' ───> ';
|
|
5
|
+
const ARROW_LEN = 8;
|
|
6
|
+
|
|
7
|
+
type ShortenedInfo = {
|
|
8
|
+
names: string[];
|
|
9
|
+
scope: string | undefined;
|
|
10
|
+
version: string | undefined;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function shortenNames(cycle: string[]): ShortenedInfo {
|
|
14
|
+
// cycle has the first element duplicated at the end; work with unique entries
|
|
15
|
+
const unique = cycle.slice(0, -1);
|
|
16
|
+
|
|
17
|
+
// extract scope: everything up to and including the last '/' before the component name
|
|
18
|
+
// e.g. "my-org.scope/ui/button@0.0.1" → scope "my-org.scope/ui", name "button", ver "0.0.1"
|
|
19
|
+
const parsed = unique.map((id) => {
|
|
20
|
+
const atIdx = id.lastIndexOf('@');
|
|
21
|
+
const version = atIdx > 0 ? id.slice(atIdx + 1) : undefined;
|
|
22
|
+
const withoutVer = atIdx > 0 ? id.slice(0, atIdx) : id;
|
|
23
|
+
const slashIdx = withoutVer.lastIndexOf('/');
|
|
24
|
+
const scope = slashIdx > 0 ? withoutVer.slice(0, slashIdx) : undefined;
|
|
25
|
+
const name = slashIdx > 0 ? withoutVer.slice(slashIdx + 1) : withoutVer;
|
|
26
|
+
return { scope, name, version };
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// common scope: only if ALL entries share the same scope
|
|
30
|
+
const scopes = new Set(parsed.map((p) => p.scope));
|
|
31
|
+
const commonScope = scopes.size === 1 ? parsed[0].scope : undefined;
|
|
32
|
+
|
|
33
|
+
// common version: only if ALL entries share the same version
|
|
34
|
+
const versions = new Set(parsed.map((p) => p.version));
|
|
35
|
+
const commonVersion = versions.size === 1 ? parsed[0].version : undefined;
|
|
36
|
+
|
|
37
|
+
const names = parsed.map((p) => {
|
|
38
|
+
let display = commonScope ? p.name : p.scope ? `${p.scope}/${p.name}` : p.name;
|
|
39
|
+
if (!commonVersion && p.version) {
|
|
40
|
+
display += `@${p.version}`;
|
|
41
|
+
}
|
|
42
|
+
return display;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return { names, scope: commonScope, version: commonVersion };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function renderHeader(
|
|
49
|
+
cycleIndex: number | undefined,
|
|
50
|
+
totalCycles: number,
|
|
51
|
+
componentCount: number,
|
|
52
|
+
scope: string | undefined,
|
|
53
|
+
version: string | undefined
|
|
54
|
+
): string {
|
|
55
|
+
const isSelf = componentCount === 1;
|
|
56
|
+
let header = '';
|
|
57
|
+
|
|
58
|
+
if (totalCycles > 1 && cycleIndex !== undefined) {
|
|
59
|
+
header += `Cycle ${cycleIndex + 1} of ${totalCycles}`;
|
|
60
|
+
} else {
|
|
61
|
+
header += 'Cycle';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
header += isSelf ? ' - self-dependency' : ` - ${componentCount} components`;
|
|
65
|
+
|
|
66
|
+
if (scope) header += ` (scope: ${scope})`;
|
|
67
|
+
if (version) header += ` @${version}`;
|
|
68
|
+
|
|
69
|
+
return chalk.bold(header);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function renderSelfCycle(name: string): string {
|
|
73
|
+
return ` ${chalk.cyan(name)} ⟲`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function renderHorizontal(names: string[]): string {
|
|
77
|
+
// build chain: name0 ───> name1 ───> name2
|
|
78
|
+
const chainParts: string[] = [];
|
|
79
|
+
const plainParts: string[] = [];
|
|
80
|
+
for (let i = 0; i < names.length; i++) {
|
|
81
|
+
chainParts.push(chalk.cyan(names[i]));
|
|
82
|
+
plainParts.push(names[i]);
|
|
83
|
+
if (i < names.length - 1) {
|
|
84
|
+
chainParts.push(chalk.dim(ARROW));
|
|
85
|
+
plainParts.push(ARROW);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const chainStr = chainParts.join('');
|
|
90
|
+
const plainLen = plainParts.join('').length;
|
|
91
|
+
|
|
92
|
+
// the last segment connects to the closing edge: ───┘
|
|
93
|
+
const closingSuffix = chalk.red(' ───┘');
|
|
94
|
+
const closingSuffixLen = 6; // " ───┘"
|
|
95
|
+
|
|
96
|
+
const totalWidth = plainLen + closingSuffixLen;
|
|
97
|
+
|
|
98
|
+
// top bar spans from above ▼ (column 0) to the ┐ (at totalWidth - 1)
|
|
99
|
+
const topBar = chalk.red('┌') + chalk.red('─'.repeat(totalWidth - 2)) + chalk.red('┐');
|
|
100
|
+
const sideLine = ' '.repeat(totalWidth - 1) + chalk.red('│');
|
|
101
|
+
const entryArrow = chalk.red('▼') + ' '.repeat(totalWidth - 2) + chalk.red('│');
|
|
102
|
+
|
|
103
|
+
const lines = [topBar, sideLine, entryArrow, chainStr + closingSuffix];
|
|
104
|
+
return lines.join('\n');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function renderVertical(names: string[]): string {
|
|
108
|
+
const lines: string[] = [];
|
|
109
|
+
for (let i = 0; i < names.length; i++) {
|
|
110
|
+
lines.push(chalk.cyan(names[i]));
|
|
111
|
+
if (i < names.length - 1) {
|
|
112
|
+
lines.push(chalk.dim(' │'));
|
|
113
|
+
lines.push(chalk.dim(' ▼'));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// back-edge to start
|
|
117
|
+
lines.push(chalk.red(` ╰───▶ `) + chalk.cyan(names[0]) + chalk.dim(' (back to start)'));
|
|
118
|
+
return lines.join('\n');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Render an array of cycles (each cycle is an array of component-id strings with the
|
|
123
|
+
* first element duplicated at the end) into a human-readable string with ASCII diagrams.
|
|
124
|
+
*/
|
|
125
|
+
export function renderCycles(cycles: string[][]): string {
|
|
126
|
+
if (!cycles.length) {
|
|
127
|
+
return 'No circular dependencies found';
|
|
128
|
+
}
|
|
129
|
+
const totalCycles = cycles.length;
|
|
130
|
+
const blocks = cycles.map((cycle, idx) => {
|
|
131
|
+
const componentCount = cycle.length - 1; // last entry is duplicate of first
|
|
132
|
+
const { names, scope, version } = shortenNames(cycle);
|
|
133
|
+
const cycleIndex = totalCycles > 1 ? idx : undefined;
|
|
134
|
+
const header = renderHeader(cycleIndex, totalCycles, componentCount, scope, version);
|
|
135
|
+
|
|
136
|
+
let body: string;
|
|
137
|
+
if (componentCount === 1) {
|
|
138
|
+
body = renderSelfCycle(names[0]);
|
|
139
|
+
} else {
|
|
140
|
+
const chainPlainLen = names.reduce((sum, n) => sum + n.length, 0) + (names.length - 1) * ARROW_LEN;
|
|
141
|
+
const horizontalWidth = chainPlainLen + 6; // + closing " ───┘"
|
|
142
|
+
if (horizontalWidth <= MAX_HORIZONTAL_WIDTH) {
|
|
143
|
+
body = renderHorizontal(names);
|
|
144
|
+
} else {
|
|
145
|
+
body = renderVertical(names);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return `${header}\n\n${body}`;
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return '\n' + blocks.join('\n\n') + '\n';
|
|
153
|
+
}
|