Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 44 additions & 49 deletions packages/angular/cli/src/commands/version/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation } from '../../command-builder/command-module';
import { colors } from '../../utilities/color';
import { RootCommands } from '../command-config';
import { VersionInfo, gatherVersionInfo } from './version-info';
import { gatherVersionInfo } from './version-info';

/**
* The Angular CLI logo, displayed as ASCII art.
Expand Down Expand Up @@ -65,17 +65,31 @@ export default class VersionCommandModule
versions,
} = versionInfo;

const header = `
Angular CLI: ${ngCliVersion}
Node: ${nodeVersion}${unsupportedNodeVersion ? ' (Unsupported)' : ''}
Package Manager: ${packageManagerName} ${packageManagerVersion ?? '<error>'}
OS: ${os} ${arch}
`.replace(/^ {6}/gm, '');
const headerInfo = [
{ label: 'Angular CLI', value: ngCliVersion },
{
label: 'Node.js',
value: `${nodeVersion}${unsupportedNodeVersion ? colors.yellow(' (Unsupported)') : ''}`,
},
{
label: 'Package Manager',
value: `${packageManagerName} ${packageManagerVersion ?? '<error>'}`,
},
{ label: 'Operating System', value: `${os} ${arch}` },
];

const maxHeaderLabelLength = Math.max(...headerInfo.map((l) => l.label.length));

const header = headerInfo
.map(
({ label, value }) =>
colors.bold(label.padEnd(maxHeaderLabelLength + 2)) + `: ${colors.cyan(value)}`,
)
.join('\n');

const angularPackages = this.formatAngularPackages(versionInfo);
const packageTable = this.formatPackageTable(versions);

logger.info([ASCII_ART, header, angularPackages, packageTable].join('\n\n'));
logger.info([ASCII_ART, header, packageTable].join('\n\n'));

if (unsupportedNodeVersion) {
logger.warn(
Expand All @@ -84,36 +98,6 @@ export default class VersionCommandModule
}
}

/**
* Formats the Angular packages section of the version output.
* @param versionInfo An object containing the version information.
* @returns A string containing the formatted Angular packages information.
*/
private formatAngularPackages(versionInfo: VersionInfo): string {
const { angularCoreVersion, angularSameAsCore } = versionInfo;
if (!angularCoreVersion) {
return 'Angular: <error>';
}

const wrappedPackages = angularSameAsCore
.reduce<string[]>((acc, name) => {
if (acc.length === 0) {
return [name];
}
const line = acc[acc.length - 1] + ', ' + name;
if (line.length > 60) {
acc.push(name);
} else {
acc[acc.length - 1] = line;
}

return acc;
}, [])
.join('\n... ');

return `Angular: ${angularCoreVersion}\n... ${wrappedPackages}`;
}

/**
* Formats the package table section of the version output.
* @param versions A map of package names to their versions.
Expand All @@ -125,22 +109,33 @@ export default class VersionCommandModule
return '';
}

const header = 'Package';
const maxNameLength = Math.max(...versionKeys.map((key) => key.length));
const namePad = ' '.repeat(Math.max(0, maxNameLength - header.length) + 3);
const nameHeader = 'Package';
const versionHeader = 'Version';

const tableHeader = `${header}${namePad}Version`;
const separator = '-'.repeat(tableHeader.length);
const maxNameLength = Math.max(nameHeader.length, ...versionKeys.map((key) => key.length));
const maxVersionLength = Math.max(
versionHeader.length,
...versionKeys.map((key) => versions[key].length),
);

const tableRows = versionKeys
.map((module) => {
const padding = ' '.repeat(maxNameLength - module.length + 3);
const name = module.padEnd(maxNameLength);
const version = versions[module];
const coloredVersion = version === '<error>' ? colors.red(version) : colors.cyan(version);
const padding = ' '.repeat(maxVersionLength - version.length);

return `${module}${padding}${versions[module]}`;
return `│ ${name} │ ${coloredVersion}${padding} │`;
})
.sort()
.join('\n');
.sort();

const top = `┌─${'─'.repeat(maxNameLength)}─┬─${'─'.repeat(maxVersionLength)}─┐`;
const header = `│ ${nameHeader.padEnd(maxNameLength)} │ ${versionHeader.padEnd(
maxVersionLength,
)} │`;
const separator = `├─${'─'.repeat(maxNameLength)}─┼─${'─'.repeat(maxVersionLength)}─┤`;
const bottom = `└─${'─'.repeat(maxNameLength)}─┴─${'─'.repeat(maxVersionLength)}─┘`;

return `${tableHeader}\n${separator}\n${tableRows}`;
return [top, header, separator, ...tableRows, bottom].join('\n');
}
}
26 changes: 1 addition & 25 deletions packages/angular/cli/src/commands/version/version-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ interface PartialPackageInfo {
*/
export interface VersionInfo {
ngCliVersion: string;
angularCoreVersion: string;
angularSameAsCore: string[];
versions: Record<string, string>;
unsupportedNodeVersion: boolean;
nodeVersion: string;
Expand Down Expand Up @@ -90,30 +88,8 @@ export function gatherVersionInfo(context: {
}
}

const ngCliVersion = VERSION.full;
let angularCoreVersion = '';
const angularSameAsCore: string[] = [];

if (workspacePackage) {
// Filter all angular versions that are the same as core.
angularCoreVersion = versions['@angular/core'];
if (angularCoreVersion) {
for (const [name, version] of Object.entries(versions)) {
if (version === angularCoreVersion && name.startsWith('@angular/')) {
angularSameAsCore.push(name.replace(/^@angular\//, ''));
delete versions[name];
}
}

// Make sure we list them in alphabetical order.
angularSameAsCore.sort();
}
}

return {
ngCliVersion,
angularCoreVersion,
angularSameAsCore,
ngCliVersion: VERSION.full,
versions,
unsupportedNodeVersion,
nodeVersion: process.versions.node,
Expand Down