• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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