@@ -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