| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 | /* eslint-disable standard/no-callback-literal */module.exports = configvar log = require('npmlog')var npm = require('./npm.js')var npmconf = require('./config/core.js')var fs = require('graceful-fs')var writeFileAtomic = require('write-file-atomic')var types = npmconf.defs.typesvar ini = require('ini')var editor = require('editor')var os = require('os')var path = require('path')var mkdirp = require('gentle-fs').mkdirvar umask = require('./utils/umask')var usage = require('./utils/usage')var output = require('./utils/output')var noProgressTillDone = require('./utils/no-progress-while-running').tillDoneconfig.usage = usage(  'config',  'npm config set <key> <value>' +  '\nnpm config get [<key>]' +  '\nnpm config delete <key>' +  '\nnpm config list [--json]' +  '\nnpm config edit' +  '\nnpm set <key> <value>' +  '\nnpm get [<key>]')config.completion = function (opts, cb) {  var argv = opts.conf.argv.remain  if (argv[1] !== 'config') argv.unshift('config')  if (argv.length === 2) {    var cmds = ['get', 'set', 'delete', 'ls', 'rm', 'edit']    if (opts.partialWord !== 'l') cmds.push('list')    return cb(null, cmds)  }  var action = argv[2]  switch (action) {    case 'set':      // todo: complete with valid values, if possible.      if (argv.length > 3) return cb(null, [])      // fallthrough      /* eslint no-fallthrough:0 */    case 'get':    case 'delete':    case 'rm':      return cb(null, Object.keys(types))    case 'edit':    case 'list':    case 'ls':      return cb(null, [])    default:      return cb(null, [])  }}// npm config set key value// npm config get key// npm config listfunction config (args, cb) {  var action = args.shift()  switch (action) {    case 'set':      return set(args[0], args[1], cb)    case 'get':      return get(args[0], cb)    case 'delete':    case 'rm':    case 'del':      return del(args[0], cb)    case 'list':    case 'ls':      return npm.config.get('json') ? listJson(cb) : list(cb)    case 'edit':      return edit(cb)    default:      return unknown(action, cb)  }}function edit (cb) {  var e = npm.config.get('editor')  var which = npm.config.get('global') ? 'global' : 'user'  var f = npm.config.get(which + 'config')  if (!e) return cb(new Error('No EDITOR config or environ set.'))  npm.config.save(which, function (er) {    if (er) return cb(er)    fs.readFile(f, 'utf8', function (er, data) {      if (er) data = ''      data = [        ';;;;',        '; npm ' + (npm.config.get('global')          ? 'globalconfig' : 'userconfig') + ' file',        '; this is a simple ini-formatted file',        '; lines that start with semi-colons are comments.',        '; read `npm help config` for help on the various options',        ';;;;',        '',        data      ].concat([        ';;;;',        '; all options with default values',        ';;;;'      ]).concat(Object.keys(npmconf.defaults).reduce(function (arr, key) {        var obj = {}        obj[key] = npmconf.defaults[key]        if (key === 'logstream') return arr        return arr.concat(          ini.stringify(obj)            .replace(/\n$/m, '')            .replace(/^/g, '; ')            .replace(/\n/g, '\n; ')            .split('\n'))      }, []))        .concat([''])        .join(os.EOL)      mkdirp(path.dirname(f), function (er) {        if (er) return cb(er)        writeFileAtomic(          f,          data,          function (er) {            if (er) return cb(er)            editor(f, { editor: e }, noProgressTillDone(cb))          }        )      })    })  })}function del (key, cb) {  if (!key) return cb(new Error('no key provided'))  var where = npm.config.get('global') ? 'global' : 'user'  npm.config.del(key, where)  npm.config.save(where, cb)}function set (key, val, cb) {  if (key === undefined) {    return unknown('', cb)  }  if (val === undefined) {    if (key.indexOf('=') !== -1) {      var k = key.split('=')      key = k.shift()      val = k.join('=')    } else {      val = ''    }  }  key = key.trim()  val = val.trim()  log.info('config', 'set %j %j', key, val)  var where = npm.config.get('global') ? 'global' : 'user'  if (key.match(/umask/)) val = umask.fromString(val)  npm.config.set(key, val, where)  npm.config.save(where, cb)}function get (key, cb) {  if (!key) return list(cb)  if (!publicVar(key)) {    return cb(new Error('---sekretz---'))  }  var val = npm.config.get(key)  if (key.match(/umask/)) val = umask.toString(val)  output(val)  cb()}function sort (a, b) {  return a > b ? 1 : -1}function publicVar (k) {  return !(k.charAt(0) === '_' || k.indexOf(':_') !== -1)}function getKeys (data) {  return Object.keys(data).filter(publicVar).sort(sort)}function listJson (cb) {  const publicConf = npm.config.keys.reduce((publicConf, k) => {    var value = npm.config.get(k)    if (publicVar(k) &&        // argv is not really config, it's command config        k !== 'argv' &&        // logstream is a Stream, and would otherwise produce circular refs        k !== 'logstream') publicConf[k] = value    return publicConf  }, {})  output(JSON.stringify(publicConf, null, 2))  return cb()}function listFromSource (title, conf, long) {  var confKeys = getKeys(conf)  var msg = ''  if (confKeys.length) {    msg += '; ' + title + '\n'    confKeys.forEach(function (k) {      var val = JSON.stringify(conf[k])      if (conf[k] !== npm.config.get(k)) {        if (!long) return        msg += '; ' + k + ' = ' + val + ' (overridden)\n'      } else msg += k + ' = ' + val + '\n'    })    msg += '\n'  }  return msg}function list (cb) {  var msg = ''  var long = npm.config.get('long')  var cli = npm.config.sources.cli.data  var cliKeys = getKeys(cli)  if (cliKeys.length) {    msg += '; cli configs\n'    cliKeys.forEach(function (k) {      if (cli[k] && typeof cli[k] === 'object') return      if (k === 'argv') return      msg += k + ' = ' + JSON.stringify(cli[k]) + '\n'    })    msg += '\n'  }  // env configs  msg += listFromSource('environment configs', npm.config.sources.env.data, long)  // project config file  var project = npm.config.sources.project  msg += listFromSource('project config ' + project.path, project.data, long)  // user config file  msg += listFromSource('userconfig ' + npm.config.get('userconfig'), npm.config.sources.user.data, long)  // global config file  msg += listFromSource('globalconfig ' + npm.config.get('globalconfig'), npm.config.sources.global.data, long)  // builtin config file  var builtin = npm.config.sources.builtin || {}  if (builtin && builtin.data) {    msg += listFromSource('builtin config ' + builtin.path, builtin.data, long)  }  // only show defaults if --long  if (!long) {    msg += '; node bin location = ' + process.execPath + '\n' +           '; cwd = ' + process.cwd() + '\n' +           '; HOME = ' + process.env.HOME + '\n' +           '; "npm config ls -l" to show all defaults.\n'    output(msg)    return cb()  }  var defaults = npmconf.defaults  var defKeys = getKeys(defaults)  msg += '; default values\n'  defKeys.forEach(function (k) {    if (defaults[k] && typeof defaults[k] === 'object') return    var val = JSON.stringify(defaults[k])    if (defaults[k] !== npm.config.get(k)) {      msg += '; ' + k + ' = ' + val + ' (overridden)\n'    } else msg += k + ' = ' + val + '\n'  })  msg += '\n'  output(msg)  return cb()}function unknown (action, cb) {  cb('Usage:\n' + config.usage)}
 |