in packages/angular/cli/src/commands/update/schematic/index.ts [413:529]
function _usageMessage(
options: UpdateSchema,
infoMap: Map<string, PackageInfo>,
logger: logging.LoggerApi,
) {
const packageGroups = new Map<string, string>();
const packagesToUpdate = [...infoMap.entries()]
.map(([name, info]) => {
let tag = options.next
? info.npmPackageJson['dist-tags']['next']
? 'next'
: 'latest'
: 'latest';
let version = info.npmPackageJson['dist-tags'][tag];
let target = info.npmPackageJson.versions[version];
const versionDiff = semver.diff(info.installed.version, version);
if (
versionDiff !== 'patch' &&
versionDiff !== 'minor' &&
/^@(?:angular|nguniversal)\//.test(name)
) {
const installedMajorVersion = semver.parse(info.installed.version)?.major;
const toInstallMajorVersion = semver.parse(version)?.major;
if (
installedMajorVersion !== undefined &&
toInstallMajorVersion !== undefined &&
installedMajorVersion < toInstallMajorVersion - 1
) {
const nextMajorVersion = `${installedMajorVersion + 1}.`;
const nextMajorVersions = Object.keys(info.npmPackageJson.versions)
.filter((v) => v.startsWith(nextMajorVersion))
.sort((a, b) => (a > b ? -1 : 1));
if (nextMajorVersions.length) {
version = nextMajorVersions[0];
target = info.npmPackageJson.versions[version];
tag = '';
}
}
}
return {
name,
info,
version,
tag,
target,
};
})
.filter(
({ info, version, target }) =>
target?.['ng-update'] && semver.compare(info.installed.version, version) < 0,
)
.map(({ name, info, version, tag, target }) => {
// Look for packageGroup.
const packageGroup = target['ng-update']['packageGroup'];
if (packageGroup) {
const packageGroupName = target['ng-update']['packageGroupName'] || packageGroup[0];
if (packageGroupName) {
if (packageGroups.has(name)) {
return null;
}
packageGroup.forEach((x: string) => packageGroups.set(x, packageGroupName));
packageGroups.set(packageGroupName, packageGroupName);
name = packageGroupName;
}
}
let command = `ng update ${name}`;
if (!tag) {
command += `@${semver.parse(version)?.major || version}`;
} else if (tag == 'next') {
command += ' --next';
}
return [name, `${info.installed.version} -> ${version} `, command];
})
.filter((x) => x !== null)
.sort((a, b) => (a && b ? a[0].localeCompare(b[0]) : 0));
if (packagesToUpdate.length == 0) {
logger.info('We analyzed your package.json and everything seems to be in order. Good work!');
return;
}
logger.info('We analyzed your package.json, there are some packages to update:\n');
// Find the largest name to know the padding needed.
let namePad = Math.max(...[...infoMap.keys()].map((x) => x.length)) + 2;
if (!Number.isFinite(namePad)) {
namePad = 30;
}
const pads = [namePad, 25, 0];
logger.info(
' ' + ['Name', 'Version', 'Command to update'].map((x, i) => x.padEnd(pads[i])).join(''),
);
logger.info(' ' + '-'.repeat(pads.reduce((s, x) => (s += x), 0) + 20));
packagesToUpdate.forEach((fields) => {
if (!fields) {
return;
}
logger.info(' ' + fields.map((x, i) => x.padEnd(pads[i])).join(''));
});
logger.info(
`\nThere might be additional packages which don't provide 'ng update' capabilities that are outdated.\n` +
`You can update the additional packages by running the update command of your package manager.`,
);
return;
}