Skip to content

Commit 54de37e

Browse files
authored
improve bit-dependencies command to show the dependencies graph (textually) (teambit#3987)
It makes it easier to understand the relation between components.
1 parent 7b375e2 commit 54de37e

File tree

3 files changed

+78
-39
lines changed

3 files changed

+78
-39
lines changed
Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { BitId } from '@teambit/legacy-bit-id';
12
import { loadConsumerIfExist } from '../../../consumer';
23
import {
34
DependencyResolver,
@@ -6,17 +7,36 @@ import {
67
import type { DebugDependencies } from '../../../consumer/component/dependencies/dependency-resolver/dependencies-resolver';
78
import type { OverridesDependenciesData } from '../../../consumer/component/dependencies/dependency-resolver/dependencies-data';
89
import ConsumerNotFound from '../../../consumer/exceptions/consumer-not-found';
10+
import DependencyGraph, { DependenciesInfo } from '../../../scope/graph/scope-graph';
911

10-
export type DependenciesResults = DebugDependencies & OverridesDependenciesData & { coreAspects: string[] };
12+
export type DependenciesResultsDebug = DebugDependencies & OverridesDependenciesData & { coreAspects: string[] };
1113

12-
export async function dependencies(id: string): Promise<DependenciesResults> {
14+
export type DependenciesResults = {
15+
scopeDependencies: DependenciesInfo[];
16+
workspaceDependencies: DependenciesInfo[];
17+
id: BitId;
18+
};
19+
20+
export async function dependencies(
21+
id: string,
22+
debug: boolean
23+
): Promise<DependenciesResultsDebug | DependenciesResults> {
1324
const consumer = await loadConsumerIfExist();
1425
if (!consumer) throw new ConsumerNotFound(); // @todo: supports this on bare-scope.
1526
const bitId = consumer.getParsedId(id);
16-
const component = await consumer.loadComponent(bitId);
17-
const dependencyResolver = new DependencyResolver(component, consumer);
18-
const dependenciesData = await dependencyResolver.getDependenciesData({}, undefined);
19-
const debugData: DebugDependencies = dependencyResolver.debugDependenciesData;
20-
updateDependenciesVersions(consumer, component, debugData.components);
21-
return { ...debugData, ...dependenciesData.overridesDependencies, coreAspects: dependenciesData.coreAspects };
27+
if (debug) {
28+
const component = await consumer.loadComponent(bitId);
29+
const dependencyResolver = new DependencyResolver(component, consumer);
30+
const dependenciesData = await dependencyResolver.getDependenciesData({}, undefined);
31+
const debugData: DebugDependencies = dependencyResolver.debugDependenciesData;
32+
updateDependenciesVersions(consumer, component, debugData.components);
33+
return { ...debugData, ...dependenciesData.overridesDependencies, coreAspects: dependenciesData.coreAspects };
34+
}
35+
const scopeGraph = await DependencyGraph.buildGraphFromScope(consumer.scope);
36+
const scopeDependencyGraph = new DependencyGraph(scopeGraph);
37+
const scopeDependencies = scopeDependencyGraph.getDependenciesInfo(bitId);
38+
const workspaceGraph = await DependencyGraph.buildGraphFromWorkspace(consumer, true);
39+
const workspaceDependencyGraph = new DependencyGraph(workspaceGraph);
40+
const workspaceDependencies = workspaceDependencyGraph.getDependenciesInfo(bitId);
41+
return { scopeDependencies, workspaceDependencies, id: bitId };
2242
}
Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,42 @@
1-
import { dependencies } from '../../../api/consumer/lib/dependencies';
2-
import { DebugDependencies } from '../../../consumer/component/dependencies/dependency-resolver/dependencies-resolver';
1+
import chalk from 'chalk';
2+
import { dependencies, DependenciesResultsDebug, DependenciesResults } from '../../../api/consumer/lib/dependencies';
33
import { CommandOptions, LegacyCommand } from '../../legacy-command';
4+
import { generateDependenciesInfoTable } from '../../templates/component-template';
45

56
export default class Dependencies implements LegacyCommand {
67
name = 'dependencies <id>';
7-
description = 'EXPERIMENTAL. show dependencies of the given component and how their version was determined';
8+
description = 'EXPERIMENTAL. show dependencies (direct and indirect) of the given component';
89
alias = '';
9-
opts = [] as CommandOptions;
10+
opts = [['d', 'debug', 'show the immediate dependencies and how their version was determined']] as CommandOptions;
1011

11-
action([id]: [string]): Promise<any> {
12-
return dependencies(id);
12+
action([id]: [string], { debug = false }: { debug: boolean }): Promise<any> {
13+
return dependencies(id, debug);
1314
}
1415

15-
report(results: DebugDependencies): string {
16+
report(results: DependenciesResultsDebug | DependenciesResults): string {
17+
// @ts-ignore
18+
if (!results.id) {
19+
// it's DependenciesResultsDebug
20+
return this.debugReport(results as DependenciesResultsDebug);
21+
}
22+
return this.nonDebugReport(results as DependenciesResults);
23+
}
24+
25+
private debugReport(results: DependenciesResultsDebug) {
1626
return JSON.stringify(results, undefined, 4);
1727
}
28+
29+
private nonDebugReport(results: DependenciesResults) {
30+
if (!results.scopeDependencies.length && !results.workspaceDependencies.length) {
31+
return `no dependents found for ${results.id.toString()}.
32+
try running "bit cat-component ${results.id.toStringWithoutVersion()}" to see whether the component/version exists locally`;
33+
}
34+
const scopeTable = generateDependenciesInfoTable(results.scopeDependencies, results.id);
35+
const workspaceTable = generateDependenciesInfoTable(results.workspaceDependencies, results.id);
36+
return `${chalk.bold('Dependents originated from workspace')}
37+
${workspaceTable || '<none>'}
38+
39+
${chalk.bold('Dependents originated from scope')}
40+
${scopeTable || '<none>'}`;
41+
}
1842
}

src/cli/templates/component-template.ts

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export default function paintComponent(
7070
const componentTable = table(rows, tableColumnConfig);
7171
const dependenciesTableStr = showRemoteVersion ? generateDependenciesTable() : '';
7272
const dependentsInfoTableStr = generateDependentsInfoTable(dependentsInfo, component.id);
73-
const dependenciesInfoTableStr = generateDependenciesInfoTable();
73+
const dependenciesInfoTableStr = generateDependenciesInfoTable(dependenciesInfo, component.id);
7474
return (
7575
componentTable +
7676
dependenciesTableStr +
@@ -206,29 +206,6 @@ export default function paintComponent(
206206
return dependenciesTable;
207207
}
208208

209-
function generateDependenciesInfoTable() {
210-
if (!dependenciesInfo.length) {
211-
return '';
212-
}
213-
214-
const dependenciesHeader = [];
215-
dependenciesHeader.push([
216-
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
217-
c.cyan('Dependency ID'),
218-
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
219-
c.cyan('Depth'),
220-
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
221-
c.cyan('Immediate Dependent'),
222-
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
223-
c.cyan('Dependency type'),
224-
]);
225-
const allDependenciesRows = getAllDependenciesRows(dependenciesInfo, component.id);
226-
227-
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
228-
const dependenciesTable = table(dependenciesHeader.concat(allDependenciesRows));
229-
return `\n${c.bold('Dependencies Details')}\n${dependenciesTable}`;
230-
}
231-
232209
function calculatePadRightLength(str: string, columnWidth: number): string {
233210
if (!str) return '';
234211
const padRightCount = Math.ceil(str.length / columnWidth) * columnWidth;
@@ -247,6 +224,24 @@ function getAllDependenciesRows(dependenciesInfoArray: DependenciesInfo[], id: B
247224
});
248225
}
249226

227+
export function generateDependenciesInfoTable(dependenciesInfo: DependenciesInfo[], id: BitId) {
228+
if (!dependenciesInfo.length) {
229+
return '';
230+
}
231+
232+
const dependenciesHeader: string[][] = [];
233+
dependenciesHeader.push([
234+
c.cyan('Dependency ID'),
235+
c.cyan('Depth'),
236+
c.cyan('Immediate Dependent'),
237+
c.cyan('Dependency type'),
238+
]);
239+
const allDependenciesRows = getAllDependenciesRows(dependenciesInfo, id);
240+
241+
const dependenciesTable = table(dependenciesHeader.concat(allDependenciesRows));
242+
return `\n${c.bold('Dependencies Details')}\n${dependenciesTable}`;
243+
}
244+
250245
export function generateDependentsInfoTable(dependentsInfo: DependenciesInfo[], id: BitId) {
251246
if (!dependentsInfo.length) {
252247
return '';

0 commit comments

Comments
 (0)