Skip to content

Commit e4bc35e

Browse files
clydinfilipesilva
authored andcommitted
fix(@angular/cli): exclude packages from ng add that contain invalid peer dependencies
Certain older versions of packages may contain missing or invalid peer dependencies. As a result these packages may be incorrectly added to the project when no newer compatible version is found. An exclusion list is now present within `ng add` that will exclude packages with known peer dependency concerns from consideration when adding a package. Currently, only `@angular/localize@9.x` is included in the list. (cherry picked from commit 084eff6)
1 parent 17c029a commit e4bc35e

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

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

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ import { Spinner } from '../utilities/spinner';
2929
import { isTTY } from '../utilities/tty';
3030
import { Schema as AddCommandSchema } from './add';
3131

32+
/**
33+
* The set of packages that should have certain versions excluded from consideration
34+
* when attempting to find a compatible version for a package.
35+
* The key is a package name and the value is a SemVer range of versions to exclude.
36+
*/
37+
const packageVersionExclusions: Record<string, string | undefined> = {
38+
// @angular/localize@9.x versions do not have peer dependencies setup
39+
'@angular/localize': '9.x',
40+
};
41+
3242
export class AddCommand extends SchematicCommand<AddCommandSchema> {
3343
override readonly allowPrivateSchematics = true;
3444

@@ -40,6 +50,7 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
4050
}
4151
}
4252

53+
// eslint-disable-next-line max-lines-per-function
4354
async run(options: AddCommandSchema & Arguments) {
4455
await ensureCompatibleNpm(this.context.root);
4556

@@ -100,7 +111,13 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
100111
return 1;
101112
}
102113

114+
// Start with the version tagged as `latest` if it exists
103115
const latestManifest = packageMetadata.tags['latest'];
116+
if (latestManifest) {
117+
packageIdentifier = npa.resolve(latestManifest.name, latestManifest.version);
118+
}
119+
120+
// Adjust the version based on name and peer dependencies
104121
if (latestManifest && Object.keys(latestManifest.peerDependencies).length === 0) {
105122
if (latestManifest.name === '@angular/pwa') {
106123
const version = await this.findProjectVersion('@angular/cli');
@@ -113,38 +130,52 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
113130
) {
114131
packageIdentifier = npa.resolve('@angular/pwa', '0.12');
115132
}
116-
} else {
117-
packageIdentifier = npa.resolve(latestManifest.name, latestManifest.version);
118133
}
134+
119135
spinner.succeed(
120136
`Found compatible package version: ${colors.grey(packageIdentifier.toString())}.`,
121137
);
122138
} else if (!latestManifest || (await this.hasMismatchedPeer(latestManifest))) {
123139
// 'latest' is invalid so search for most recent matching package
140+
const versionExclusions = packageVersionExclusions[packageMetadata.name];
124141
const versionManifests = Object.values(packageMetadata.versions).filter(
125-
(value: PackageManifest) => !prerelease(value.version) && !value.deprecated,
142+
(value: PackageManifest) => {
143+
// Prerelease versions are not stable and should not be considered by default
144+
if (prerelease(value.version)) {
145+
return false;
146+
}
147+
// Deprecated versions should not be used or considered
148+
if (value.deprecated) {
149+
return false;
150+
}
151+
// Excluded package versions should not be considered
152+
if (versionExclusions && satisfies(value.version, versionExclusions)) {
153+
return false;
154+
}
155+
156+
return true;
157+
},
126158
);
127159

128160
versionManifests.sort((a, b) => rcompare(a.version, b.version, true));
129161

130162
let newIdentifier;
131163
for (const versionManifest of versionManifests) {
132164
if (!(await this.hasMismatchedPeer(versionManifest))) {
133-
newIdentifier = npa.resolve(packageIdentifier.name, versionManifest.version);
165+
newIdentifier = npa.resolve(versionManifest.name, versionManifest.version);
134166
break;
135167
}
136168
}
137169

138170
if (!newIdentifier) {
139-
spinner.warn("Unable to find compatible package. Using 'latest'.");
171+
spinner.warn("Unable to find compatible package. Using 'latest' tag.");
140172
} else {
141173
packageIdentifier = newIdentifier;
142174
spinner.succeed(
143175
`Found compatible package version: ${colors.grey(packageIdentifier.toString())}.`,
144176
);
145177
}
146178
} else {
147-
packageIdentifier = npa.resolve(latestManifest.name, latestManifest.version);
148179
spinner.succeed(
149180
`Found compatible package version: ${colors.grey(packageIdentifier.toString())}.`,
150181
);

packages/angular/cli/utilities/spinner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class Spinner {
4444
}
4545

4646
warn(text?: string): void {
47-
this.spinner.fail(text && colors.yellowBright(text));
47+
this.spinner.warn(text && colors.yellowBright(text));
4848
}
4949

5050
stop(): void {

0 commit comments

Comments
 (0)