Skip to content

Commit

Permalink
tests for main npm module
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Jul 17, 2020
1 parent 5b61bc0 commit 1b00d17
Show file tree
Hide file tree
Showing 2 changed files with 371 additions and 40 deletions.
82 changes: 42 additions & 40 deletions lib/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

// these are all dependencies used in the ctor
const EventEmitter = require('events')
const perf = require('./utils/perf.js')
const { resolve } = require('path')
const parseJSON = require('json-parse-even-better-errors')
const rimraf = require('rimraf')
Expand Down Expand Up @@ -42,55 +41,53 @@ const proxyCmds = (npm) => {
if (cmds[actual]) {
return cmds[cmd] = cmds[actual]
}
const impl = require(`./${actual}.js`)
const fn = (args, cb) => npm[_runCmd](cmd, actual, impl, args, cb)
Object.assign(fn, impl)
return cmds[cmd] = cmds[actual] = fn
return cmds[cmd] = cmds[actual] = makeCmd(actual)
}
})
}

const makeCmd = cmd => {
const impl = require(`./${cmd}.js`)
const fn = (args, cb) => npm[_runCmd](cmd, impl, args, cb)
Object.assign(fn, impl)
return fn
}

let warnedNonDashArg = false
const _runCmd = Symbol('_runCmd')
const _load = Symbol('_load')
const _flatOptions = Symbol('_flatOptions')
const _tmpFolder = Symbol('_tmpFolder')
const npm = module.exports = new class extends EventEmitter {
constructor () {
super()
require('./utils/perf.js')
this.started = Date.now()
this.command = null

this.commands = proxyCmds(this)

procLogListener()

perf.emit('time', 'npm')
perf.on('timing', (name, finished) => {
log.timing(name, 'Completed in', finished + 'ms')
})

process.emit('time', 'npm')
this.version = require('../package.json').version

this.config = notYetLoadedConfig
this.loading = false
this.loaded = false
}

deref (c) {
return deref(c)
}

[_runCmd] (cmd, actual, impl, args, cb) {
// this will only ever be called with cmd set to the canonical command name
[_runCmd] (cmd, impl, args, cb) {
if (!this.loaded) {
throw new Error(
'Call npm.load(config, cb) before using this command.\n' +
'See the README.md or bin/npm-cli.js for example usage.'
)
}

this.command = actual

if (cmd === 'll' || cmd === 'la') {
this.config.set('long', true)
}
process.emit('time', `command:${cmd}`)
this.command = cmd

if (!this[_flatOptions]) {
this[_flatOptions] = require('./config/flat-options.js')(this)
Expand All @@ -99,14 +96,22 @@ const npm = module.exports = new class extends EventEmitter {

// Options are prefixed by a hyphen-minus (-, \u2d).
// Other dash-type chars look similar but are invalid.
args.filter(arg => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(arg))
.forEach(arg => log.error('arg', 'Argument starts with non-ascii dash, this is probably invalid:', arg))
if (!warnedNonDashArg) {
args.filter(arg => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(arg))
.forEach(arg => {
warnedNonDashArg = true
log.error('arg', 'Argument starts with non-ascii dash, this is probably invalid:', arg)
})
}

if (this.config.get('usage')) {
console.log(impl.usage)
cb()
} else {
impl(args, cb)
impl(args, er => {
process.emit('timeEnd', `command:${cmd}`)
cb(er)
})
}
}

Expand All @@ -116,24 +121,26 @@ const npm = module.exports = new class extends EventEmitter {
throw new TypeError('must call as: npm.load(options, callback)')
}
this.once('load', cb)
if (this.loaded || this.loadError) {
this.emit('load', this.loadError)
if (this.loaded || this.loadErr) {
this.emit('load', this.loadErr)
return
}
if (this.loading) {
return
}
this.loading = true

process.emit('time', 'npm:load')
this.log.pause()
return this[_load](cli).catch(er => er).then((er) => {
this.loading = false
this.loaded = true
this.config.loaded = true
this.loadErr = er
if (this.config.get('force')) {
if (!er && this.config.get('force')) {
this.log.warn('using --force', 'Recommended protections disabled.')
}
process.emit('timeEnd', 'npm:load')
this.emit('load', er)
})
}
Expand Down Expand Up @@ -227,20 +234,22 @@ const npm = module.exports = new class extends EventEmitter {
? resolve(this.globalPrefix, 'lib', 'node_modules')
: resolve(this.globalPrefix, 'node_modules')
}

get localDir () {
return resolve(this.prefix, 'node_modules')
}
get dir () {
return (this.config.get('global')) ? this.globalDir
: resolve(this.prefix, 'node_modules')
return (this.config.get('global')) ? this.globalDir : this.localDir
}

get globalBin () {
const b = this.globalPrefix
return process.platform !== 'win32' ? resolve(b, 'bin') : b
}

get localBin () {
return resolve(this.dir, '.bin')
}
get bin () {
return this.config.get('global') ? this.globalBin
: resolve(this.dir, '.bin')
return this.config.get('global') ? this.globalBin : this.localBin
}

get prefix () {
Expand All @@ -251,13 +260,6 @@ const npm = module.exports = new class extends EventEmitter {
this[k] = r
}

get cache () {
return this.config.get('cache')
}
set cache (r) {
this.config.set('cache', r)
}

// XXX add logging to see if we actually use this
get tmp () {
if (!this[_tmpFolder]) {
Expand Down Expand Up @@ -285,5 +287,5 @@ const cleanUpLogFiles = require('./utils/cleanup-log-files.js')
const getProjectScope = require('./utils/get-project-scope.js')

if (require.main === module) {
require('../bin/npm-cli.js')
require('./npm-cli.js')(process)
}
Loading

0 comments on commit 1b00d17

Please sign in to comment.