@angular/cli 11.2.14 → 11.2.18

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.
@@ -23,8 +23,9 @@ export declare class UpdateCommand extends Command<UpdateCommandSchema> {
23
23
  private commit;
24
24
  private checkCleanGit;
25
25
  /**
26
- * Checks if the current installed CLI version is older than the latest version.
27
- * @returns `true` when the installed version is older.
28
- */
29
- private checkCLILatestVersion;
26
+ * Checks if the current installed CLI version is older or newer than a compatible version.
27
+ * @returns the version to install or null when there is no update to install.
28
+ */
29
+ private checkCLIVersion;
30
+ private getCLIUpdateRunnerVersion;
30
31
  }
@@ -14,6 +14,7 @@ const child_process_1 = require("child_process");
14
14
  const fs = require("fs");
15
15
  const path = require("path");
16
16
  const semver = require("semver");
17
+ const cli_1 = require("../lib/cli");
17
18
  const schema_1 = require("../lib/config/schema");
18
19
  const command_1 = require("../models/command");
19
20
  const schematic_engine_host_1 = require("../models/schematic-engine-host");
@@ -26,8 +27,6 @@ const package_tree_1 = require("../utilities/package-tree");
26
27
  const npa = require('npm-package-arg');
27
28
  const pickManifest = require('npm-pick-manifest');
28
29
  const oldConfigFileNames = ['.angular-cli.json', 'angular-cli.json'];
29
- const NG_VERSION_9_POST_MSG = color_1.colors.cyan('\nYour project has been updated to Angular version 9!\n' +
30
- 'For more info, please see: https://v9.angular.io/guide/updating-to-version-9');
31
30
  /**
32
31
  * Disable CLI version mismatch checks and forces usage of the invoked CLI
33
32
  * instead of invoking the local installed version.
@@ -36,6 +35,7 @@ const disableVersionCheckEnv = process.env['NG_DISABLE_VERSION_CHECK'];
36
35
  const disableVersionCheck = disableVersionCheckEnv !== undefined &&
37
36
  disableVersionCheckEnv !== '0' &&
38
37
  disableVersionCheckEnv.toLowerCase() !== 'false';
38
+ const ANGULAR_PACKAGES_REGEXP = /^@(?:angular|nguniversal)\//;
39
39
  class UpdateCommand extends command_1.Command {
40
40
  constructor() {
41
41
  super(...arguments);
@@ -57,7 +57,7 @@ class UpdateCommand extends command_1.Command {
57
57
  let error = false;
58
58
  let logs = [];
59
59
  const files = new Set();
60
- const reporterSubscription = this.workflow.reporter.subscribe(event => {
60
+ const reporterSubscription = this.workflow.reporter.subscribe((event) => {
61
61
  // Strip leading slash to prevent confusion.
62
62
  const eventPath = event.path.startsWith('/') ? event.path.substr(1) : event.path;
63
63
  switch (event.kind) {
@@ -85,11 +85,11 @@ class UpdateCommand extends command_1.Command {
85
85
  break;
86
86
  }
87
87
  });
88
- const lifecycleSubscription = this.workflow.lifeCycle.subscribe(event => {
88
+ const lifecycleSubscription = this.workflow.lifeCycle.subscribe((event) => {
89
89
  if (event.kind == 'end' || event.kind == 'post-tasks-start') {
90
90
  if (!error) {
91
91
  // Output the logging queue, no error happened.
92
- logs.forEach(log => this.logger.info(` ${log}`));
92
+ logs.forEach((log) => this.logger.info(` ${log}`));
93
93
  logs = [];
94
94
  }
95
95
  }
@@ -125,7 +125,7 @@ class UpdateCommand extends command_1.Command {
125
125
  */
