Skip to content

Commit 1435fcf

Browse files
committed
fix: do less work loading ./lib/npm.js
Wrapping logging messages is very inacessible and makes for bad logs. We can let terminals wrap content. The whole cli.js file needs to parse, not just the single function checking for compatibility, so we inline it again.
1 parent 09b58e4 commit 1435fcf

File tree

1 file changed

+34
-79
lines changed

1 file changed

+34
-79
lines changed

lib/cli.js

+34-79
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,28 @@
1-
// This is separate to indicate that it should contain code we expect to work in
2-
// all conceivably runnable versions of node. This is a best effort to catch
3-
// syntax errors to give users a good error message if they are using a node
4-
// version that doesn't allow syntax we are using such as private properties, etc
5-
const createEnginesValidation = () => {
6-
const node = process.version.replace(/-.*$/, '')
1+
/* eslint-disable max-len */
2+
// Code in this file should work in all conceivably runnable versions of node.
3+
// A best effort is made to catch syntax errors to give users a good error message if they are using a node version that doesn't allow syntax we are using in other files such as private properties, etc
4+
5+
// Separated out for easier unit testing
6+
module.exports = async process => {
7+
// set it here so that regardless of what happens later, we don't
8+
// leak any private CLI configs to other programs
9+
process.title = 'npm'
10+
11+
// if npm is called as "npmg" or "npm_g", then run in global mode.
12+
if (process.argv[1][process.argv[1].length - 1] === 'g') {
13+
process.argv.splice(1, 1, 'npm', '-g')
14+
}
15+
16+
const nodeVersion = process.version.replace(/-.*$/, '')
717
const pkg = require('../package.json')
818
const engines = pkg.engines.node
9-
const npm = `v${pkg.version}`
10-
11-
const cols = Math.min(Math.max(20, process.stdout.columns) || 80, 80)
12-
const wrap = (lines) => lines
13-
.join(' ')
14-
.split(/[ \n]+/)
15-
.reduce((left, right) => {
16-
const last = left.split('\n').pop()
17-
const join = last.length && last.length + right.length > cols ? '\n' : ' '
18-
return left + join + right
19-
})
20-
.trim()
21-
22-
const unsupportedMessage = wrap([
23-
`npm ${npm} does not support Node.js ${node}.`,
24-
`You should probably upgrade to a newer version of node as we can't make any`,
25-
`promises that npm will work with this version.`,
26-
`This version of npm supports the following node versions: \`${engines}\`.`,
27-
'You can find the latest version at https://nodejs.org/.',
28-
])
29-
30-
const brokenMessage = wrap([
31-
`ERROR: npm ${npm} is known not to run on Node.js ${node}.`,
32-
`You'll need to upgrade to a newer Node.js version in order to use this version of npm.`,
33-
`This version of npm supports the following node versions: \`${engines}\`.`,
34-
'You can find the latest version at https://nodejs.org/.',
35-
])
36-
37-
// coverage ignored because this is only hit in very unsupported node versions
38-
// and it's a best effort attempt to show something nice in those cases
19+
const npmVersion = `v${pkg.version}`
20+
21+
const unsupportedMessage = `npm ${npmVersion} does not support Node.js ${nodeVersion}. This version of npm supports the following node versions: \`${engines}\`. You can find the latest version at https://nodejs.org/.`
22+
23+
const brokenMessage = `ERROR: npm ${npmVersion} is known not to run on Node.js ${nodeVersion}. This version of npm supports the following node versions: \`${engines}\`. You can find the latest version at https://nodejs.org/.`
24+
25+
// Coverage ignored because this is only hit in very unsupported node versions and it's a best effort attempt to show something nice in those cases
3926
/* istanbul ignore next */
4027
const syntaxErrorHandler = (err) => {
4128
if (err instanceof SyntaxError) {
@@ -51,74 +38,42 @@ const createEnginesValidation = () => {
5138
process.on('uncaughtException', syntaxErrorHandler)
5239
process.on('unhandledRejection', syntaxErrorHandler)
5340

54-
return {
55-
node,
56-
engines,
57-
unsupportedMessage,
58-
off: () => {
59-
process.off('uncaughtException', syntaxErrorHandler)
60-
process.off('unhandledRejection', syntaxErrorHandler)
61-
},
62-
}
63-
}
64-
65-
// Separated out for easier unit testing
66-
module.exports = async process => {
67-
// set it here so that regardless of what happens later, we don't
68-
// leak any private CLI configs to other programs
69-
process.title = 'npm'
70-
71-
// if npm is called as "npmg" or "npm_g", then run in global mode.
72-
if (process.argv[1][process.argv[1].length - 1] === 'g') {
73-
process.argv.splice(1, 1, 'npm', '-g')
74-
}
75-
76-
// Nothing should happen before this line if we can't guarantee it will
77-
// not have syntax errors in some version of node
78-
const validateEngines = createEnginesValidation()
79-
8041
const satisfies = require('semver/functions/satisfies')
8142
const exitHandler = require('./utils/exit-handler.js')
8243
const Npm = require('./npm.js')
8344
const npm = new Npm()
8445
exitHandler.setNpm(npm)
8546

86-
// only log node and npm paths in argv initially since argv can contain
87-
// sensitive info. a cleaned version will be logged later
47+
// only log node and npm paths in argv initially since argv can contain sensitive info. a cleaned version will be logged later
8848
const log = require('./utils/log-shim.js')
8949
log.verbose('cli', process.argv.slice(0, 2).join(' '))
9050
log.info('using', 'npm@%s', npm.version)
9151
log.info('using', 'node@%s', process.version)
9252

93-
// At this point we've required a few files and can be pretty sure
94-
// we dont contain invalid syntax for this version of node. It's
95-
// possible a lazy require would, but that's unlikely enough that
96-
// it's not worth catching anymore and we attach the more important
97-
// exit handlers.
98-
validateEngines.off()
53+
// At this point we've required a few files and can be pretty sure we dont contain invalid syntax for this version of node. It's possible a lazy require would, but that's unlikely enough that it's not worth catching anymore and we attach the more important exit handlers.
54+
process.off('uncaughtException', syntaxErrorHandler)
55+
process.off('unhandledRejection', syntaxErrorHandler)
9956
process.on('uncaughtException', exitHandler)
10057
process.on('unhandledRejection', exitHandler)
10158

102-
// It is now safe to log a warning if they are using a version of node
103-
// that is not going to fail on syntax errors but is still unsupported
104-
// and untested and might not work reliably. This is safe to use the logger
105-
// now which we want since this will show up in the error log too.
106-
if (!satisfies(validateEngines.node, validateEngines.engines)) {
107-
log.warn('cli', validateEngines.unsupportedMessage)
59+
// It is now safe to log a warning if they are using a version of node that is not going to fail on syntax errors but is still unsupported and untested and might not work reliably. This is safe to use the logger now which we want since this will show up in the error log too.
60+
if (!satisfies(nodeVersion, engines)) {
61+
log.warn('cli', unsupportedMessage)
10862
}
10963

11064
let cmd
111-
// now actually fire up npm and run the command.
112-
// this is how to use npm programmatically:
65+
// Now actually fire up npm and run the command.
66+
// This is how to use npm programmatically:
11367
try {
11468
await npm.load()
11569

70+
// npm -v
11671
if (npm.config.get('version', 'cli')) {
11772
npm.output(npm.version)
11873
return exitHandler()
11974
}
12075

121-
// npm --versions=cli
76+
// npm --versions
12277
if (npm.config.get('versions', 'cli')) {
12378
npm.argv = ['version']
12479
npm.config.set('usage', false, 'cli')

0 commit comments

Comments
 (0)