@@ -14,6 +14,7 @@ import {
1414 Tree ,
1515} from '@angular-devkit/schematics' ;
1616import { NodePackageInstallTask , RunSchematicTask } from '@angular-devkit/schematics/tasks' ;
17+ import * as npa from 'npm-package-arg' ;
1718import { Observable , from as observableFrom , of } from 'rxjs' ;
1819import { map , mergeMap , reduce , switchMap } from 'rxjs/operators' ;
1920import * as semver from 'semver' ;
@@ -788,7 +789,7 @@ function _addPeerDependencies(
788789}
789790
790791
791- function _getAllDependencies ( tree : Tree ) : Map < string , VersionRange > {
792+ function _getAllDependencies ( tree : Tree ) : Array < readonly [ string , VersionRange ] > {
792793 const packageJsonContent = tree . read ( '/package.json' ) ;
793794 if ( ! packageJsonContent ) {
794795 throw new SchematicsException ( 'Could not find a package.json. Are you in a Node project?' ) ;
@@ -801,11 +802,11 @@ function _getAllDependencies(tree: Tree): Map<string, VersionRange> {
801802 throw new SchematicsException ( 'package.json could not be parsed: ' + e . message ) ;
802803 }
803804
804- return new Map < string , VersionRange > ( [
805- ...Object . entries ( packageJson . peerDependencies || { } ) ,
806- ...Object . entries ( packageJson . devDependencies || { } ) ,
807- ...Object . entries ( packageJson . dependencies || { } ) ,
808- ] as [ string , VersionRange ] [ ] ) ;
805+ return [
806+ ...Object . entries ( packageJson . peerDependencies || { } ) as Array < [ string , VersionRange ] > ,
807+ ...Object . entries ( packageJson . devDependencies || { } ) as Array < [ string , VersionRange ] > ,
808+ ...Object . entries ( packageJson . dependencies || { } ) as Array < [ string , VersionRange ] > ,
809+ ] ;
809810}
810811
811812function _formatVersion ( version : string | undefined ) {
@@ -826,6 +827,16 @@ function _formatVersion(version: string | undefined) {
826827 return version ;
827828}
828829
830+ /**
831+ * Returns whether or not the given package specifier (the value string in a
832+ * `package.json` dependency) is hosted in the NPM registry.
833+ * @throws When the specifier cannot be parsed.
834+ */
835+ function isPkgFromRegistry ( name : string , specifier : string ) : boolean {
836+ const result = npa . resolve ( name , specifier ) ;
837+
838+ return ! ! result . registry ;
839+ }
829840
830841export default function ( options : UpdateSchema ) : Rule {
831842 if ( ! options . packages ) {
@@ -847,14 +858,23 @@ export default function(options: UpdateSchema): Rule {
847858
848859 options . from = _formatVersion ( options . from ) ;
849860 options . to = _formatVersion ( options . to ) ;
861+ const usingYarn = options . packageManager === 'yarn' ;
850862
851863 return ( tree : Tree , context : SchematicContext ) => {
852864 const logger = context . logger ;
853- const allDependencies = _getAllDependencies ( tree ) ;
854- const packages = _buildPackageList ( options , allDependencies , logger ) ;
855- const usingYarn = options . packageManager === 'yarn' ;
865+ const npmDeps = new Map ( _getAllDependencies ( tree ) . filter ( ( [ name , specifier ] ) => {
866+ try {
867+ return isPkgFromRegistry ( name , specifier ) ;
868+ } catch {
869+ // Abort on failure because package.json is malformed.
870+ throw new SchematicsException (
871+ `Failed to parse dependency "${ name } " with specifier "${ specifier } "`
872+ + ` from package.json. Is the specifier malformed?` ) ;
873+ }
874+ } ) ) ;
875+ const packages = _buildPackageList ( options , npmDeps , logger ) ;
856876
857- return observableFrom ( [ ... allDependencies . keys ( ) ] ) . pipe (
877+ return observableFrom ( npmDeps . keys ( ) ) . pipe (
858878 // Grab all package.json from the npm repository. This requires a lot of HTTP calls so we
859879 // try to parallelize as many as possible.
860880 mergeMap ( depName => getNpmPackageJson (
@@ -899,8 +919,8 @@ export default function(options: UpdateSchema): Rule {
899919 do {
900920 lastPackagesSize = packages . size ;
901921 npmPackageJsonMap . forEach ( ( npmPackageJson ) => {
902- _addPackageGroup ( tree , packages , allDependencies , npmPackageJson , logger ) ;
903- _addPeerDependencies ( tree , packages , allDependencies , npmPackageJson , npmPackageJsonMap , logger ) ;
922+ _addPackageGroup ( tree , packages , npmDeps , npmPackageJson , logger ) ;
923+ _addPeerDependencies ( tree , packages , npmDeps , npmPackageJson , npmPackageJsonMap , logger ) ;
904924 } ) ;
905925 } while ( packages . size > lastPackagesSize ) ;
906926
@@ -909,7 +929,7 @@ export default function(options: UpdateSchema): Rule {
909929 npmPackageJsonMap . forEach ( ( npmPackageJson ) => {
910930 packageInfoMap . set (
911931 npmPackageJson . name ,
912- _buildPackageInfo ( tree , packages , allDependencies , npmPackageJson , logger ) ,
932+ _buildPackageInfo ( tree , packages , npmDeps , npmPackageJson , logger ) ,
913933 ) ;
914934 } ) ;
915935
0 commit comments