88import { execSync } from 'child_process' ;
99import * as fs from 'fs' ;
1010import * as path from 'path' ;
11- import * as semver from 'semver' ;
1211import { Arguments , Option } from '../models/interface' ;
1312import { SchematicCommand } from '../models/schematic-command' ;
1413import { getPackageManager } from '../utilities/package-manager' ;
@@ -21,7 +20,11 @@ import {
2120import { PackageTreeNode , findNodeDependencies , readPackageTree } from '../utilities/package-tree' ;
2221import { Schema as UpdateCommandSchema } from './update' ;
2322
24- const npa = require ( 'npm-package-arg' ) ;
23+ const npa = require ( 'npm-package-arg' ) as ( selector : string ) => PackageIdentifier ;
24+ const pickManifest = require ( 'npm-pick-manifest' ) as (
25+ metadata : PackageMetadata ,
26+ selector : string ,
27+ ) => PackageManifest ;
2528
2629const oldConfigFileNames = [ '.angular-cli.json' , 'angular-cli.json' ] ;
2730
@@ -37,7 +40,7 @@ export class UpdateCommand extends SchematicCommand<UpdateCommandSchema> {
3740 const packages : PackageIdentifier [ ] = [ ] ;
3841 for ( const request of options [ '--' ] || [ ] ) {
3942 try {
40- const packageIdentifier : PackageIdentifier = npa ( request ) ;
43+ const packageIdentifier = npa ( request ) ;
4144
4245 // only registry identifiers are supported
4346 if ( ! packageIdentifier . registry ) {
@@ -245,7 +248,7 @@ export class UpdateCommand extends SchematicCommand<UpdateCommandSchema> {
245248
246249 const requests : {
247250 identifier : PackageIdentifier ;
248- node : PackageTreeNode | string ;
251+ node : PackageTreeNode ;
249252 } [ ] = [ ] ;
250253
251254 // Validate packages actually are part of the workspace
@@ -258,11 +261,7 @@ export class UpdateCommand extends SchematicCommand<UpdateCommandSchema> {
258261 }
259262
260263 // If a specific version is requested and matches the installed version, skip.
261- if (
262- pkg . type === 'version' &&
263- typeof node === 'object' &&
264- node . package . version === pkg . fetchSpec
265- ) {
264+ if ( pkg . type === 'version' && node . package . version === pkg . fetchSpec ) {
266265 this . logger . info ( `Package '${ pkg . name } ' is already at '${ pkg . fetchSpec } '.` ) ;
267266 continue ;
268267 }
@@ -294,18 +293,34 @@ export class UpdateCommand extends SchematicCommand<UpdateCommandSchema> {
294293 // Try to find a package version based on the user requested package specifier
295294 // registry specifier types are either version, range, or tag
296295 let manifest : PackageManifest | undefined ;
297- if ( requestIdentifier . type === 'version' ) {
298- manifest = metadata . versions . get ( requestIdentifier . fetchSpec ) ;
299- } else if ( requestIdentifier . type === 'range' ) {
300- const maxVersion = semver . maxSatisfying (
301- Array . from ( metadata . versions . keys ( ) ) ,
302- requestIdentifier . fetchSpec ,
303- ) ;
304- if ( maxVersion ) {
305- manifest = metadata . versions . get ( maxVersion ) ;
296+ if (
297+ requestIdentifier . type === 'version' ||
298+ requestIdentifier . type === 'range' ||
299+ requestIdentifier . type === 'tag'
300+ ) {
301+ try {
302+ manifest = pickManifest ( metadata , requestIdentifier . fetchSpec ) ;
303+ } catch ( e ) {
304+ if ( e . code === 'ETARGET' ) {
305+ // If not found and next was used and user did not provide a specifier, try latest.
306+ // Package may not have a next tag.
307+ if (
308+ requestIdentifier . type === 'tag' &&
309+ requestIdentifier . fetchSpec === 'next' &&
310+ ! requestIdentifier . rawSpec
311+ ) {
312+ try {
313+ manifest = pickManifest ( metadata , 'latest' ) ;
314+ } catch ( e ) {
315+ if ( e . code !== 'ETARGET' && e . code !== 'ENOVERSIONS' ) {
316+ throw e ;
317+ }
318+ }
319+ }
320+ } else if ( e . code !== 'ENOVERSIONS' ) {
321+ throw e ;
322+ }
306323 }
307- } else if ( requestIdentifier . type === 'tag' ) {
308- manifest = metadata . tags [ requestIdentifier . fetchSpec ] ;
309324 }
310325
311326 if ( ! manifest ) {
@@ -316,10 +331,7 @@ export class UpdateCommand extends SchematicCommand<UpdateCommandSchema> {
316331 return 1 ;
317332 }
318333
319- if (
320- ( typeof node === 'string' && manifest . version === node ) ||
321- ( typeof node === 'object' && manifest . version === node . package . version )
322- ) {
334+ if ( manifest . version === node . package . version ) {
323335 this . logger . info ( `Package '${ packageName } ' is already up to date.` ) ;
324336 continue ;
325337 }
0 commit comments