@@ -9,37 +9,64 @@ import { logging } from '@angular-devkit/core';
9
9
import { exec } from 'child_process' ;
10
10
import { readFileSync } from 'fs' ;
11
11
import { 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' ;
13
13
import * as url from 'url' ;
14
14
import { NpmRepositoryPackageJson } from './npm-package-json' ;
15
15
16
16
const RegistryClient = require ( 'npm-registry-client' ) ;
17
17
18
18
const 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
+ }
19
43
44
+ const subject = new ReplaySubject < string | undefined > ( 1 ) ;
20
45
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 ( ) ;
27
54
} 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 ) ;
34
56
}
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 ) ;
35
68
36
- obs . complete ( ) ;
37
- } ) ;
38
- } catch {
39
- obs . next ( ) ;
40
- obs . complete ( ) ;
41
- }
42
- } ) ;
69
+ return value ;
43
70
}
44
71
45
72
function getNpmClientSslOptions ( strictSsl ?: string , cafile ?: string ) {
@@ -71,15 +98,11 @@ export function getNpmPackageJson(
71
98
registryUrl : string | undefined ,
72
99
logger : logging . LoggerApi ,
73
100
) : Observable < Partial < NpmRepositoryPackageJson > > {
74
- const scope = packageName . startsWith ( '@' ) ? packageName . split ( '/' ) [ 0 ] : null ;
101
+ const scope = packageName . startsWith ( '@' ) ? packageName . split ( '/' ) [ 0 ] : undefined ;
75
102
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 )
80
105
) . pipe (
81
- filter ( partialUrl => ! ! partialUrl ) ,
82
- first ( ) ,
83
106
map ( partialUrl => {
84
107
if ( ! partialUrl ) {
85
108
partialUrl = 'https://registry.npmjs.org/' ;
0 commit comments