@@ -9,7 +9,16 @@ 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 , defaultIfEmpty , filter , first , map , toArray } from 'rxjs/operators' ;
12
+ import {
13
+ catchError ,
14
+ concatMap ,
15
+ defaultIfEmpty ,
16
+ filter ,
17
+ first ,
18
+ map ,
19
+ shareReplay ,
20
+ toArray ,
21
+ } from 'rxjs/operators' ;
13
22
import * as url from 'url' ;
14
23
import { NpmRepositoryPackageJson } from './npm-package-json' ;
15
24
@@ -18,6 +27,69 @@ const RegistryClient = require('npm-registry-client');
18
27
const npmPackageJsonCache = new Map < string , Observable < NpmRepositoryPackageJson > > ( ) ;
19
28
const npmConfigOptionCache = new Map < string , Observable < string | undefined > > ( ) ;
20
29
30
+
31
+ function _readNpmRc ( ) : Observable < { [ key : string ] : string } > {
32
+ return new Observable < { [ key : string ] : string } > ( subject => {
33
+ // TODO: have a way to read options without using fs directly.
34
+ const path = require ( 'path' ) ;
35
+ const fs = require ( 'fs' ) ;
36
+
37
+ let npmrc = '' ;
38
+ if ( process . platform === 'win32' ) {
39
+ if ( process . env . LOCALAPPDATA ) {
40
+ npmrc = fs . readFileSync ( path . join ( process . env . LOCALAPPDATA , '.npmrc' ) ) . toString ( 'utf-8' ) ;
41
+ }
42
+ } else {
43
+ if ( process . env . HOME ) {
44
+ npmrc = fs . readFileSync ( path . join ( process . env . HOME , '.npmrc' ) ) . toString ( 'utf-8' ) ;
45
+ }
46
+ }
47
+
48
+ const allOptionsArr = npmrc . split ( / \r ? \n / ) . map ( x => x . trim ( ) ) ;
49
+ const allOptions : { [ key : string ] : string } = { } ;
50
+
51
+ allOptionsArr . forEach ( x => {
52
+ const [ key , ...value ] = x . split ( '=' ) ;
53
+ allOptions [ key ] = value . join ( '=' ) ;
54
+ } ) ;
55
+
56
+ subject . next ( allOptions ) ;
57
+ subject . complete ( ) ;
58
+ } ) . pipe (
59
+ catchError ( ( ) => of ( { } ) ) ,
60
+ shareReplay ( ) ,
61
+ ) ;
62
+ }
63
+
64
+
65
+ function getOptionFromNpmRc ( option : string ) : Observable < string | undefined > {
66
+ return _readNpmRc ( ) . pipe (
67
+ map ( options => options [ option ] ) ,
68
+ ) ;
69
+ }
70
+
71
+ function getOptionFromNpmCli ( option : string ) : Observable < string | undefined > {
72
+ return new Observable < string | undefined > ( subject => {
73
+ exec ( `npm get ${ option } ` , ( error , data ) => {
74
+ if ( error ) {
75
+ throw error ;
76
+ } else {
77
+ data = data . trim ( ) ;
78
+ if ( ! data || data === 'undefined' || data === 'null' ) {
79
+ subject . next ( ) ;
80
+ } else {
81
+ subject . next ( data ) ;
82
+ }
83
+ }
84
+
85
+ subject . complete ( ) ;
86
+ } ) ;
87
+ } ) . pipe (
88
+ catchError ( ( ) => of ( ) ) ,
89
+ shareReplay ( ) ,
90
+ ) ;
91
+ }
92
+
21
93
function getNpmConfigOption (
22
94
option : string ,
23
95
scope ?: string ,
@@ -41,29 +113,10 @@ function getNpmConfigOption(
41
113
return value ;
42
114
}
43
115
44
- const subject = new ReplaySubject < string | undefined > ( 1 ) ;
45
-
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 ( ) ;
54
- } else {
55
- subject . next ( data ) ;
56
- }
57
- }
58
-
59
- subject . complete ( ) ;
60
- } ) ;
61
- } catch {
62
- subject . next ( ) ;
63
- subject . complete ( ) ;
64
- }
116
+ value = option . startsWith ( '_' )
117
+ ? getOptionFromNpmRc ( fullOption )
118
+ : getOptionFromNpmCli ( fullOption ) ;
65
119
66
- value = subject . asObservable ( ) ;
67
120
npmConfigOptionCache . set ( fullOption , value ) ;
68
121
69
122
return value ;
0 commit comments