Skip to content

Commit

Permalink
update lib/*.js to use new config structures
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Mar 18, 2021
1 parent f52c51d commit 7c89e74
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 80 deletions.
8 changes: 4 additions & 4 deletions bin/npx-cli.js
Expand Up @@ -24,11 +24,11 @@ const removed = new Set([
...removedOpts
])

const { types, shorthands } = require('../lib/utils/config.js')
const npmSwitches = Object.entries(types)
.filter(([key, type]) => type === Boolean ||
const { definitions, shorthands } = require('../lib/utils/config/index.js')
const npmSwitches = Object.entries(definitions)
.filter(([key, {type}]) => type === Boolean ||
(Array.isArray(type) && type.includes(Boolean)))
.map(([key, type]) => key)
.map(([key]) => key)

// things that don't take a value
const switches = new Set([
Expand Down
10 changes: 7 additions & 3 deletions lib/completion.js
Expand Up @@ -29,13 +29,13 @@
// as an array.
//

const { types, shorthands } = require('./utils/config.js')
const { definitions, shorthands } = require('./utils/config/index.js')
const deref = require('./utils/deref-command.js')
const { aliases, cmdList, plumbing } = require('./utils/cmd-list.js')
const aliasNames = Object.keys(aliases)
const fullList = cmdList.concat(aliasNames).filter(c => !plumbing.includes(c))
const nopt = require('nopt')
const configNames = Object.keys(types)
const configNames = Object.keys(definitions)
const shorthandNames = Object.keys(shorthands)
const allConfs = configNames.concat(shorthandNames)
const isWindowsShell = require('./utils/is-windows-shell.js')
Expand Down Expand Up @@ -147,6 +147,10 @@ class Completion extends BaseCommand {
// take a little shortcut and use npm's arg parsing logic.
// don't have to worry about the last arg being implicitly
// boolean'ed, since the last block will catch that.
const types = Object.entries(definitions).reduce((types, [key, def]) => {
types[key] = def.type
return types
}, {})
const parsed = opts.conf =
nopt(types, shorthands, partialWords.slice(0, -1), 0)
// check if there's a command already.
Expand Down Expand Up @@ -256,7 +260,7 @@ const isFlag = word => {
const split = word.match(/^(-*)((?:no-)+)?(.*)$/)
const no = split[2]
const conf = split[3]
const type = types[conf]
const {type} = definitions[conf]
return no ||
type === Boolean ||
(Array.isArray(type) && type.includes(Boolean)) ||
Expand Down
19 changes: 11 additions & 8 deletions lib/config.js
@@ -1,4 +1,5 @@
const { defaults, types } = require('./utils/config.js')
// don't expand so that we only assemble the set of defaults when needed
const configDefs = require('./utils/config/index.js')

const mkdirp = require('mkdirp-infer-owner')
const { dirname } = require('path')
Expand Down Expand Up @@ -70,7 +71,7 @@ class Config extends BaseCommand {
case 'get':
case 'delete':
case 'rm':
return Object.keys(types)
return Object.keys(configDefs.definitions)
case 'edit':
case 'list':
case 'ls':
Expand Down Expand Up @@ -100,7 +101,7 @@ class Config extends BaseCommand {
break
case 'list':
case 'ls':
await (this.npm.flatOptions.json ? this.listJson() : this.list())
await (this.npm.config.get('json') ? this.listJson() : this.list())
break
case 'edit':
await this.edit()
Expand All @@ -117,7 +118,7 @@ class Config extends BaseCommand {
if (!args.length)
throw this.usageError()

const where = this.npm.flatOptions.global ? 'global' : 'user'
const where = this.npm.config.get('global') ? 'global' : 'user'
for (const [key, val] of Object.entries(keyValues(args))) {
this.npm.log.info('config', 'set %j %j', key, val)
this.npm.config.set(key, val || '', where)
Expand Down Expand Up @@ -147,14 +148,15 @@ class Config extends BaseCommand {
if (!keys.length)
throw this.usageError()

const where = this.npm.flatOptions.global ? 'global' : 'user'
const where = this.npm.config.get('global') ? 'global' : 'user'
for (const key of keys)
this.npm.config.delete(key, where)
await this.npm.config.save(where)
}

async edit () {
const { editor: e, global } = this.npm.flatOptions
const global = this.npm.config.get('global')
const e = this.npm.config.get('editor')
const where = global ? 'global' : 'user'
const file = this.npm.config.data.get(where).source

Expand All @@ -165,7 +167,8 @@ class Config extends BaseCommand {
const data = (
await readFile(file, 'utf8').catch(() => '')
).replace(/\r\n/g, '\n')
const defData = Object.entries(defaults).reduce((str, [key, val]) => {
const entries = Object.entries(configDefs.defaults)
const defData = entries.reduce((str, [key, val]) => {
const obj = { [key]: val }
const i = ini.stringify(obj)
.replace(/\r\n/g, '\n') // normalizes output from ini.stringify
Expand Down Expand Up @@ -210,7 +213,7 @@ ${defData}

async list () {
const msg = []
const { long } = this.npm.flatOptions
const long = this.npm.config.get('long')
for (const [where, { data, source }] of this.npm.config.data.entries()) {
if (where === 'default' && !long)
continue
Expand Down
2 changes: 1 addition & 1 deletion lib/doctor.js
Expand Up @@ -11,7 +11,7 @@ const { promisify } = require('util')
const ansiTrim = require('./utils/ansi-trim.js')
const isWindows = require('./utils/is-windows.js')
const ping = require('./utils/ping.js')
const { defaults: { registry: defaultRegistry } } = require('./utils/config.js')
const { registry: { default: defaultRegistry } } = require('./utils/config/definitions.js')
const lstat = promisify(fs.lstat)
const readdir = promisify(fs.readdir)
const access = promisify(fs.access)
Expand Down
38 changes: 19 additions & 19 deletions lib/npm.js
Expand Up @@ -36,24 +36,18 @@ const proxyCmds = new Proxy({}, {
},
})

const { types, defaults, shorthands } = require('./utils/config.js')
const { definitions, flatten, shorthands } = require('./utils/config/index.js')
const { shellouts } = require('./utils/cmd-list.js')

let warnedNonDashArg = false
const _runCmd = Symbol('_runCmd')
const _load = Symbol('_load')
const _flatOptions = Symbol('_flatOptions')
const _tmpFolder = Symbol('_tmpFolder')
const _title = Symbol('_title')
const npm = module.exports = new class extends EventEmitter {
constructor () {
super()
require('./utils/perf.js')
this.modes = {
exec: 0o755,
file: 0o644,
umask: 0o22,
}
this.started = Date.now()
this.command = null
this.commands = proxyCmds
Expand All @@ -62,8 +56,8 @@ const npm = module.exports = new class extends EventEmitter {
this.version = require('../package.json').version
this.config = new Config({
npmPath: dirname(__dirname),
types,
defaults,
definitions,
flatten,
shorthands,
})
this[_title] = process.title
Expand Down Expand Up @@ -140,9 +134,6 @@ const npm = module.exports = new class extends EventEmitter {
if (!er && this.config.get('force'))
this.log.warn('using --force', 'Recommended protections disabled.')

if (!er && !this[_flatOptions])
this[_flatOptions] = require('./utils/flat-options.js')(this)

process.emit('timeEnd', 'npm:load')
this.emit('load', er)
})
Expand All @@ -162,48 +153,57 @@ const npm = module.exports = new class extends EventEmitter {
}

async [_load] () {
process.emit('time', 'npm:load:whichnode')
const node = await which(process.argv[0]).catch(er => null)
process.emit('timeEnd', 'npm:load:whichnode')
if (node && node.toUpperCase() !== process.execPath.toUpperCase()) {
log.verbose('node symlink', node)
process.execPath = node
this.config.execPath = node
}

process.emit('time', 'npm:load:configload')
await this.config.load()
process.emit('timeEnd', 'npm:load:configload')

this.argv = this.config.parsedArgv.remain
// note: this MUST be shorter than the actual argv length, because it
// uses the same memory, so node will truncate it if it's too long.
// if it's a token revocation, then the argv contains a secret, so
// don't show that. (Regrettable historical choice to put it there.)
// Any other secrets are configs only, so showing only the positional
// args keeps those from being leaked.
process.emit('time', 'npm:load:setTitle')
const tokrev = deref(this.argv[0]) === 'token' && this.argv[1] === 'revoke'
this.title = tokrev ? 'npm token revoke' + (this.argv[2] ? ' ***' : '')
: ['npm', ...this.argv].join(' ')
process.emit('timeEnd', 'npm:load:setTitle')

process.emit('time', 'npm:load:setupLog')
this.color = setupLog(this.config)
process.emit('timeEnd', 'npm:load:setupLog')
process.env.COLOR = this.color ? '1' : '0'

process.emit('time', 'npm:load:cleanupLog')
cleanUpLogFiles(this.cache, this.config.get('logs-max'), log.warn)
process.emit('timeEnd', 'npm:load:cleanupLog')

log.resume()
const umask = this.config.get('umask')
this.modes = {
exec: 0o777 & (~umask),
file: 0o666 & (~umask),
umask,
}

process.emit('time', 'npm:load:configScope')
const configScope = this.config.get('scope')
if (configScope && !/^@/.test(configScope))
this.config.set('scope', `@${configScope}`, this.config.find('scope'))
process.emit('timeEnd', 'npm:load:configScope')

process.emit('time', 'npm:load:projectScope')
this.projectScope = this.config.get('scope') ||
getProjectScope(this.prefix)
process.emit('timeEnd', 'npm:load:projectScope')
}

get flatOptions () {
return this[_flatOptions]
return this.config.flat
}

get lockfileVersion () {
Expand Down
5 changes: 3 additions & 2 deletions lib/publish.js
Expand Up @@ -8,7 +8,7 @@ const pacote = require('pacote')
const npa = require('npm-package-arg')
const npmFetch = require('npm-registry-fetch')

const { flatten } = require('./utils/flat-options.js')
const flatten = require('./utils/config/flatten.js')
const otplease = require('./utils/otplease.js')
const { getContents, logTar } = require('./utils/tar.js')

Expand Down Expand Up @@ -141,7 +141,8 @@ class Publish extends BaseCommand {
publishConfigToOpts (publishConfig) {
// create a new object that inherits from the config stack
// then squash the css-case into camelCase opts, like we do
return flatten({...flatten(this.npm.config.list[0]), ...publishConfig})
// this is Object.assign()'ed onto the base npm.flatOptions
return flatten(publishConfig, {})
}
}
module.exports = Publish
13 changes: 8 additions & 5 deletions test/lib/completion.js
Expand Up @@ -63,11 +63,14 @@ const cmdList = {
plumbing: [],
}

// only include a subset so that the snapshots aren't huge and
// don't change when we add/remove config definitions.
const definitions = require('../../lib/utils/config/definitions.js')
const config = {
types: {
global: Boolean,
browser: [null, Boolean, String],
registry: [null, String],
definitions: {
global: definitions.global,
browser: definitions.browser,
registry: definitions.registry,
},
shorthands: {
reg: ['--registry'],
Expand All @@ -80,7 +83,7 @@ const deref = (cmd) => {

const Completion = requireInject('../../lib/completion.js', {
'../../lib/utils/cmd-list.js': cmdList,
'../../lib/utils/config.js': config,
'../../lib/utils/config/index.js': config,
'../../lib/utils/deref-command.js': deref,
'../../lib/utils/is-windows-shell.js': false,
})
Expand Down

0 comments on commit 7c89e74

Please sign in to comment.