'use strict'; const fs = require('fs'); const path = require('path'); const ConfigChain = require('config-chain').ConfigChain; const util = require('./util'); class Conf extends ConfigChain { // https://github.com/npm/npm/blob/latest/lib/config/core.js#L208-L222 constructor(base) { super(base); this.root = base; } // https://github.com/npm/npm/blob/latest/lib/config/core.js#L332-L342 add(data, marker) { try { for (const x of Object.keys(data)) { data[x] = util.parseField(data[x], x); } } catch (err) { throw err; } return super.add(data, marker); } // https://github.com/npm/npm/blob/latest/lib/config/core.js#L312-L325 addFile(file, name) { name = name || file; const marker = {__source__: name}; this.sources[name] = {path: file, type: 'ini'}; this.push(marker); this._await(); try { const contents = fs.readFileSync(file, 'utf8'); this.addString(contents, file, 'ini', marker); } catch (err) { this.add({}, marker); } return this; } // https://github.com/npm/npm/blob/latest/lib/config/core.js#L344-L360 addEnv(env) { env = env || process.env; const conf = {}; Object.keys(env) .filter(x => /^npm_config_/i.test(x)) .forEach(x => { if (!env[x]) { return; } const p = x.toLowerCase() .replace(/^npm_config_/, '') .replace(/(?!^)_/g, '-'); conf[p] = env[x]; }); return super.addEnv('', conf, 'env'); } // https://github.com/npm/npm/blob/latest/lib/config/load-prefix.js loadPrefix() { const cli = this.list[0]; Object.defineProperty(this, 'prefix', { enumerable: true, set: prefix => { const g = this.get('global'); this[g ? 'globalPrefix' : 'localPrefix'] = prefix; }, get: () => { const g = this.get('global'); return g ? this.globalPrefix : this.localPrefix; } }); Object.defineProperty(this, 'globalPrefix', { enumerable: true, set: prefix => { this.set('prefix', prefix); }, get: () => { return path.resolve(this.get('prefix')); } }); let p; Object.defineProperty(this, 'localPrefix', { enumerable: true, set: prefix => { p = prefix; }, get: () => { return p; } }); if (Object.prototype.hasOwnProperty.call(cli, 'prefix')) { p = path.resolve(cli.prefix); } else { try { const prefix = util.findPrefix(process.cwd()); p = prefix; } catch (err) { throw err; } } return p; } // https://github.com/npm/npm/blob/latest/lib/config/load-cafile.js loadCAFile(file) { if (!file) { return; } try { const contents = fs.readFileSync(file, 'utf8'); const delim = '-----END CERTIFICATE-----'; const output = contents .split(delim) .filter(x => Boolean(x.trim())) .map(x => x.trimLeft() + delim); this.set('ca', output); } catch (err) { if (err.code === 'ENOENT') { return; } throw err; } } // https://github.com/npm/npm/blob/latest/lib/config/set-user.js loadUser() { const defConf = this.root; if (this.get('global')) { return; } if (process.env.SUDO_UID) { defConf.user = Number(process.env.SUDO_UID); return; } const prefix = path.resolve(this.get('prefix')); try { const stats = fs.statSync(prefix); defConf.user = stats.uid; } catch (err) { if (err.code === 'ENOENT') { return; } throw err; } } } module.exports = Conf;