@@ -47,7 +47,6 @@ const envReplace = require('./env-replace.js')
4747const parseField = require ( './parse-field.js' )
4848const typeDescription = require ( './type-description.js' )
4949const setEnvs = require ( './set-envs.js' )
50- const getUserAgent = require ( './get-user-agent.js' )
5150
5251// types that can be saved back to
5352const confFileTypes = new Set ( [
@@ -69,16 +68,19 @@ const _get = Symbol('get')
6968const _find = Symbol ( 'find' )
7069const _loadObject = Symbol ( 'loadObject' )
7170const _loadFile = Symbol ( 'loadFile' )
71+ const _checkDeprecated = Symbol ( 'checkDeprecated' )
72+ const _flatten = Symbol ( 'flatten' )
73+ const _flatOptions = Symbol ( 'flatOptions' )
7274
7375class Config {
7476 static get typeDefs ( ) {
7577 return typeDefs
7678 }
7779
7880 constructor ( {
79- types ,
81+ definitions ,
8082 shorthands,
81- defaults ,
83+ flatten ,
8284 npmPath,
8385
8486 // options just to override in tests, mostly
@@ -89,10 +91,27 @@ class Config {
8991 execPath = process . execPath ,
9092 cwd = process . cwd ( ) ,
9193 } ) {
92- this . npmPath = npmPath
94+
95+ // turn the definitions into nopt's weirdo syntax
96+ this . definitions = definitions
97+ const types = { }
98+ const defaults = { }
99+ this . deprecated = { }
100+ for ( const [ key , def ] of Object . entries ( definitions ) ) {
101+ defaults [ key ] = def . default
102+ types [ key ] = def . type
103+ if ( def . deprecated )
104+ this . deprecated [ key ] = def . deprecated . trim ( ) . replace ( / \n + / , '\n' )
105+ }
106+
107+ // populated the first time we flatten the object
108+ this [ _flatOptions ] = null
109+ this [ _flatten ] = flatten
93110 this . types = types
94111 this . shorthands = shorthands
95112 this . defaults = defaults
113+
114+ this . npmPath = npmPath
96115 this . log = log
97116 this . argv = argv
98117 this . env = env
@@ -183,10 +202,31 @@ class Config {
183202 if ( ! email )
184203 throw new Error ( 'Cannot set _auth without first setting email' )
185204 }
186- this . data . get ( where ) . data [ key ] = val
205+ this [ _checkDeprecated ] ( key )
206+ const { data } = this . data . get ( where )
207+ data [ key ] = val
187208
188209 // this is now dirty, the next call to this.valid will have to check it
189210 this . data . get ( where ) [ _valid ] = null
211+
212+ // the flat options are invalidated, regenerate next time they're needed
213+ this [ _flatOptions ] = null
214+ }
215+
216+ get flat ( ) {
217+ if ( this [ _flatOptions ] )
218+ return this [ _flatOptions ]
219+
220+ // create the object for flat options passed to deps
221+ process . emit ( 'time' , 'config:load:flatten' )
222+ this [ _flatOptions ] = { }
223+ // walk from least priority to highest
224+ for ( const { data } of this . data . values ( ) ) {
225+ this [ _flatten ] ( data , this [ _flatOptions ] )
226+ }
227+ process . emit ( 'timeEnd' , 'config:load:flatten' )
228+
229+ return this [ _flatOptions ]
190230 }
191231
192232 delete ( key , where = 'cli' ) {
@@ -233,11 +273,6 @@ class Config {
233273 await this . loadGlobalConfig ( )
234274 process . emit ( 'timeEnd' , 'config:load:global' )
235275
236- // now the extras
237- process . emit ( 'time' , 'config:load:cafile' )
238- await this . loadCAFile ( )
239- process . emit ( 'timeEnd' , 'config:load:cafile' )
240-
241276 // warn if anything is not valid
242277 process . emit ( 'time' , 'config:load:validate' )
243278 this . validate ( )
@@ -250,10 +285,6 @@ class Config {
250285 // set proper globalPrefix now that everything is loaded
251286 this . globalPrefix = this . get ( 'prefix' )
252287
253- process . emit ( 'time' , 'config:load:setUserAgent' )
254- this . setUserAgent ( )
255- process . emit ( 'timeEnd' , 'config:load:setUserAgent' )
256-
257288 process . emit ( 'time' , 'config:load:setEnvs' )
258289 this . setEnvs ( )
259290 process . emit ( 'timeEnd' , 'config:load:setEnvs' )
@@ -376,13 +407,13 @@ class Config {
376407 this . data . get ( where ) [ _valid ] = false
377408
378409 if ( Array . isArray ( type ) ) {
379- if ( type . indexOf ( typeDefs . url . type ) !== - 1 )
410+ if ( type . includes ( typeDefs . url . type ) )
380411 type = typeDefs . url . type
381412 else {
382413 /* istanbul ignore if - no actual configs matching this, but
383414 * path types SHOULD be handled this way, like URLs, for the
384415 * same reason */
385- if ( type . indexOf ( typeDefs . path . type ) !== - 1 )
416+ if ( type . includes ( typeDefs . path . type ) )
386417 type = typeDefs . path . type
387418 }
388419 }
@@ -428,11 +459,21 @@ class Config {
428459 for ( const [ key , value ] of Object . entries ( obj ) ) {
429460 const k = envReplace ( key , this . env )
430461 const v = this . parseField ( value , k )
462+ if ( where !== 'default' )
463+ this [ _checkDeprecated ] ( k , where , obj , [ key , value ] )
431464 conf . data [ k ] = v
432465 }
433466 }
434467 }
435468
469+ [ _checkDeprecated ] ( key , where , obj , kv ) {
470+ // XXX a future npm version will make this a warning.
471+ // An even more future npm version will make this an error.
472+ if ( this . deprecated [ key ] ) {
473+ this . log . verbose ( 'config' , key , this . deprecated [ key ] )
474+ }
475+ }
476+
436477 // Parse a field, coercing it to the best type available.
437478 parseField ( f , key , listElement = false ) {
438479 return parseField ( f , key , this , listElement )
@@ -675,48 +716,6 @@ class Config {
675716 return creds
676717 }
677718
678- async loadCAFile ( ) {
679- const where = this [ _find ] ( 'cafile' )
680-
681- /* istanbul ignore if - it'll always be set in the defaults */
682- if ( ! where )
683- return
684-
685- const cafile = this [ _get ] ( 'cafile' , where )
686- const ca = this [ _get ] ( 'ca' , where )
687-
688- // if you have a ca, or cafile is set to null, then nothing to do here.
689- if ( ca || ! cafile )
690- return
691-
692- const raw = await readFile ( cafile , 'utf8' ) . catch ( er => {
693- if ( er . code !== 'ENOENT' )
694- throw er
695- } )
696- if ( ! raw )
697- return
698-
699- const delim = '-----END CERTIFICATE-----'
700- const output = raw . replace ( / \r \n / g, '\n' ) . split ( delim )
701- . filter ( section => section . trim ( ) )
702- . map ( section => section . trimLeft ( ) + delim )
703-
704- // make it non-enumerable so we don't save it back by accident
705- const { data } = this . data . get ( where )
706- Object . defineProperty ( data , 'ca' , {
707- value : output ,
708- enumerable : false ,
709- configurable : true ,
710- writable : true ,
711- } )
712- }
713-
714- // the user-agent configuration is a template that gets populated
715- // with some variables, that takes place here
716- setUserAgent ( ) {
717- this . set ( 'user-agent' , getUserAgent ( this ) )
718- }
719-
720719 // set up the environment object we have with npm_config_* environs
721720 // for all configs that are different from their default values, and
722721 // set EDITOR and HOME.
0 commit comments