6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
import { logging } from '@angular-devkit/core' ;
9
- import { readFileSync } from 'fs' ;
9
+ import { existsSync , readFileSync } from 'fs' ;
10
+ import { homedir } from 'os' ;
11
+ import * as path from 'path' ;
10
12
import { Observable , from } from 'rxjs' ;
11
13
import { shareReplay } from 'rxjs/operators' ;
12
14
import { NpmRepositoryPackageJson } from './npm-package-json' ;
13
15
16
+ const ini = require ( 'ini' ) ;
17
+ const lockfile = require ( '@yarnpkg/lockfile' ) ;
14
18
const pacote = require ( 'pacote' ) ;
15
19
16
20
const npmPackageJsonCache = new Map < string , Observable < NpmRepositoryPackageJson > > ( ) ;
17
-
18
21
let npmrc : { [ key : string ] : string } ;
19
- try {
20
- npmrc = _readNpmRc ( ) ;
21
- } catch {
22
- npmrc = { } ;
23
- }
24
22
25
23
26
- function _readNpmRc ( ) : { [ key : string ] : string } {
24
+ function readOptions ( yarn = false ) : { [ key : string ] : string } {
27
25
// TODO: have a way to read options without using fs directly.
28
- const path = require ( 'path' ) ;
29
- const fs = require ( 'fs' ) ;
30
- const perProjectNpmrc = path . resolve ( '.npmrc' ) ;
26
+ const cwd = process . cwd ( ) ;
27
+ const baseFilename = yarn ? 'yarnrc' : 'npmrc' ;
28
+ const dotFilename = '.' + baseFilename ;
31
29
32
- const configs : string [ ] = [ ] ;
33
-
34
- if ( process . platform === 'win32' ) {
35
- if ( process . env . LOCALAPPDATA ) {
36
- configs . push ( fs . readFileSync ( path . join ( process . env . LOCALAPPDATA , '.npmrc' ) , 'utf8' ) ) ;
37
- }
30
+ let globalPrefix : string ;
31
+ if ( process . env . PREFIX ) {
32
+ globalPrefix = process . env . PREFIX ;
38
33
} else {
39
- if ( process . env . HOME ) {
40
- configs . push ( fs . readFileSync ( path . join ( process . env . HOME , '.npmrc' ) , 'utf8' ) ) ;
34
+ globalPrefix = path . dirname ( process . execPath ) ;
35
+ if ( process . platform !== 'win32' ) {
36
+ globalPrefix = path . dirname ( globalPrefix ) ;
41
37
}
42
38
}
43
39
44
- if ( fs . existsSync ( perProjectNpmrc ) ) {
45
- configs . push ( fs . readFileSync ( perProjectNpmrc , 'utf8' ) ) ;
46
- }
47
-
48
- const allOptions : { [ key : string ] : string } = { } ;
49
- for ( const config of configs ) {
50
- const allOptionsArr = config . split ( / \r ? \n / ) . map ( x => x . trim ( ) ) ;
40
+ const defaultConfigLocations = [
41
+ path . join ( globalPrefix , 'etc' , baseFilename ) ,
42
+ path . join ( homedir ( ) , dotFilename ) ,
43
+ ] ;
51
44
52
- allOptionsArr . forEach ( x => {
53
- const [ key , ...value ] = x . split ( '=' ) ;
54
- const fullValue = value . join ( '=' ) . trim ( ) ;
55
- if ( key && fullValue && fullValue !== 'null' ) {
56
- allOptions [ key . trim ( ) ] = fullValue ;
45
+ const projectConfigLocations : string [ ] = [ ] ;
46
+ const root = path . parse ( cwd ) . root ;
47
+ for ( let curDir = path . dirname ( cwd ) ; curDir && curDir !== root ; curDir = path . dirname ( curDir ) ) {
48
+ projectConfigLocations . unshift ( path . join ( curDir , dotFilename ) ) ;
49
+ }
50
+ projectConfigLocations . push ( path . join ( cwd , dotFilename ) ) ;
51
+
52
+ let options : { [ key : string ] : string } = { } ;
53
+ for ( const location of [ ...defaultConfigLocations , ...projectConfigLocations ] ) {
54
+ if ( existsSync ( location ) ) {
55
+ const data = readFileSync ( location , 'utf8' ) ;
56
+ options = {
57
+ ...options ,
58
+ ...( yarn ? lockfile . parse ( data ) : ini . parse ( data ) ) ,
59
+ } ;
60
+
61
+ if ( options . cafile ) {
62
+ const cafile = path . resolve ( path . dirname ( location ) , options . cafile ) ;
63
+ delete options . cafile ;
64
+ try {
65
+ options . ca = readFileSync ( cafile , 'utf8' ) . replace ( / \r ? \n / , '\\n' ) ;
66
+ } catch { }
57
67
}
58
- } ) ;
59
-
60
- if ( allOptions . cafile ) {
61
- const cafile = allOptions . cafile ;
62
- delete allOptions . cafile ;
63
- try {
64
- allOptions . ca = readFileSync ( cafile , 'utf8' ) ;
65
- allOptions . ca = allOptions . ca . replace ( / \r ? \n / , '\\n' ) ;
66
- } catch { }
67
68
}
68
69
}
69
70
70
- return allOptions ;
71
+ return options ;
71
72
}
72
73
73
74
/**
@@ -82,12 +83,25 @@ export function getNpmPackageJson(
82
83
packageName : string ,
83
84
registryUrl : string | undefined ,
84
85
_logger : logging . LoggerApi ,
86
+ usingYarn = false ,
85
87
) : Observable < Partial < NpmRepositoryPackageJson > > {
86
88
const cachedResponse = npmPackageJsonCache . get ( packageName ) ;
87
89
if ( cachedResponse ) {
88
90
return cachedResponse ;
89
91
}
90
92
93
+ if ( ! npmrc ) {
94
+ try {
95
+ npmrc = readOptions ( ) ;
96
+ } catch { }
97
+
98
+ if ( usingYarn ) {
99
+ try {
100
+ npmrc = { ...npmrc , ...readOptions ( true ) } ;
101
+ } catch { }
102
+ }
103
+ }
104
+
91
105
const resultPromise = pacote . packument (
92
106
packageName ,
93
107
{
0 commit comments