1'use strict' 2 3const fs = require('fs') 4const figgyPudding = require('figgy-pudding') 5const findUp = require('find-up') 6const ini = require('ini') 7const os = require('os') 8const path = require('path') 9 10const NpmConfig = figgyPudding({}, { 11 // Open up the pudding object. 12 other () { return true } 13}) 14 15const ConfigOpts = figgyPudding({ 16 cache: { default: path.join(os.homedir(), '.npm') }, 17 configNames: { default: ['npmrc', '.npmrc'] }, 18 envPrefix: { default: /^npm_config_/i }, 19 cwd: { default: () => process.cwd() }, 20 globalconfig: { 21 default: () => path.join(getGlobalPrefix(), 'etc', 'npmrc') 22 }, 23 userconfig: { default: path.join(os.homedir(), '.npmrc') } 24}) 25 26module.exports.read = getNpmConfig 27function getNpmConfig (_opts, _builtin) { 28 const builtin = ConfigOpts(_builtin) 29 const env = {} 30 for (let key of Object.keys(process.env)) { 31 if (!key.match(builtin.envPrefix)) continue 32 const newKey = key.toLowerCase() 33 .replace(builtin.envPrefix, '') 34 .replace(/(?!^)_/g, '-') 35 env[newKey] = process.env[key] 36 } 37 const cli = NpmConfig(_opts) 38 const userConfPath = ( 39 builtin.userconfig || 40 cli.userconfig || 41 env.userconfig 42 ) 43 const user = userConfPath && maybeReadIni(userConfPath) 44 const globalConfPath = ( 45 builtin.globalconfig || 46 cli.globalconfig || 47 env.globalconfig 48 ) 49 const global = globalConfPath && maybeReadIni(globalConfPath) 50 const projConfPath = findUp.sync(builtin.configNames, { cwd: builtin.cwd }) 51 let proj = {} 52 if (projConfPath && projConfPath !== userConfPath) { 53 proj = maybeReadIni(projConfPath) 54 } 55 const newOpts = NpmConfig(builtin, global, user, proj, env, cli) 56 if (newOpts.cache) { 57 return newOpts.concat({ 58 cache: path.resolve( 59 ( 60 (cli.cache || env.cache) 61 ? builtin.cwd 62 : proj.cache 63 ? path.dirname(projConfPath) 64 : user.cache 65 ? path.dirname(userConfPath) 66 : global.cache 67 ? path.dirname(globalConfPath) 68 : path.dirname(userConfPath) 69 ), 70 newOpts.cache 71 ) 72 }) 73 } else { 74 return newOpts 75 } 76} 77 78function maybeReadIni (f) { 79 let txt 80 try { 81 txt = fs.readFileSync(f, 'utf8') 82 } catch (err) { 83 if (err.code === 'ENOENT') { 84 return '' 85 } else { 86 throw err 87 } 88 } 89 return ini.parse(txt) 90} 91 92function getGlobalPrefix () { 93 if (process.env.PREFIX) { 94 return process.env.PREFIX 95 } else if (process.platform === 'win32') { 96 // c:\node\node.exe --> prefix=c:\node\ 97 return path.dirname(process.execPath) 98 } else { 99 // /usr/local/bin/node --> prefix=/usr/local 100 let pref = path.dirname(path.dirname(process.execPath)) 101 // destdir only is respected on Unix 102 if (process.env.DESTDIR) { 103 pref = path.join(process.env.DESTDIR, pref) 104 } 105 return pref 106 } 107} 108