Skip to content

Commit 0abeadb

Browse files
clydinvikerman
authored andcommitted
refactor(@angular/cli): use canonical npm logic to determine update package version
1 parent e444412 commit 0abeadb

File tree

5 files changed

+60
-31
lines changed

5 files changed

+60
-31
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
9090
}
9191
} else if (!latestManifest || (await this.hasMismatchedPeer(latestManifest))) {
9292
// 'latest' is invalid so search for most recent matching package
93-
const versionManifests = Array.from(packageMetadata.versions.values()).filter(
93+
const versionManifests = Object.values(packageMetadata.versions).filter(
9494
value => !prerelease(value.version),
9595
);
9696

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

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ import {
2626
import { PackageTreeNode, findNodeDependencies, readPackageTree } from '../utilities/package-tree';
2727
import { Schema as UpdateCommandSchema } from './update';
2828

29-
const npa = require('npm-package-arg');
29+
const npa = require('npm-package-arg') as (selector: string) => PackageIdentifier;
30+
const pickManifest = require('npm-pick-manifest') as (
31+
metadata: PackageMetadata,
32+
selector: string,
33+
) => PackageManifest;
3034

3135
const oldConfigFileNames = ['.angular-cli.json', 'angular-cli.json'];
3236

@@ -188,7 +192,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
188192
const packages: PackageIdentifier[] = [];
189193
for (const request of options['--'] || []) {
190194
try {
191-
const packageIdentifier: PackageIdentifier = npa(request);
195+
const packageIdentifier = npa(request);
192196

193197
// only registry identifiers are supported
194198
if (!packageIdentifier.registry) {
@@ -271,8 +275,19 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
271275

272276
this.logger.info(`Found ${Object.keys(rootDependencies).length} dependencies.`);
273277

274-
if (options.all || packages.length === 0) {
275-
// Either update all packages or show status
278+
if (options.all) {
279+
// 'all' option and a zero length packages have already been checked.
280+
// Add all direct dependencies to be updated
281+
for (const dep of Object.keys(rootDependencies)) {
282+
const packageIdentifier = npa(dep);
283+
if (options.next) {
284+
packageIdentifier.fetchSpec = 'next';
285+
}
286+
287+
packages.push(packageIdentifier);
288+
}
289+
} else if (packages.length === 0) {
290+
// Show status
276291
const { success } = await this.executeSchematic('@schematics/update', 'update', {
277292
force: options.force || false,
278293
next: options.next || false,
@@ -397,7 +412,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
397412

398413
const requests: {
399414
identifier: PackageIdentifier;
400-
node: PackageTreeNode | string;
415+
node: PackageTreeNode;
401416
}[] = [];
402417

403418
// Validate packages actually are part of the workspace
@@ -410,11 +425,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
410425
}
411426

412427
// If a specific version is requested and matches the installed version, skip.
413-
if (
414-
pkg.type === 'version' &&
415-
typeof node === 'object' &&
416-
node.package.version === pkg.fetchSpec
417-
) {
428+
if (pkg.type === 'version' && node.package.version === pkg.fetchSpec) {
418429
this.logger.info(`Package '${pkg.name}' is already at '${pkg.fetchSpec}'.`);
419430
continue;
420431
}
@@ -448,18 +459,34 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
448459
// Try to find a package version based on the user requested package specifier
449460
// registry specifier types are either version, range, or tag
450461
let manifest: PackageManifest | undefined;
451-
if (requestIdentifier.type === 'version') {
452-
manifest = metadata.versions.get(requestIdentifier.fetchSpec);
453-
} else if (requestIdentifier.type === 'range') {
454-
const maxVersion = semver.maxSatisfying(
455-
Array.from(metadata.versions.keys()),
456-
requestIdentifier.fetchSpec,
457-
);
458-
if (maxVersion) {
459-
manifest = metadata.versions.get(maxVersion);
462+
if (
463+
requestIdentifier.type === 'version' ||
464+
requestIdentifier.type === 'range' ||
465+
requestIdentifier.type === 'tag'
466+
) {
467+
try {
468+
manifest = pickManifest(metadata, requestIdentifier.fetchSpec);
469+
} catch (e) {
470+
if (e.code === 'ETARGET') {
471+
// If not found and next was used and user did not provide a specifier, try latest.
472+
// Package may not have a next tag.
473+
if (
474+
requestIdentifier.type === 'tag' &&
475+
requestIdentifier.fetchSpec === 'next' &&
476+
!requestIdentifier.rawSpec
477+
) {
478+
try {
479+
manifest = pickManifest(metadata, 'latest');
480+
} catch (e) {
481+
if (e.code !== 'ETARGET' && e.code !== 'ENOVERSIONS') {
482+
throw e;
483+
}
484+
}
485+
}
486+
} else if (e.code !== 'ENOVERSIONS') {
487+
throw e;
488+
}
460489
}
461-
} else if (requestIdentifier.type === 'tag') {
462-
manifest = metadata.tags[requestIdentifier.fetchSpec];
463490
}
464491

465492
if (!manifest) {
@@ -470,10 +497,7 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
470497
return 1;
471498
}
472499

473-
if (
474-
(typeof node === 'string' && manifest.version === node) ||
475-
(typeof node === 'object' && manifest.version === node.package.version)
476-
) {
500+
if (manifest.version === node.package.version) {
477501
this.logger.info(`Package '${packageName}' is already up to date.`);
478502
continue;
479503
}

packages/angular/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"ini": "1.3.5",
3737
"inquirer": "7.0.0",
3838
"npm-package-arg": "6.1.1",
39+
"npm-pick-manifest": "3.0.2",
3940
"open": "6.4.0",
4041
"pacote": "9.5.8",
4142
"read-package-tree": "5.3.1",

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export interface PackageManifest {
5050
export interface PackageMetadata {
5151
name: string;
5252
tags: { [tag: string]: PackageManifest | undefined };
53-
versions: Map<string, PackageManifest>;
53+
versions: Record<string, PackageManifest>;
5454
}
5555

5656
let npmrc: { [key: string]: string };
@@ -179,18 +179,22 @@ export async function fetchPackageMetadata(
179179
const metadata: PackageMetadata = {
180180
name: response.name,
181181
tags: {},
182-
versions: new Map(),
182+
versions: {},
183183
};
184184

185185
if (response.versions) {
186186
for (const [version, manifest] of Object.entries(response.versions)) {
187-
metadata.versions.set(version, normalizeManifest(manifest as {}));
187+
metadata.versions[version] = normalizeManifest(manifest as {});
188188
}
189189
}
190190

191191
if (response['dist-tags']) {
192+
// Store this for use with other npm utility packages
193+
// tslint:disable-next-line: no-any
194+
(metadata as any)['dist-tags'] = response['dist-tags'];
195+
192196
for (const [tag, version] of Object.entries(response['dist-tags'])) {
193-
const manifest = metadata.versions.get(version as string);
197+
const manifest = metadata.versions[version as string];
194198
if (manifest) {
195199
metadata.tags[tag] = manifest;
196200
} else if (verbose) {

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7114,7 +7114,7 @@ npm-packlist@^1.1.12, npm-packlist@^1.1.6:
71147114
ignore-walk "^3.0.1"
71157115
npm-bundled "^1.0.1"
71167116

7117-
npm-pick-manifest@^3.0.0:
7117+
npm-pick-manifest@3.0.2, npm-pick-manifest@^3.0.0:
71187118
version "3.0.2"
71197119
resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz#f4d9e5fd4be2153e5f4e5f9b7be8dc419a99abb7"
71207120
integrity sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==

0 commit comments

Comments
 (0)