@@ -9,37 +9,64 @@ import { logging } from '@angular-devkit/core';
99import { exec } from 'child_process' ;
1010import { readFileSync } from 'fs' ;
1111import { Observable , ReplaySubject , concat , of } from 'rxjs' ;
12- import { concatMap , filter , first , map , toArray } from 'rxjs/operators' ;
12+ import { concatMap , defaultIfEmpty , filter , first , map , toArray } from 'rxjs/operators' ;
1313import * as url from 'url' ;
1414import { NpmRepositoryPackageJson } from './npm-package-json' ;
1515
1616const RegistryClient = require ( 'npm-registry-client' ) ;
1717
1818const npmPackageJsonCache = new Map < string , Observable < NpmRepositoryPackageJson > > ( ) ;
19+ const npmConfigOptionCache = new Map < string , Observable < string | undefined > > ( ) ;
20+
21+ function getNpmConfigOption (
22+ option : string ,
23+ scope ?: string ,
24+ tryWithoutScope ?: boolean ,
25+ ) : Observable < string | undefined > {
26+ if ( scope && tryWithoutScope ) {
27+ return concat (
28+ getNpmConfigOption ( option , scope ) ,
29+ getNpmConfigOption ( option ) ,
30+ ) . pipe (
31+ filter ( result => ! ! result ) ,
32+ defaultIfEmpty ( ) ,
33+ first ( ) ,
34+ ) ;
35+ }
36+
37+ const fullOption = `${ scope ? scope + ':' : '' } ${ option } ` ;
38+
39+ let value = npmConfigOptionCache . get ( fullOption ) ;
40+ if ( value ) {
41+ return value ;
42+ }
1943
44+ const subject = new ReplaySubject < string | undefined > ( 1 ) ;
2045
21- function getNpmConfigOption ( option : string ) {
22- return new Observable < string | undefined > ( obs => {
23- try {
24- exec ( `npm get ${ option } ` , ( error , data ) => {
25- if ( error ) {
26- obs . next ( ) ;
46+ try {
47+ exec ( `npm get ${ fullOption } ` , ( error , data ) => {
48+ if ( error ) {
49+ subject . next ( ) ;
50+ } else {
51+ data = data . trim ( ) ;
52+ if ( ! data || data === 'undefined' || data === 'null' ) {
53+ subject . next ( ) ;
2754 } else {
28- data = data . trim ( ) ;
29- if ( ! data || data === 'undefined' || data === 'null' ) {
30- obs . next ( ) ;
31- } else {
32- obs . next ( data ) ;
33- }
55+ subject . next ( data ) ;
3456 }
57+ }
58+
59+ subject . complete ( ) ;
60+ } ) ;
61+ } catch {
62+ subject . next ( ) ;
63+ subject . complete ( ) ;
64+ }
65+
66+ value = subject . asObservable ( ) ;
67+ npmConfigOptionCache . set ( fullOption , value ) ;
3568
36- obs . complete ( ) ;
37- } ) ;
38- } catch {
39- obs . next ( ) ;
40- obs . complete ( ) ;
41- }
42- } ) ;
69+ return value ;
4370}
4471
4572function getNpmClientSslOptions ( strictSsl ?: string , cafile ?: string ) {
@@ -71,15 +98,11 @@ export function getNpmPackageJson(
7198 registryUrl : string | undefined ,
7299 logger : logging . LoggerApi ,
73100) : Observable < Partial < NpmRepositoryPackageJson > > {
74- const scope = packageName . startsWith ( '@' ) ? packageName . split ( '/' ) [ 0 ] : null ;
101+ const scope = packageName . startsWith ( '@' ) ? packageName . split ( '/' ) [ 0 ] : undefined ;
75102
76- return concat (
77- of ( registryUrl ) ,
78- scope ? getNpmConfigOption ( scope + ':registry' ) : of ( undefined ) ,
79- getNpmConfigOption ( 'registry' ) ,
103+ return (
104+ registryUrl ? of ( registryUrl ) : getNpmConfigOption ( 'registry' , scope , true )
80105 ) . pipe (
81- filter ( partialUrl => ! ! partialUrl ) ,
82- first ( ) ,
83106 map ( partialUrl => {
84107 if ( ! partialUrl ) {
85108 partialUrl = 'https://registry.npmjs.org/' ;
0 commit comments