From 57d8f75eb864486f6aa17bb3dd2f213b5c148073 Mon Sep 17 00:00:00 2001 From: Gar Date: Thu, 24 Mar 2022 11:09:41 -0700 Subject: [PATCH] fix: consolidate node version support logic --- lib/cli.js | 22 +++++++- lib/utils/unsupported.js | 39 ------------- test/lib/cli.js | 39 +++++++++++-- test/lib/utils/unsupported.js | 102 ---------------------------------- 4 files changed, 54 insertions(+), 148 deletions(-) delete mode 100644 lib/utils/unsupported.js delete mode 100644 test/lib/utils/unsupported.js diff --git a/lib/cli.js b/lib/cli.js index 6583bd0c00206..f261dae121b9f 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -11,9 +11,25 @@ module.exports = async process => { // 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 { checkForBrokenNode, checkForUnsupportedNode } = require('./utils/unsupported.js') - checkForBrokenNode() - checkForUnsupportedNode() + const semver = require('semver') + const supported = require('../package.json').engines.node + const knownBroken = '<6.2.0 || 9 <9.3.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) diff --git a/lib/utils/unsupported.js b/lib/utils/unsupported.js deleted file mode 100644 index 75aad5e780ec4..0000000000000 --- a/lib/utils/unsupported.js +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable no-console */ -const semver = require('semver') -const supported = require('../../package.json').engines.node -const knownBroken = '<6.2.0 || 9 <9.3.0' - -// Keep this file compatible with all practical versions of node -// so we dont get syntax errors when trying to give the users -// a nice error message. Don't use our log handler because -// if we encounter a syntax error early on, that will never -// get displayed to the user. - -const checkVersion = exports.checkVersion = version => { - const versionNoPrerelease = version.replace(/-.*$/, '') - return { - version: versionNoPrerelease, - broken: semver.satisfies(versionNoPrerelease, knownBroken), - unsupported: !semver.satisfies(versionNoPrerelease, supported), - } -} - -exports.checkForBrokenNode = () => { - const nodejs = checkVersion(process.version) - if (nodejs.broken) { - 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) - } -} - -exports.checkForUnsupportedNode = () => { - const nodejs = checkVersion(process.version) - if (nodejs.unsupported) { - 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/') - } -} diff --git a/test/lib/cli.js b/test/lib/cli.js index b6606c69fc429..49af62e8f2164 100644 --- a/test/lib/cli.js +++ b/test/lib/cli.js @@ -14,10 +14,6 @@ const cliMock = async (t, opts) => { const { Npm, outputs, logMocks, logs } = await loadMockNpm(t, { ...opts, init: false }) const cli = t.mock('../../lib/cli.js', { '../../lib/npm.js': Npm, - '../../lib/utils/unsupported.js': { - checkForBrokenNode: () => {}, - checkForUnsupportedNode: () => {}, - }, '../../lib/utils/exit-handler.js': exitHandlerMock, ...logMocks, }) @@ -175,3 +171,38 @@ t.test('load error calls error handler', async t => { await cli(process) t.strictSame(exitHandlerCalled(), [err]) }) + +t.test('known broken node version', async t => { + const errors = [] + let exitCode + const { cli } = await cliMock(t, { + globals: { + 'console.error': (msg) => errors.push(msg), + 'process.version': '6.0.0', + 'process.exit': e => exitCode = e, + }, + }) + await cli(process) + t.match(errors, [ + 'ERROR: npm is known not to run on Node.js 6.0.0', + 'You\'ll need to upgrade to a newer Node.js version in order to use this', + 'version of npm. You can find the latest version at https://nodejs.org/', + ]) + t.match(exitCode, 1) +}) + +t.test('unsupported node version', async t => { + const errors = [] + const { cli } = await cliMock(t, { + globals: { + 'console.error': (msg) => errors.push(msg), + 'process.version': '10.0.0', + }, + }) + await cli(process) + t.match(errors, [ + 'npm does not support Node.js 10.0.0', + 'You should probably upgrade to a newer version of node as we', + 'can\'t make any promises that npm will work with this version.', + ]) +}) diff --git a/test/lib/utils/unsupported.js b/test/lib/utils/unsupported.js deleted file mode 100644 index 2703044a227d3..0000000000000 --- a/test/lib/utils/unsupported.js +++ /dev/null @@ -1,102 +0,0 @@ -const t = require('tap') -const unsupported = require('../../../lib/utils/unsupported.js') -const mockGlobals = require('../../fixtures/mock-globals.js') - -const versions = [ - // broken unsupported - ['v0.1.103', true, true], - ['v0.2.0', true, true], - ['v0.3.5', true, true], - ['v0.4.7', true, true], - ['v0.5.3', true, true], - ['v0.6.17', true, true], - ['v0.7.8', true, true], - ['v0.8.28', true, true], - ['v0.9.6', true, true], - ['v0.10.48', true, true], - ['v0.11.16', true, true], - ['v0.12.9', true, true], - ['v1.0.1', true, true], - ['v1.6.0', true, true], - ['v2.3.1', true, true], - ['v3.0.0', true, true], - ['v4.5.0', true, true], - ['v4.8.4', true, true], - ['v5.7.1', true, true], - ['v6.8.1', false, true], - ['v7.0.0-beta23', false, true], - ['v7.2.3', false, true], - ['v8.4.0', false, true], - ['v9.3.0', false, true], - ['v10.0.0-0', false, true], - ['v11.0.0-0', false, true], - ['v12.0.0-0', false, true], - ['v12.13.0-0', false, false], - ['v13.0.0-0', false, true], - ['v14.0.0-0', false, true], - ['v14.15.0-0', false, false], - ['v15.0.0-0', false, true], - ['v16.0.0-0', false, false], -] - -t.test('versions', function (t) { - t.plan(versions.length * 2) - versions.forEach(function (verinfo) { - const version = verinfo[0] - const broken = verinfo[1] - const unsupp = verinfo[2] - const nodejs = unsupported.checkVersion(version) - t.equal(nodejs.broken, broken, version + ' ' + (broken ? '' : 'not ') + 'broken') - t.equal(nodejs.unsupported, unsupp, version + ' ' + (unsupp ? 'unsupported' : 'supported')) - }) - t.end() -}) - -t.test('checkForBrokenNode', t => { - // run it once to not fail - unsupported.checkForBrokenNode() - - const logs = [] - const expectLogs = [ - 'ERROR: npm is known not to run on Node.js 1.2.3', - "You'll need to upgrade to a newer Node.js version in order to use this", - 'version of npm. You can find the latest version at https://nodejs.org/', - ] - - // then make it a thing that fails - mockGlobals(t, { - 'console.error': msg => logs.push(msg), - 'process.version': '1.2.3', - 'process.exit': (code) => { - t.equal(code, 1) - t.strictSame(logs, expectLogs) - t.end() - }, - }) - - unsupported.checkForBrokenNode() -}) - -t.test('checkForUnsupportedNode', t => { - // run it once to not fail or warn - unsupported.checkForUnsupportedNode() - - const logs = [] - const expectLogs = [ - 'npm does not support Node.js 8.0.0', - 'You should probably upgrade to a newer version of node as we', - "can't make any promises that npm will work with this version.", - 'You can find the latest version at https://nodejs.org/', - ] - - // then make it a thing that fails - mockGlobals(t, { - 'console.error': msg => logs.push(msg), - 'process.version': '8.0.0', - }) - - unsupported.checkForUnsupportedNode() - - t.strictSame(logs, expectLogs) - t.end() -})