8
8
import { logging } from '@angular-devkit/core' ;
9
9
import { exec } from 'child_process' ;
10
10
import { 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' ;
12
12
import * as url from 'url' ;
13
13
import { NpmRepositoryPackageJson } from './npm-package-json' ;
14
14
15
15
const RegistryClient = require ( 'npm-registry-client' ) ;
16
16
17
17
const 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 ( ) ;
26
53
} 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 ) ;
33
55
}
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 ) ;
34
67
35
- obs . complete ( ) ;
36
- } ) ;
37
- } catch {
38
- obs . next ( ) ;
39
- obs . complete ( ) ;
40
- }
41
- } ) ;
68
+ return value ;
42
69
}
43
70
44
71
/**
@@ -54,15 +81,11 @@ export function getNpmPackageJson(
54
81
registryUrl : string | undefined ,
55
82
logger : logging . LoggerApi ,
56
83
) : Observable < Partial < NpmRepositoryPackageJson > > {
57
- const scope = packageName . startsWith ( '@' ) ? packageName . split ( '/' ) [ 0 ] : null ;
84
+ const scope = packageName . startsWith ( '@' ) ? packageName . split ( '/' ) [ 0 ] : undefined ;
58
85
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 )
63
88
) . pipe (
64
- filter ( partialUrl => ! ! partialUrl ) ,
65
- first ( ) ,
66
89
map ( partialUrl => {
67
90
if ( ! partialUrl ) {
68
91
partialUrl = 'https://registry.npmjs.org/' ;
0 commit comments