88
99import { analytics , tags } from '@angular-devkit/core' ;
1010import { NodePackageDoesNotSupportSchematics } from '@angular-devkit/schematics/tools' ;
11+ import npa from 'npm-package-arg' ;
1112import { dirname , join } from 'path' ;
1213import { intersects , prerelease , rcompare , satisfies , valid , validRange } from 'semver' ;
1314import { PackageManager } from '../lib/config/workspace-schema' ;
@@ -28,8 +29,6 @@ import { Spinner } from '../utilities/spinner';
2829import { isTTY } from '../utilities/tty' ;
2930import { Schema as AddCommandSchema } from './add' ;
3031
31- const npa = require ( 'npm-package-arg' ) ;
32-
3332export class AddCommand extends SchematicCommand < AddCommandSchema > {
3433 override readonly allowPrivateSchematics = true ;
3534
@@ -62,21 +61,12 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
6261 return 1 ;
6362 }
6463
65- if ( packageIdentifier . registry && this . isPackageInstalled ( packageIdentifier . name ) ) {
66- let validVersion = false ;
67- const installedVersion = await this . findProjectVersion ( packageIdentifier . name ) ;
68- if ( installedVersion ) {
69- if ( packageIdentifier . type === 'range' ) {
70- validVersion = satisfies ( installedVersion , packageIdentifier . fetchSpec ) ;
71- } else if ( packageIdentifier . type === 'version' ) {
72- const v1 = valid ( packageIdentifier . fetchSpec ) ;
73- const v2 = valid ( installedVersion ) ;
74- validVersion = v1 !== null && v1 === v2 ;
75- } else if ( ! packageIdentifier . rawSpec ) {
76- validVersion = true ;
77- }
78- }
79-
64+ if (
65+ packageIdentifier . name &&
66+ packageIdentifier . registry &&
67+ this . isPackageInstalled ( packageIdentifier . name )
68+ ) {
69+ const validVersion = await this . isProjectVersionValid ( packageIdentifier ) ;
8070 if ( validVersion ) {
8171 // Already installed so just run schematic
8272 this . logger . info ( 'Skipping installation: Package already installed' ) ;
@@ -92,7 +82,7 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
9282 const usingYarn = packageManager === PackageManager . Yarn ;
9383 spinner . info ( `Using package manager: ${ colors . grey ( packageManager ) } ` ) ;
9484
95- if ( packageIdentifier . type === 'tag' && ! packageIdentifier . rawSpec ) {
85+ if ( packageIdentifier . name && packageIdentifier . type === 'tag' && ! packageIdentifier . rawSpec ) {
9686 // only package name provided; search for viable version
9787 // plus special cases for packages that did not have peer deps setup
9888 spinner . start ( 'Searching for compatible package version...' ) ;
@@ -126,7 +116,9 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
126116 } else {
127117 packageIdentifier = npa . resolve ( latestManifest . name , latestManifest . version ) ;
128118 }
129- spinner . succeed ( `Found compatible package version: ${ colors . grey ( packageIdentifier ) } .` ) ;
119+ spinner . succeed (
120+ `Found compatible package version: ${ colors . grey ( packageIdentifier . toString ( ) ) } .` ,
121+ ) ;
130122 } else if ( ! latestManifest || ( await this . hasMismatchedPeer ( latestManifest ) ) ) {
131123 // 'latest' is invalid so search for most recent matching package
132124 const versionManifests = Object . values ( packageMetadata . versions ) . filter (
@@ -147,11 +139,15 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
147139 spinner . warn ( "Unable to find compatible package. Using 'latest'." ) ;
148140 } else {
149141 packageIdentifier = newIdentifier ;
150- spinner . succeed ( `Found compatible package version: ${ colors . grey ( packageIdentifier ) } .` ) ;
142+ spinner . succeed (
143+ `Found compatible package version: ${ colors . grey ( packageIdentifier . toString ( ) ) } .` ,
144+ ) ;
151145 }
152146 } else {
153147 packageIdentifier = npa . resolve ( latestManifest . name , latestManifest . version ) ;
154- spinner . succeed ( `Found compatible package version: ${ colors . grey ( packageIdentifier ) } .` ) ;
148+ spinner . succeed (
149+ `Found compatible package version: ${ colors . grey ( packageIdentifier . toString ( ) ) } .` ,
150+ ) ;
155151 }
156152 }
157153
@@ -160,7 +156,7 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
160156
161157 try {
162158 spinner . start ( 'Loading package information from registry...' ) ;
163- const manifest = await fetchPackageManifest ( packageIdentifier , this . logger , {
159+ const manifest = await fetchPackageManifest ( packageIdentifier . toString ( ) , this . logger , {
164160 registry : options . registry ,
165161 verbose : options . verbose ,
166162 usingYarn,
@@ -235,6 +231,28 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
235231 return this . executeSchematic ( collectionName , options [ '--' ] ) ;
236232 }
237233
234+ private async isProjectVersionValid ( packageIdentifier : npa . Result ) : Promise < boolean > {
235+ if ( ! packageIdentifier . name ) {
236+ return false ;
237+ }
238+
239+ let validVersion = false ;
240+ const installedVersion = await this . findProjectVersion ( packageIdentifier . name ) ;
241+ if ( installedVersion ) {
242+ if ( packageIdentifier . type === 'range' && packageIdentifier . fetchSpec ) {
243+ validVersion = satisfies ( installedVersion , packageIdentifier . fetchSpec ) ;
244+ } else if ( packageIdentifier . type === 'version' ) {
245+ const v1 = valid ( packageIdentifier . fetchSpec ) ;
246+ const v2 = valid ( installedVersion ) ;
247+ validVersion = v1 !== null && v1 === v2 ;
248+ } else if ( ! packageIdentifier . rawSpec ) {
249+ validVersion = true ;
250+ }
251+ }
252+
253+ return validVersion ;
254+ }
255+
238256 override async reportAnalytics (
239257 paths : string [ ] ,
240258 options : AddCommandSchema & Arguments ,
0 commit comments