126
126
  async executeMigration(packageName, collectionPath, migrationName, commit) {
127
127
  const collection = this.workflow.engine.createCollection(collectionPath);
128
- const name = collection.listSchematicNames().find(name => name === migrationName);
128
+ const name = collection.listSchematicNames().find((name) => name === migrationName);
129
129
  if (!name) {
130
130
  this.logger.error(`Cannot find migration '${migrationName}' in '${packageName}'.`);
131
131
  return false;
@@ -161,7 +161,8 @@ class UpdateCommand extends command_1.Command {
161
161
  async executePackageMigrations(migrations, packageName, commit = false) {
162
162
  for (const migration of migrations) {
163
163
  const [title, ...description] = migration.description.split('. ');
164
- this.logger.info(color_1.colors.cyan(color_1.colors.symbols.pointer) + ' ' +
164
+ this.logger.info(color_1.colors.cyan(color_1.colors.symbols.pointer) +
165
+ ' ' +
165
166
  color_1.colors.bold(title.endsWith('.') ? title : title + '.'));
166
167
  if (description.length) {
167
168
  this.logger.info(' ' + description.join('.\n '));
@@ -191,11 +192,14 @@ class UpdateCommand extends command_1.Command {
191
192
  async run(options) {
192
193
  var _a;
193
194
  await package_manager_1.ensureCompatibleNpm(this.context.root);
194
- // Check if the current installed CLI version is older than the latest version.
195
- if (!disableVersionCheck && await this.checkCLILatestVersion(options.verbose, options.next)) {
196
- this.logger.warn(`The installed local Angular CLI version is older than the latest ${options.next ? 'pre-release' : 'stable'} version.\n` +
197
- 'Installing a temporary version to perform the update.');
198
- return install_package_1.runTempPackageBin(`@angular/cli@${options.next ? 'next' : 'latest'}`, this.logger, this.packageManager, process.argv.slice(2));
195
+ // Check if the current installed CLI version is older than the latest compatible version.
196
+ if (!disableVersionCheck) {
197
+ const cliVersionToInstall = await this.checkCLIVersion(options['--'], options.verbose, options.next);
198
+ if (cliVersionToInstall) {
199
+ this.logger.warn('The installed Angular CLI version is outdated.\n' +
200
+ `Installing a temporary Angular CLI versioned ${cliVersionToInstall} to perform the update.`);
201
+ return install_package_1.runTempPackageBin(`@angular/cli@${cliVersionToInstall}`, this.logger, this.packageManager, process.argv.slice(2));
202
+ }
199
203
  }
200
204
  const logVerbose = (message) => {
201
205
  if (options.verbose) {
@@ -222,7 +226,7 @@ class UpdateCommand extends command_1.Command {
222
226
  this.logger.error(`Package '${request}' is not a registry package identifer.`);
223
227
  return 1;
224
228
  }
225
- if (packages.some(v => v.name === packageIdentifier.name)) {
229
+ if (packages.some((v) => v.name === packageIdentifier.name)) {
226
230
  this.logger.error(`Duplicate package '${packageIdentifier.name}' specified.`);
227
231
  return 1;
228
232
  }
@@ -331,8 +335,7 @@ class UpdateCommand extends command_1.Command {
331
335
  // Normalize slashes
332
336
  migrations = migrations.replace(/\\/g, '/');
333
337
  if (migrations.startsWith('../')) {
334
- this.logger.error('Package contains an invalid migrations field. ' +
335
- 'Paths outside the package root are not permitted.');
338
+ this.logger.error('Package contains an invalid migrations field. Paths outside the package root are not permitted.');
336
339
  return 1;
337
340
  }
338
341
  // Check if it is a package-local location
@@ -356,9 +359,9 @@ class UpdateCommand extends command_1.Command {
356
359
  return 1;
357
360
  }
358
361
  }
359
- let success = false;
362
+ let result;
360
363
  if (typeof options.migrateOnly == 'string') {
361
- success = await this.executeMigration(packageName, migrations, options.migrateOnly, options.createCommits);
364
+ result = await this.executeMigration(packageName, migrations, options.migrateOnly, options.createCommits);
362
365
  }
363
366
  else {
364
367
  const from = coerceVersionNumber(options.from);
@@ -367,18 +370,9 @@ class UpdateCommand extends command_1.Command {
367
370
  return 1;
368
371
  }
369
372
  const migrationRange = new semver.Range('>' + from + ' <=' + (options.to || packageNode.version));
370
- success = await this.executeMigrations(packageName, migrations, migrationRange, options.createCommits);
371
- }
372
- if (success) {
373
- if (packageName === '@angular/core'
374
- && options.from
375
- && +options.from.split('.')[0] < 9
376
- && (options.to || packageNode.version).split('.')[0] === '9') {
377
- this.logger.info(NG_VERSION_9_POST_MSG);
378
- }
379
- return 0;
373
+ result = await this.executeMigrations(packageName, migrations, migrationRange, options.createCommits);
380
374
  }
381
- return 1;
375
+ return result ? 0 : 1;
382
376
  }
383
377
  const requests = [];
384
378
  // Validate packages actually are part of the workspace
@@ -453,6 +447,28 @@ class UpdateCommand extends command_1.Command {
453
447
  this.logger.info(`Package '${packageName}' is already up to date.`);
454
448
  continue;
455
449
  }
450
+ if (node.package && ANGULAR_PACKAGES_REGEXP.test(node.package.name)) {
451
+ const { name, version } = node.package;
452
+ const toBeInstalledMajorVersion = +manifest.version.split('.')[0];
453
+ const currentMajorVersion = +version.split('.')[0];
454
+ if (toBeInstalledMajorVersion - currentMajorVersion > 1) {
455
+ // Only allow updating a single version at a time.
456
+ if (currentMajorVersion < 6) {
457
+ // Before version 6, the major versions were not always sequential.
458
+ // Example @angular/core skipped version 3, @angular/cli skipped versions 2-5.
459
+ this.logger.error(`Updating multiple major versions of '${name}' at once is not supported. Please migrate each major version individually.\n` +
460
+ `For more information about the update process, see https://update.angular.io/.`);
461
+ }
462
+ else {
463
+ const nextMajorVersionFromCurrent = currentMajorVersion + 1;
464
+ this.logger.error(`Updating multiple major versions of '${name}' at once is not supported. Please migrate each major version individually.\n` +
465
+ `Run 'ng update ${name}@${nextMajorVersionFromCurrent}' in your workspace directory ` +
466
+ `to update to latest '${nextMajorVersionFromCurrent}.x' version of '${name}'.\n\n` +
467
+ `For more information about the update process, see https://update.angular.io/?v=${currentMajorVersion}.0-${nextMajorVersionFromCurrent}.0`);
468
+ }
469
+ return 1;
470
+ }
471
+ }
456
472
  packagesToUpdate.push(requestIdentifier.toString());
457
473
  }
458
474
  if (packagesToUpdate.length === 0) {
@@ -537,9 +553,6 @@ class UpdateCommand extends command_1.Command {
537
553
  return 0;
538
554
  }
539
555
  }
540
- if (migrations.some(m => m.package === '@angular/core' && m.to.split('.')[0] === '9' && +m.from.split('.')[0] < 9)) {
541
- this.logger.info(NG_VERSION_9_POST_MSG);
542
- }
543
556
  }
544
557
  return success ? 0 : 1;
545
558
  }
@@ -584,7 +597,10 @@ class UpdateCommand extends command_1.Command {
584
597
  }
585
598
  checkCleanGit() {
586
599
  try {
587
- const topLevel = child_process_1.execSync('git rev-parse --show-toplevel', { encoding: 'utf8', stdio: 'pipe' });
600
+ const topLevel = child_process_1.execSync('git rev-parse --show-toplevel', {
601
+ encoding: 'utf8',
602
+ stdio: 'pipe',
603
+ });
588
604
  const result = child_process_1.execSync('git status --porcelain', { encoding: 'utf8', stdio: 'pipe' });
589
605
  if (result.trim().length === 0) {
590
606
  return true;
@@ -601,16 +617,38 @@ class UpdateCommand extends command_1.Command {
601
617
  return true;
602
618
  }
603
619
  /**
604
- * Checks if the current installed CLI version is older than the latest version.
605
- * @returns `true` when the installed version is older.
606
- */
607
- async checkCLILatestVersion(verbose = false, next = false) {
608
- const { version: installedCLIVersion } = require('../package.json');
609
- const LatestCLIManifest = await package_metadata_1.fetchPackageManifest(`@angular/cli@${next ? 'next' : 'latest'}`, this.logger, {
620
+ * Checks if the current installed CLI version is older or newer than a compatible version.
621
+ * @returns the version to install or null when there is no update to install.
622
+ */
623
+ async checkCLIVersion(packagesToUpdate, verbose = false, next = false) {
624
+ const { version } = await package_metadata_1.fetchPackageManifest(`@angular/cli@${this.getCLIUpdateRunnerVersion(packagesToUpdate, next)}`, this.logger, {
610
625
  verbose,
611
626
  usingYarn: this.packageManager === schema_1.PackageManager.Yarn,
612
627
  });
613
- return semver.lt(installedCLIVersion, LatestCLIManifest.version);
628
+ return cli_1.VERSION.full === version ? null : version;
629
+ }
630
+ getCLIUpdateRunnerVersion(packagesToUpdate, next) {
631
+ var _a, _b;
632
+ if (next) {
633
+ return 'next';
634
+ }
635
+ const updatingAngularPackage = packagesToUpdate === null || packagesToUpdate === void 0 ? void 0 : packagesToUpdate.find((r) => ANGULAR_PACKAGES_REGEXP.test(r));
636
+ if (updatingAngularPackage) {
637
+ // If we are updating any Angular package we can update the CLI to the target version because
638
+ // migrations for @angular/core@13 can be executed using Angular/cli@13.
639
+ // This is same behaviour as `npx @angular/cli@13 update @angular/core@13`.
640
+ // `@angular/cli@13` -> ['', 'angular/cli', '13']
641
+ // `@angular/cli` -> ['', 'angular/cli']
642
+ const tempVersion = coerceVersionNumber(updatingAngularPackage.split('@')[2]);
643
+ return (_b = (_a = semver.parse(tempVersion)) === null || _a === void 0 ? void 0 : _a.major) !== null && _b !== void 0 ? _b : 'latest';
644
+ }
645
+ // When not updating an Angular package we cannot determine which schematic runtime the migration should to be executed in.
646
+ // Typically, we can assume that the `@angular/cli` was updated previously.
647
+ // Example: Angular official packages are typically updated prior to NGRX etc...
648
+ // Therefore, we only update to the latest patch version of the installed major version of the Angular CLI.
649
+ // This is important because we might end up in a scenario where locally Angular v12 is installed, updating NGRX from 11 to 12.
650
+ // We end up using Angular ClI v13 to run the migrations if we run the migrations using the CLI installed major version + 1 logic.
651
+ return cli_1.VERSION.major;
614
652
  }
615
653
  }
616
654
  exports.UpdateCommand = UpdateCommand;
package/lib/init.js CHANGED
@@ -90,7 +90,9 @@ if (process.env['NG_CLI_PROFILING']) {
90
90
  if (isGlobalGreater) {
91
91
  // If using the update command and the global version is greater, use the newer update command
92
92
  // This allows improvements in update to be used in older versions that do not have bootstrapping
93
- if (process.argv[2] === 'update') {
93
+ if (process.argv[2] === 'update' &&
94
+ cli.VERSION &&
95
+ cli.VERSION.major - globalVersion.major <= 1) {
94
96
  cli = await Promise.resolve().then(() => require('./cli'));
95
97
  }
96
98
  else if (await config_1.isWarningEnabled('versionMismatch')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/cli",
3
- "version": "11.2.14",
3
+ "version": "11.2.18",
4
4
  "description": "CLI tool for Angular",
5
5
  "main": "lib/cli/index.js",
6
6
  "bin": {
@@ -28,11 +28,11 @@
28
28
  },
29
29
  "homepage": "https://github.com/angular/angular-cli",
30
30
  "dependencies": {
31
- "@angular-devkit/architect": "0.1102.14",
32
- "@angular-devkit/core": "11.2.14",
33
- "@angular-devkit/schematics": "11.2.14",
34
- "@schematics/angular": "11.2.14",
35
- "@schematics/update": "0.1102.14",
31
+ "@angular-devkit/architect": "0.1102.18",
32
+ "@angular-devkit/core": "11.2.18",
33
+ "@angular-devkit/schematics": "11.2.18",
34
+ "@schematics/angular": "11.2.18",
35
+ "@schematics/update": "0.1102.18",
36
36
  "@yarnpkg/lockfile": "1.1.0",
37
37
  "ansi-colors": "4.1.1",
38
38
  "debug": "4.3.1",
@@ -54,12 +54,12 @@
54
54
  "ng-update": {
55
55
  "migrations": "@schematics/angular/migrations/migration-collection.json",
56
56
  "packageGroup": {
57
- "@angular/cli": "11.2.14",
58
- "@angular-devkit/architect": "0.1102.14",
59
- "@angular-devkit/build-angular": "0.1102.14",
60
- "@angular-devkit/build-webpack": "0.1102.14",
61
- "@angular-devkit/core": "11.2.14",
62
- "@angular-devkit/schematics": "11.2.14"
57
+ "@angular/cli": "11.2.18",
58
+ "@angular-devkit/architect": "0.1102.18",
59
+ "@angular-devkit/build-angular": "0.1102.18",
60
+ "@angular-devkit/build-webpack": "0.1102.18",
61
+ "@angular-devkit/core": "11.2.18",
62
+ "@angular-devkit/schematics": "11.2.18"
63
63
  }
64
64
  },
65
65
  "engines": {