Mini Shell
// Separated out for easier unit testing
module.exports = async process => {
// set it here so that regardless of what happens later, we don't
// leak any private CLI configs to other programs
process.title = 'npm'
// We used to differentiate between known broken and unsupported
// versions of node and attempt to only log unsupported but still run.
// After we dropped node 10 support, we can use new features
// (like static, private, etc) which will only give vague syntax errors,
// so now both broken and unsupported use console, but only broken
// will process.exit. It is important to now perform *both* of these
// checks as early as possible so the user gets the error message.
const semver = require('semver')
const supported = require('../package.json').engines.node
const knownBroken = '<12.5.0'
const nodejsVersion = process.version.replace(/-.*$/, '')
/* eslint-disable no-console */
if (semver.satisfies(nodejsVersion, knownBroken)) {
console.error('ERROR: npm is known not to run on Node.js ' + process.version)
console.error("You'll need to upgrade to a newer Node.js version in order to use this")
console.error('version of npm. You can find the latest version at https://nodejs.org/')
process.exit(1)
}
if (!semver.satisfies(nodejsVersion, supported)) {
console.error('npm does not support Node.js ' + process.version)
console.error('You should probably upgrade to a newer version of node as we')
console.error("can't make any promises that npm will work with this version.")
console.error('You can find the latest version at https://nodejs.org/')
}
/* eslint-enable no-console */
const exitHandler = require('./utils/exit-handler.js')
process.on('uncaughtException', exitHandler)
process.on('unhandledRejection', exitHandler)
const Npm = require('./npm.js')
const npm = new Npm()
exitHandler.setNpm(npm)
// if npm is called as "npmg" or "npm_g", then
// run in global mode.
if (process.argv[1][process.argv[1].length - 1] === 'g') {
process.argv.splice(1, 1, 'npm', '-g')
}
const log = require('./utils/log-shim.js')
// only log node and npm paths in argv initially since argv can contain
// sensitive info. a cleaned version will be logged later
log.verbose('cli', process.argv.slice(0, 2).join(' '))
log.info('using', 'npm@%s', npm.version)
log.info('using', 'node@%s', process.version)
let cmd
// now actually fire up npm and run the command.
// this is how to use npm programmatically:
try {
await npm.load()
if (npm.config.get('version', 'cli')) {
npm.output(npm.version)
return exitHandler()
}
// npm --versions=cli
if (npm.config.get('versions', 'cli')) {
npm.argv = ['version']
npm.config.set('usage', false, 'cli')
}
cmd = npm.argv.shift()
if (!cmd) {
npm.output(await npm.usage)
process.exitCode = 1
return exitHandler()
}
await npm.exec(cmd, npm.argv)
return exitHandler()
} catch (err) {
if (err.code === 'EUNKNOWNCOMMAND') {
const didYouMean = require('./utils/did-you-mean.js')
const suggestions = await didYouMean(npm, npm.localPrefix, cmd)
npm.output(`Unknown command: "${cmd}"${suggestions}\n`)
npm.output('To see a list of supported npm commands, run:\n npm help')
process.exitCode = 1
return exitHandler()
}
return exitHandler(err)
}
}
Zerion Mini Shell 1.0