function _usageMessage()

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;
}