@@ -9,7 +9,16 @@ 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 , 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' ;
1322import * as url from 'url' ;
1423import { NpmRepositoryPackageJson } from './npm-package-json' ;
1524
@@ -18,6 +27,69 @@ const RegistryClient = require('npm-registry-client');
1827const npmPackageJsonCache = new Map < string , Observable < NpmRepositoryPackageJson > > ( ) ;
1928const npmConfigOptionCache = new Map < string , Observable < string | undefined > > ( ) ;
2029
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+
2193function getNpmConfigOption (
2294 option : string ,
2395 scope ?: string ,
@@ -41,29 +113,10 @@ function getNpmConfigOption(
41113 return value ;
42114 }
43115
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 ) ;
65119
66- value = subject . asObservable ( ) ;
67120 npmConfigOptionCache . set ( fullOption , value ) ;
68121
69122 return value ;
0 commit comments