@@ -16,7 +16,9 @@ const lockfile = require('@yarnpkg/lockfile');
1616const ini = require ( 'ini' ) ;
1717const pacote = require ( 'pacote' ) ;
1818
19- type PackageManagerOptions = Record < string , unknown > ;
19+ interface PackageManagerOptions extends Record < string , unknown > {
20+ forceAuth ?: Record < string , unknown > ;
21+ }
2022
2123const npmPackageJsonCache = new Map < string , Promise < Partial < NpmRepositoryPackageJson > > > ( ) ;
2224let npmrc : PackageManagerOptions ;
@@ -41,8 +43,8 @@ function readOptions(
4143 }
4244
4345 const defaultConfigLocations = [
44- path . join ( globalPrefix , 'etc' , baseFilename ) ,
45- path . join ( homedir ( ) , dotFilename ) ,
46+ ( ! yarn && process . env . NPM_CONFIG_GLOBALCONFIG ) || path . join ( globalPrefix , 'etc' , baseFilename ) ,
47+ ( ! yarn && process . env . NPM_CONFIG_USERCONFIG ) || path . join ( homedir ( ) , dotFilename ) ,
4648 ] ;
4749
4850 const projectConfigLocations : string [ ] = [ path . join ( cwd , dotFilename ) ] ;
@@ -67,47 +69,57 @@ function readOptions(
6769 // See: https://github.com/npm/npm-registry-fetch/blob/ebddbe78a5f67118c1f7af2e02c8a22bcaf9e850/index.js#L99-L126
6870 const rcConfig : PackageManagerOptions = yarn ? lockfile . parse ( data ) : ini . parse ( data ) ;
6971 for ( const [ key , value ] of Object . entries ( rcConfig ) ) {
72+ let substitutedValue = value ;
73+
74+ // Substitute any environment variable references.
75+ if ( typeof value === 'string' ) {
76+ substitutedValue = value . replace ( / \$ \{ ( [ ^ \} ] + ) \} / , ( _ , name ) => process . env [ name ] || '' ) ;
77+ }
78+
7079 switch ( key ) {
80+ // Unless auth options are scope with the registry url it appears that npm-registry-fetch ignores them,
81+ // even though they are documented.
82+ // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/README.md
83+ // https://github.com/npm/npm-registry-fetch/blob/8954f61d8d703e5eb7f3d93c9b40488f8b1b62ac/auth.js#L45-L91
84+ case '_authToken' :
85+ case 'token' :
86+ case 'username' :
87+ case 'password' :
88+ case '_auth' :
89+ case 'auth' :
90+ options [ 'forceAuth' ] ??= { } ;
91+ options [ 'forceAuth' ] [ key ] = substitutedValue ;
92+ break ;
7193 case 'noproxy' :
7294 case 'no-proxy' :
73- options [ 'noProxy' ] = value ;
95+ options [ 'noProxy' ] = substitutedValue ;
7496 break ;
7597 case 'maxsockets' :
76- options [ 'maxSockets' ] = value ;
98+ options [ 'maxSockets' ] = substitutedValue ;
7799 break ;
78100 case 'https-proxy' :
79101 case 'proxy' :
80- options [ 'proxy' ] = value ;
102+ options [ 'proxy' ] = substitutedValue ;
81103 break ;
82104 case 'strict-ssl' :
83- options [ 'strictSSL' ] = value ;
105+ options [ 'strictSSL' ] = substitutedValue ;
84106 break ;
85107 case 'local-address' :
86- options [ 'localAddress' ] = value ;
108+ options [ 'localAddress' ] = substitutedValue ;
87109 break ;
88110 case 'cafile' :
89- if ( typeof value === 'string' ) {
90- const cafile = path . resolve ( path . dirname ( location ) , value ) ;
111+ if ( typeof substitutedValue === 'string' ) {
112+ const cafile = path . resolve ( path . dirname ( location ) , substitutedValue ) ;
91113 try {
92114 options [ 'ca' ] = readFileSync ( cafile , 'utf8' ) . replace ( / \r ? \n / g, '\n' ) ;
93115 } catch { }
94116 }
95117 break ;
96118 default :
97- options [ key ] = value ;
119+ options [ key ] = substitutedValue ;
98120 break ;
99121 }
100122 }
101- } else if ( showPotentials ) {
102- logger . info ( `Trying '${ location } '...not found.` ) ;
103- }
104- }
105-
106- // Substitute any environment variable references
107- for ( const key in options ) {
108- const value = options [ key ] ;
109- if ( typeof value === 'string' ) {
110- options [ key ] = value . replace ( / \$ \{ ( [ ^ \} ] + ) \} / , ( _ , name ) => process . env [ name ] || '' ) ;
111123 }
112124 }
113125
0 commit comments