check-node-version
Advanced tools
Comparing version 1.1.2 to 2.0.0
76
bin.js
@@ -6,34 +6,41 @@ #!/usr/bin/env node | ||
var check = require("./"); | ||
var PROGRAMS = require("./").PROGRAMS; | ||
var fs = require("fs"); | ||
var path = require("path"); | ||
function logResult(result) { | ||
console.log("node:", "v" + result.node.version); | ||
console.log("npm:", "v" + result.npm.version); | ||
if ( ! result.nodeSatisfied) { | ||
console.log([ | ||
"Error: Wanted node version ", | ||
JSON.stringify(result.nodeWanted.raw), | ||
" (" + result.nodeWanted.range + ")", | ||
].join("")); | ||
function logVersionError(err) { | ||
if (err.stderr) { | ||
console.error(err.stderr); | ||
} | ||
if ( ! result.npmSatisfied) { | ||
console.log([ | ||
"Error: Wanted npm version ", | ||
JSON.stringify(result.npmWanted.raw), | ||
" (" + result.npmWanted.range + ")", | ||
].join("")); | ||
else if (err.execError) { | ||
console.error(err.execError.message); | ||
} | ||
if ( ! result.nodeSatisfied) { | ||
console.log([ | ||
"To install node, run ", | ||
"`nvm install " + result.nodeWanted.raw + "`", | ||
" or check https://nodejs.org/", | ||
].join("")); | ||
else { | ||
console.error(err.message); | ||
} | ||
if ( ! result.npmSatisfied) { | ||
console.log("To install npm, run `npm install -g npm@" + result.npmWanted.raw + "`"); | ||
} | ||
} | ||
function logResult(result) { | ||
// report installed versions | ||
Object.keys(PROGRAMS).forEach(function(name) { | ||
var info = result[name]; | ||
if (info.version) { | ||
console.log(name + ": " + info.version); | ||
} | ||
if (info.error) { | ||
logVersionError(info.error); | ||
} | ||
}); | ||
// display any non-compliant versions | ||
Object.keys(PROGRAMS).forEach(function(name) { | ||
if (result[name].isSatisfied === false) { | ||
var raw = result[name].wanted.raw; | ||
var range = result[name].wanted.range; | ||
console.log("Error: Wanted " + name + " version " + raw + " (" + range +")"); | ||
console.log(PROGRAMS[name].getInstallInstructions(raw)); | ||
} | ||
}); | ||
} | ||
var argv = minimist(process.argv.slice(2), { | ||
@@ -58,6 +65,6 @@ alias: { | ||
var options = { | ||
node: argv.node, | ||
npm: argv.npm, | ||
}; | ||
var options = Object.keys(PROGRAMS).reduce(function(memo, name) { | ||
memo[name] = argv[name]; | ||
return memo; | ||
}, {}); | ||
@@ -77,6 +84,6 @@ if (argv.package) { | ||
} | ||
options = { | ||
node: packageJson.engines.node, | ||
npm: packageJson.engines.npm, | ||
}; | ||
options = Object.keys(PROGRAMS).reduce(function(memo, name) { | ||
memo[name] = packageJson.engines[name]; | ||
return memo; | ||
}, {}); | ||
} | ||
@@ -86,3 +93,3 @@ | ||
if (err) { | ||
console.error(err.longMessage || err.message); | ||
console.error(err.message); | ||
process.exit(1); | ||
@@ -94,4 +101,3 @@ return; | ||
} | ||
var isSatisfied = result.nodeSatisfied && result.npmSatisfied; | ||
process.exit(isSatisfied ? 0 : 1); | ||
process.exit(result.isSatisfied ? 0 : 1); | ||
}); |
122
index.js
@@ -6,14 +6,46 @@ "use strict"; | ||
var parallel = require("run-parallel"); | ||
var mapValues = require("map-values"); | ||
var filterObject = require("object-filter"); | ||
var PROGRAMS = { | ||
node: { | ||
getVersion: runVersionCommand.bind(null, "node --version"), | ||
getInstallInstructions: function(v) { | ||
return "To install node, run `nvm install " + v + | ||
"` or see https://nodejs.org/"; | ||
} | ||
}, | ||
npm: { | ||
getVersion: runVersionCommand.bind(null, "npm --version"), | ||
getInstallInstructions: function(v) { | ||
return "To install npm, run `npm install -g npm@" + v + "`"; | ||
} | ||
}, | ||
yarn: { | ||
getVersion: runVersionCommand.bind(null, "yarn --version"), | ||
getInstallInstructions: function(v) { | ||
return "To install yarn, see https://yarnpkg.com/lang/en/docs/install/"; | ||
} | ||
}, | ||
}; | ||
function runVersionCommand(command, callback) { | ||
exec(command, function(err, stdin, stderr) { | ||
exec(command, function(execError, stdin, stderr) { | ||
var commandDescription = JSON.stringify(command); | ||
if (err || stderr) { | ||
var err = new Error("Command failed: " + commandDescription); | ||
err.longMessage = err.message + (stderr && ("\n" + stderr.trim())); | ||
err.execError = err; | ||
callback(err); | ||
if (execError || stderr) { | ||
var runError = new Error("Command failed: " + commandDescription); | ||
if (stderr) { | ||
runError.stderr = stderr.trim(); | ||
} | ||
if (execError) { | ||
runError.execError = execError; | ||
} | ||
return callback(null, { | ||
error: runError, | ||
}); | ||
} | ||
else { | ||
callback(null, stdin.toString().trim()); | ||
return callback(null, { | ||
version: stdin.toString().trim(), | ||
}); | ||
} | ||
@@ -23,11 +55,29 @@ }); | ||
// Return object containing only keys that a program exists for and | ||
// something valid was given. | ||
function normalizeWanted(wanted) { | ||
wanted = wanted || {}; | ||
return { | ||
node: wanted.node != null ? String(wanted.node) : "", | ||
npm: wanted.npm != null ? String(wanted.npm) : "", | ||
}; | ||
// Validate keys | ||
wanted = filterObject(wanted, Boolean); | ||
// Normalize to strings | ||
wanted = mapValues(wanted, String); | ||
// Filter existing programs | ||
wanted = filterObject(wanted, function(version, key) { | ||
return PROGRAMS[key]; | ||
}); | ||
return wanted; | ||
} | ||
module.exports = function(wanted, callback) { | ||
function normalizeOptions(options) { | ||
return Object.assign({ | ||
getVersion: defaultGetVersion, | ||
}, options); | ||
} | ||
function defaultGetVersion(name, callback) { | ||
PROGRAMS[name].getVersion(callback); | ||
} | ||
module.exports = function check(wanted, options, callback) { | ||
// Normalize arguments | ||
if (typeof wanted === "function") { | ||
@@ -37,8 +87,13 @@ callback = wanted; | ||
} | ||
if (typeof options === "function") { | ||
callback = options; | ||
options = null; | ||
} | ||
wanted = normalizeWanted(wanted); | ||
options = normalizeOptions(options); | ||
parallel({ | ||
node: runVersionCommand.bind(null, "node --version"), | ||
npm: runVersionCommand.bind(null, "npm --version"), | ||
}, function(err, versions) { | ||
var commands = mapValues(PROGRAMS, function(program, name) { | ||
return options.getVersion.bind(null, name); | ||
}); | ||
parallel(commands, function(err, versions) { | ||
if (err) { | ||
@@ -48,12 +103,31 @@ callback(err); | ||
else { | ||
callback(null, { | ||
node: semver(versions.node), | ||
nodeWanted: new semver.Range(wanted.node), | ||
nodeSatisfied: semver.satisfies(versions.node, wanted.node), | ||
npm: semver(versions.npm), | ||
npmWanted: new semver.Range(wanted.npm), | ||
npmSatisfied: semver.satisfies(versions.npm, wanted.npm), | ||
}); | ||
var retval = mapValues(PROGRAMS, function(program, name) { | ||
var name = name; | ||
var programInfo = {}; | ||
if (versions[name].error) { | ||
programInfo.error = versions[name].error; | ||
} | ||
if (versions[name].version) { | ||
programInfo.version = semver(versions[name].version); | ||
} | ||
if (wanted[name]) { | ||
programInfo.wanted = new semver.Range(wanted[name]); | ||
programInfo.isSatisfied = programInfo.version && semver.satisfies( | ||
programInfo.version, | ||
programInfo.wanted | ||
) || false; | ||
} | ||
return programInfo; | ||
}, {}); | ||
retval.isSatisfied = Object.keys(wanted).reduce(function(memo, name) { | ||
if (retval[name].isSatisfied !== false) { | ||
return memo; | ||
} | ||
return false; | ||
}, true); | ||
callback(null, retval); | ||
} | ||
}); | ||
}; | ||
module.exports.PROGRAMS = PROGRAMS; |
{ | ||
"name": "check-node-version", | ||
"version": "1.1.2", | ||
"version": "2.0.0", | ||
"description": "Check installed versions of node and npm", | ||
@@ -27,3 +27,5 @@ "main": "index.js", | ||
"dependencies": { | ||
"map-values": "^1.0.1", | ||
"minimist": "^1.2.0", | ||
"object-filter": "^1.0.2", | ||
"run-parallel": "^1.1.4", | ||
@@ -30,0 +32,0 @@ "semver": "^5.0.3" |
# check-node-version | ||
Check installed versions of `node` and `npm`. | ||
Check installed versions of `node`, `npm`, and `yarn`. | ||
@@ -20,3 +20,3 @@ ## Install | ||
DESCRIPTION | ||
check-node-version will check if the current node and npm versions | ||
check-node-version will check if the current node, npm and yarn versions | ||
match the given semver version ranges. | ||
@@ -38,2 +38,6 @@ | ||
--yarn VERSION | ||
Check that the current yarn version matches the given semver | ||
version range. | ||
--package | ||
@@ -44,4 +48,4 @@ Use the "engines" key in the current package.json for the | ||
-q, --quiet | ||
Don't output anything. Exit with an error code if the node | ||
or npm version is not satisfied, otherwise exit with code 0. | ||
Don't output anything. Exit with an error code if the | ||
version is not satisfied, otherwise exit with code 0. | ||
@@ -56,3 +60,3 @@ -h, --help | ||
When no versions are given, the current node and npm versions are | ||
When no versions are given, the current node, npm, and yarn versions are | ||
printed out. | ||
@@ -64,2 +68,3 @@ | ||
npm: v2.14.10 | ||
yarn: v0.21.3 | ||
$ echo $? | ||
@@ -75,2 +80,3 @@ 0 | ||
npm: v2.14.10 | ||
yarn: v0.21.3 | ||
Error: Wanted node version "4" (>=4.0.0 <5.0.0) | ||
@@ -82,2 +88,21 @@ To install node, run `nvm install 4` or check https://nodejs.org/ | ||
#### Check for `node@4` and `npm@2.14`, `yarn` not installed | ||
``` | ||
$ check-node-version --node 4 --npm 2.14 | ||
node: v0.12.7 | ||
npm: v2.14.10 | ||
yarn: not installed | ||
Error: Wanted node version "4" (>=4.0.0 <5.0.0) | ||
To install node, run `nvm install 4` or check https://nodejs.org/ | ||
$ echo $? | ||
1 | ||
``` | ||
#### Use with a `.nvmrc` file | ||
``` | ||
$ check-node-version --node $(cat .nvmrc) --npm 2.14 | ||
``` | ||
#### Use with `npm test` | ||
@@ -100,2 +125,2 @@ | ||
This module can also be used programmatically from node. See `index.js` | ||
and `test.js` for more information.n | ||
and `test.js` for more information. |
129
test.js
@@ -6,2 +6,21 @@ "use strict"; | ||
function getMockedGetVersionsOptions(versions) { | ||
return { | ||
getVersion: function(name, callback) { | ||
process.nextTick(function() { | ||
if (versions[name] instanceof Error) { | ||
callback(null, { | ||
error: versions[name], | ||
}); | ||
} | ||
else { | ||
callback(null, { | ||
version: versions[name], | ||
}); | ||
} | ||
}); | ||
}, | ||
}; | ||
} | ||
test("simple call", function(t) { | ||
@@ -11,9 +30,111 @@ check(function(err, result) { | ||
t.ok(result.node); | ||
t.ok(result.nodeWanted); | ||
t.ok(result.nodeSatisfied); | ||
t.ok(result.node.version); | ||
t.ok(result.npm); | ||
t.ok(result.npmWanted); | ||
t.ok(result.npmSatisfied); | ||
t.ok(result.npm.version); | ||
t.ok(result.yarn); | ||
t.ok(result.yarn.version); | ||
t.ok(result.isSatisfied); | ||
t.end(); | ||
}); | ||
}); | ||
test("positive node result", function(t) { | ||
var version = "7.0.0"; | ||
var wanted = { | ||
node: version, | ||
}; | ||
var options = getMockedGetVersionsOptions({ | ||
node: version, | ||
}); | ||
check(wanted, options, function(err, result) { | ||
t.ifError(err); | ||
t.ok(result.node); | ||
t.ok(result.node.version); | ||
t.equal(result.node.version.raw, version); | ||
t.equal(result.node.wanted.range, version); | ||
t.equal(result.node.isSatisfied, true); | ||
t.equal(result.isSatisfied, true); | ||
t.end(); | ||
}); | ||
}); | ||
test("negative node result", function(t) { | ||
var version = "7.0.0"; | ||
var wanted = { | ||
node: "6.9.9", | ||
}; | ||
var options = getMockedGetVersionsOptions({ | ||
node: version, | ||
}); | ||
check(wanted, options, function(err, result) { | ||
t.ifError(err); | ||
t.ok(result.node); | ||
t.equal(result.node.version.raw, version); | ||
t.equal(result.node.wanted.range, "6.9.9"); | ||
t.equal(result.node.isSatisfied, false); | ||
t.equal(result.isSatisfied, false); | ||
t.end(); | ||
}); | ||
}); | ||
test("positive node result, yarn not installed", function(t) { | ||
var version = "7.0.0"; | ||
var wanted = { | ||
node: version, | ||
}; | ||
var options = getMockedGetVersionsOptions({ | ||
node: version, | ||
yarn: new Error("Command failed: yarn --version"), | ||
}); | ||
check(wanted, options, function(err, result) { | ||
t.ifError(err); | ||
t.ok(result.node); | ||
t.equal(result.node.version.raw, version); | ||
t.equal(result.node.wanted.range, version); | ||
t.equal(result.node.isSatisfied, true); | ||
t.equal(result.isSatisfied, true); | ||
t.equal(result.yarn.version, undefined); | ||
t.ok(result.yarn.error); | ||
t.end(); | ||
}); | ||
}); | ||
test("negative node result, yarn not installed", function(t) { | ||
var wanted = { | ||
node: "6.9.9", | ||
}; | ||
var options = getMockedGetVersionsOptions({ | ||
node: "7.0.0", | ||
npm: "2.0.0", | ||
yarn: new Error("Command failed: yarn --version"), | ||
}); | ||
check(wanted, options, function(err, result) { | ||
t.ifError(err); | ||
t.ok(result.node); | ||
t.equal(result.node.version.raw, "7.0.0"); | ||
t.equal(result.node.wanted.range, "6.9.9"); | ||
t.equal(result.node.isSatisfied, false); | ||
t.equal(result.yarn.version, undefined); | ||
t.ok(result.yarn.error); | ||
t.equal(result.isSatisfied, false); | ||
t.end(); | ||
}); | ||
}); | ||
test("negative yarn result, yarn not installed", function(t) { | ||
var wanted = { | ||
yarn: "1.1.1", | ||
}; | ||
var options = getMockedGetVersionsOptions({ | ||
node: "7.0.0", | ||
npm: "2.0.0", | ||
yarn: new Error("Command failed: yarn --version"), | ||
}); | ||
check(wanted, options, function(err, result) { | ||
t.ifError(err); | ||
t.equal(result.yarn.version, undefined); | ||
t.equal(result.yarn.wanted.range, "1.1.1"); | ||
t.equal(result.isSatisfied, false); | ||
t.end(); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13365
7
339
119
5
2
+ Addedmap-values@^1.0.1
+ Addedobject-filter@^1.0.2
+ Addedmap-values@1.0.1(transitive)
+ Addedobject-filter@1.0.2(transitive)