Skip to content

Commit 530bca6

Browse files
clydinKeen Yee Liau
authored and
Keen Yee Liau
committed
fix(@angular/cli): temporarily limit npm to version 6
This change will display an error message if using npm 7 (or versions earlier than 6). This is a temporarily change while npm 7 usability concerns are addressed. (cherry picked from commit 331f628)
1 parent 7b8bb16 commit 530bca6

File tree

6 files changed

+78
-3
lines changed

6 files changed

+78
-3
lines changed

lib/packages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ function loadPackageJson(p: string) {
8888
case 'engines':
8989
pkg['engines'] = {
9090
'node': '>= 10.13.0',
91-
'npm': '>= 6.11.0',
91+
'npm': '^6.11.0',
9292
'yarn': '>= 1.13.0',
9393
};
9494
break;

packages/angular/cli/commands/add-impl.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { Arguments } from '../models/interface';
1515
import { RunSchematicOptions, SchematicCommand } from '../models/schematic-command';
1616
import { colors } from '../utilities/color';
1717
import { installPackage, installTempPackage } from '../utilities/install-package';
18-
import { getPackageManager } from '../utilities/package-manager';
18+
import { ensureCompatibleNpm, getPackageManager } from '../utilities/package-manager';
1919
import {
2020
NgAddSaveDepedency,
2121
PackageManifest,
@@ -38,6 +38,8 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
3838
}
3939

4040
async run(options: AddCommandSchema & Arguments) {
41+
ensureCompatibleNpm();
42+
4143
if (!options.collection) {
4244
this.logger.fatal(
4345
`The "ng add" command requires a name argument to be specified eg. ` +

packages/angular/cli/commands/new-impl.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
import { Arguments } from '../models/interface';
99
import { SchematicCommand } from '../models/schematic-command';
10+
import { ensureCompatibleNpm } from '../utilities/package-manager';
1011
import { Schema as NewCommandSchema } from './new';
1112

1213

@@ -21,6 +22,8 @@ export class NewCommand extends SchematicCommand<NewCommandSchema> {
2122
}
2223

2324
public async run(options: NewCommandSchema & Arguments) {
25+
ensureCompatibleNpm();
26+
2427
// Register the version of the CLI in the registry.
2528
const packageJson = require('../package.json');
2629
const version = packageJson.version;

packages/angular/cli/commands/update-impl.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { Arguments } from '../models/interface';
1717
import { colors } from '../utilities/color';
1818
import { runTempPackageBin } from '../utilities/install-package';
1919
import { writeErrorToLogFile } from '../utilities/log-file';
20-
import { getPackageManager } from '../utilities/package-manager';
20+
import { ensureCompatibleNpm, getPackageManager } from '../utilities/package-manager';
2121
import {
2222
PackageIdentifier,
2323
PackageManifest,
@@ -265,6 +265,8 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
265265

266266
// tslint:disable-next-line:no-big-function
267267
async run(options: UpdateCommandSchema & Arguments) {
268+
ensureCompatibleNpm();
269+
268270
// Check if the @angular-devkit/schematics package can be resolved from the workspace root
269271
// This works around issues with packages containing migrations that cannot directly depend on the package
270272
// This check can be removed once the schematic runtime handles this situation

packages/angular/cli/utilities/package-manager.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,26 @@ export async function getPackageManager(root: string): Promise<PackageManager> {
5454
// Potentially with a prompt to choose and optionally set as the default.
5555
return packageManager || PackageManager.Npm;
5656
}
57+
58+
/**
59+
* Checks if the npm version is version 6.x. If not, display a message and exit.
60+
*/
61+
export function ensureCompatibleNpm() {
62+
try {
63+
const version = execSync('npm --version', {encoding: 'utf8', stdio: 'pipe'}).trim();
64+
const major = Number(version.match(/^(\d+)\./)?.[1]);
65+
if (major === 6) {
66+
return;
67+
}
68+
69+
// tslint:disable-next-line: no-console
70+
console.error(
71+
`npm version ${version} detected.\n` +
72+
'The Angular CLI currently requires npm version 6.\n\n' +
73+
'Please install a compatible version to proceed (`npm install --global npm@6`).\n',
74+
);
75+
process.exit(3);
76+
} catch {
77+
// npm is not installed
78+
}
79+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { getActivePackageManager } from '../../utils/packages';
2+
import { ng, npm } from '../../utils/process';
3+
import { expectToFail } from '../../utils/utils';
4+
5+
const errorText = 'The Angular CLI currently requires npm version 6.';
6+
7+
export default async function() {
8+
// Only relevant with npm as a package manager
9+
if (getActivePackageManager() !== 'npm') {
10+
return;
11+
}
12+
13+
const currentDirectory = process.cwd();
14+
try {
15+
// Install version 7.x
16+
await npm('install', '--global', 'npm@7');
17+
18+
// Ensure `ng add` exits and shows npm error
19+
const { message: stderrAdd } = await expectToFail(() => ng('add'));
20+
if (!stderrAdd.includes(errorText)) {
21+
throw new Error('ng add expected to show npm version error.');
22+
}
23+
24+
// Ensure `ng update` exits and shows npm error
25+
const { message: stderrUpdate } = await expectToFail(() => ng('update'));
26+
if (!stderrUpdate.includes(errorText)) {
27+
throw new Error('ng update expected to show npm version error.');
28+
}
29+
30+
// Ensure `ng new` exits and shows npm error
31+
// Must be outside the project for `ng new`
32+
process.chdir('..');
33+
const { message: stderrNew } = await expectToFail(() => ng('new'));
34+
if (!stderrNew.includes(errorText)) {
35+
throw new Error('ng new expected to show npm version error.');
36+
}
37+
} finally {
38+
// Change directory back
39+
process.chdir(currentDirectory);
40+
41+
// Reset version back to 6.x
42+
await npm('install', '--global', 'npm@6');
43+
}
44+
45+
}

0 commit comments

Comments
 (0)