Skip to content

Commit

Permalink
feat(config): nicer input config input handling
Browse files Browse the repository at this point in the history
  • Loading branch information
zkat committed Mar 15, 2018
1 parent 073869b commit b9ce21d
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 65 deletions.
17 changes: 9 additions & 8 deletions auth.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
'use strict'

const config = require('./config.js')
const url = require('url')

module.exports = getAuth
function getAuth (registry, conf) {
function getAuth (registry, opts) {
if (!registry) { throw new Error('registry is required') }
if (!conf) { conf = new Map() }
opts = config(opts)
let AUTH = {}
const regKey = registry && registryKey(registry)
const doKey = (key, alias) => addKey(conf, AUTH, regKey, key, alias)
const doKey = (key, alias) => addKey(opts, AUTH, regKey, key, alias)
doKey('_authToken', 'token')
doKey('username')
doKey('password')
Expand All @@ -24,12 +25,12 @@ function getAuth (registry, conf) {
return AUTH
}

function addKey (conf, obj, scope, key, objKey) {
if (conf.get(key)) {
obj[objKey || key] = conf.get(key)
function addKey (opts, obj, scope, key, objKey) {
if (opts.get(key)) {
obj[objKey || key] = opts.get(key)
}
if (scope && conf.get(`${scope}:${key}`)) {
obj[objKey || key] = conf.get(`${scope}:${key}`)
if (scope && opts.get(`${scope}:${key}`)) {
obj[objKey || key] = opts.get(`${scope}:${key}`)
}
}

Expand Down
86 changes: 86 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'use strict'

const silentLog = require('./silentlog.js')

const OPTION_TRANSLATIONS = {
'is-from-ci': 'isFromCI',
'max-sockets': 'maxsockets',
'project-scope': 'projectScope',
'npm-session': 'npmSession'
}

const AUTH_REGEX = /^(?:.*:)?(_authToken|username|_password|password|email|always-auth|_auth|otp)$/
const SCOPE_REGISTRY_REGEX = /@.*:registry$/gi
const CONFIGS = new Set([
'agent',
'algorithms',
'body',
'ca',
'cache',
'cert',
'fetch-retries',
'fetch-retry-factor',
'fetch-retry-maxtimeout',
'fetch-retry-mintimeout',
'gid',
'headers',
'integrity',
'is-from-ci',
'key',
'local-address',
'log',
'max-sockets',
'maxsockets',
'memoize',
'method',
'noproxy',
'npm-session',
'offline',
'otp',
'prefer-offline',
'prefer-online',
'project-scope',
'Promise',
'proxy',
'refer',
'registry',
'retry',
'scope',
'spec',
'strict-ssl',
'timeout',
'uid',
'user-agent'
])

class NpmRegistryFetchConfig {
constructor (opts) {
opts = opts || {}
if (opts.opts) {
this.opts = opts.opts
} else if (typeof opts.get === 'function') {
this.opts = {config: opts}
} else {
this.opts = opts
}
this.config = this.opts.config || new Map()
}
get log () { return this.get('log') || silentLog }
get (opt) {
if (!CONFIGS.has(opt) && !opt.match(AUTH_REGEX) && !opt.match(SCOPE_REGISTRY_REGEX)) {
throw new Error(`Invalid config var requested: ${opt}`)
}
const key = OPTION_TRANSLATIONS[opt] || opt
const fromOpts = this.opts[key]
if (fromOpts !== undefined) {
return fromOpts
} else {
return this.config.get(key)
}
}
}

module.exports = config
function config (opts) {
return new NpmRegistryFetchConfig(opts || {})
}
108 changes: 51 additions & 57 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@

const Buffer = require('safe-buffer').Buffer

const getAuth = require('./auth.js')
const checkResponse = require('./check-response.js')
const config = require('./config.js')
const getAuth = require('./auth.js')
const fetch = require('make-fetch-happen')
const npa = require('npm-package-arg')
const silentLog = require('./silentlog.js')
const url = require('url')

module.exports = regFetch
function regFetch (uri, opts) {
opts = Object.assign({
log: silentLog,
config: new Map()
}, opts)
const registry = opts.registry ||
opts.config.get('registry') ||
opts = config(Object.assign({
log: silentLog
}, opts))
const registry = opts.get('registry') ||
'https://registry.npmjs.org/'
uri = url.parse(uri).protocol
? uri
Expand All @@ -27,9 +26,8 @@ function regFetch (uri, opts) {
}`
// through that takes into account the scope, the prefix of `uri`, etc
const startTime = Date.now()
const conf = opts.config
const headers = getHeaders(registry, uri, opts)
let body = opts.body
let body = opts.get('body')
const bodyIsStream = body &&
typeof body === 'object' &&
typeof body.pipe === 'function'
Expand All @@ -40,40 +38,36 @@ function regFetch (uri, opts) {
headers['content-type'] = 'application/octet-stream'
}
return fetch(uri, {
agent: opts.agent,
algorithms: opts.algorithms,
agent: opts.get('agent'),
algorithms: opts.get('algorithms'),
body,
cache: getCacheMode(conf),
cacheManager: conf.get('cache'),
ca: conf.get('ca'),
cert: conf.get('cert'),
cache: getCacheMode(opts),
cacheManager: opts.get('cache'),
ca: opts.get('ca'),
cert: opts.get('cert'),
headers,
integrity: opts.integrity,
key: conf.get('key'),
localAddress: conf.get('local-address'),
maxSockets: conf.get('maxsockets'),
memoize: opts.memoize,
method: opts.method || 'GET',
noProxy: conf.get('noproxy'),
Promise: opts.Promise,
proxy: conf.get('proxy'),
referer: opts.refer || conf.get('refer'),
retry: opts.retry != null
? opts.retry
: {
retries: conf.get('fetch-retries'),
factor: conf.get('fetch-retry-factor'),
minTimeout: conf.get('fetch-retry-mintimeout'),
maxTimeout: conf.get('fetch-retry-maxtimeout')
},
strictSSL: !!conf.get('strict-ssl'),
timeout: opts.timeout != null
? opts.timeout
: conf.get('timeout'),
uid: conf.get('uid'),
gid: conf.get('gid')
integrity: opts.get('integrity'),
key: opts.get('key'),
localAddress: opts.get('local-address'),
maxSockets: opts.get('maxsockets'),
memoize: opts.get('memoize'),
method: opts.get('method') || 'GET',
noProxy: opts.get('noproxy'),
Promise: opts.get('Promise'),
proxy: opts.get('proxy'),
referer: opts.get('refer'),
retry: opts.get('retry') || {
retries: opts.get('fetch-retries'),
factor: opts.get('fetch-retry-factor'),
minTimeout: opts.get('fetch-retry-mintimeout'),
maxTimeout: opts.get('fetch-retry-maxtimeout')
},
strictSSL: !!opts.get('strict-ssl'),
timeout: opts.get('timeout'),
uid: opts.get('uid'),
gid: opts.get('gid')
}).then(res => checkResponse(
opts.method || 'GET', res, registry, startTime, opts
opts.get('method') || 'GET', res, registry, startTime, opts
))
}

Expand All @@ -85,53 +79,53 @@ function fetchJSON (uri, opts) {
module.exports.pickRegistry = pickRegistry
function pickRegistry (spec, opts) {
spec = npa(spec)
const config = (opts && opts.config) || new Map()
opts = config(opts)
if (!spec.registry) {
throw new Error(`${spec} is not a valid registry dependency spec`)
}
let registry = spec.scope &&
config.get(spec.scope.replace(/^@?/, '@') + ':registry')
opts.get(spec.scope.replace(/^@?/, '@') + ':registry')

if (!registry && config.get('scope')) {
registry = config.get(
config.get('scope').replace(/^@?/, '@') + ':registry'
if (!registry && opts.get('scope')) {
registry = opts.get(
opts.get('scope').replace(/^@?/, '@') + ':registry'
)
}

if (!registry) {
registry = config.get('registry') || 'https://registry.npmjs.org/'
registry = opts.get('registry') || 'https://registry.npmjs.org/'
}

return registry
}

function getCacheMode (conf) {
return conf.get('offline')
function getCacheMode (opts) {
return opts.get('offline')
? 'only-if-cached'
: conf.get('prefer-offline')
: opts.get('prefer-offline')
? 'force-cache'
: conf.get('prefer-online')
: opts.get('prefer-online')
? 'no-cache'
: 'default'
}

function getHeaders (registry, uri, opts) {
const headers = Object.assign({
'npm-in-ci': !!(
opts.isFromCI ||
opts.get('is-from-ci') ||
process.env['CI'] === 'true' ||
process.env['TDDIUM'] ||
process.env['JENKINS_URL'] ||
process.env['bamboo.buildKey'] ||
process.env['GO_PIPELINE_NAME']
),
'npm-scope': opts.projectScope,
'npm-session': opts.npmSession,
'user-agent': opts.config.get('user-agent'),
'referer': opts.refer
}, opts.headers)
'npm-scope': opts.get('project-scope'),
'npm-session': opts.get('npm-session'),
'user-agent': opts.get('user-agent'),
'referer': opts.get('refer')
}, opts.get('headers'))

const auth = getAuth(registry, opts.config)
const auth = getAuth(registry, opts)
// If a tarball is hosted on a different place than the manifest, only send
// credentials on `alwaysAuth`
const shouldAuth = (
Expand Down

0 comments on commit b9ce21d

Please sign in to comment.