88import { logging } from '@angular-devkit/core' ;
99import { exec } from 'child_process' ;
1010import { Observable , ReplaySubject , concat , of } from 'rxjs' ;
11- import { concatMap , filter , first , map , toArray } from 'rxjs/operators' ;
11+ import { concatMap , defaultIfEmpty , filter , first , map , toArray } from 'rxjs/operators' ;
1212import * as url from 'url' ;
1313import { NpmRepositoryPackageJson } from './npm-package-json' ;
1414
1515const RegistryClient = require ( 'npm-registry-client' ) ;
1616
1717const npmPackageJsonCache = new Map < string , Observable < NpmRepositoryPackageJson > > ( ) ;
18-
19-
20- function getNpmConfigOption ( option : string ) {
21- return new Observable < string | undefined > ( obs => {
22- try {
23- exec ( `npm get ${ option } ` , ( error , data ) => {
24- if ( error ) {
25- obs . next ( ) ;
18+ const npmConfigOptionCache = new Map < string , Observable < string | undefined > > ( ) ;
19+
20+ function getNpmConfigOption (
21+ option : string ,
22+ scope ?: string ,
23+ tryWithoutScope ?: boolean ,
24+ ) : Observable < string | undefined > {
25+ if ( scope && tryWithoutScope ) {
26+ return concat (
27+ getNpmConfigOption ( option , scope ) ,
28+ getNpmConfigOption ( option ) ,
29+ ) . pipe (
30+ filter ( result => ! ! result ) ,
31+ defaultIfEmpty ( ) ,
32+ first ( ) ,
33+ ) ;
34+ }
35+
36+ const fullOption = `${ scope ? scope + ':' : '' } ${ option } ` ;
37+
38+ let value = npmConfigOptionCache . get ( fullOption ) ;
39+ if ( value ) {
40+ return value ;
41+ }
42+
43+ const subject = new ReplaySubject < string | undefined > ( 1 ) ;
44+
45+ try {
46+ exec ( `npm get ${ fullOption } ` , ( error , data ) => {
47+ if ( error ) {
48+ subject . next ( ) ;
49+ } else {
50+ data = data . trim ( ) ;
51+ if ( ! data || data === 'undefined' || data === 'null' ) {
52+ subject . next ( ) ;
2653 } else {
27- data = data . trim ( ) ;
28- if ( ! data || data === 'undefined' || data === 'null' ) {
29- obs . next ( ) ;
30- } else {
31- obs . next ( data ) ;
32- }
54+ subject . next ( data ) ;
3355 }
56+ }
57+
58+ subject . complete ( ) ;
59+ } ) ;
60+ } catch {
61+ subject . next ( ) ;
62+ subject . complete ( ) ;
63+ }
64+
65+ value = subject . asObservable ( ) ;
66+ npmConfigOptionCache . set ( fullOption , value ) ;
3467
35- obs . complete ( ) ;
36- } ) ;
37- } catch {
38- obs . next ( ) ;
39- obs . complete ( ) ;
40- }
41- } ) ;
68+ return value ;
4269}
4370
4471/**
@@ -54,15 +81,11 @@ export function getNpmPackageJson(
5481 registryUrl : string | undefined ,
5582 logger : logging . LoggerApi ,
5683) : Observable < Partial < NpmRepositoryPackageJson > > {
57- const scope = packageName . startsWith ( '@' ) ? packageName . split ( '/' ) [ 0 ] : null ;
84+ const scope = packageName . startsWith ( '@' ) ? packageName . split ( '/' ) [ 0 ] : undefined ;
5885
59- return concat (
60- of ( registryUrl ) ,
61- scope ? getNpmConfigOption ( scope + ':registry' ) : of ( undefined ) ,
62- getNpmConfigOption ( 'registry' ) ,
86+ return (
87+ registryUrl ? of ( registryUrl ) : getNpmConfigOption ( 'registry' , scope , true )
6388 ) . pipe (
64- filter ( partialUrl => ! ! partialUrl ) ,
65- first ( ) ,
6689 map ( partialUrl => {
6790 if ( ! partialUrl ) {
6891 partialUrl = 'https://registry.npmjs.org/' ;
0 commit comments