check-node-version
Advanced tools
Comparing version 3.3.0 to 4.0.0
106
bin.js
@@ -1,104 +0,2 @@ | ||
#!/usr/bin/env node | ||
"use strict"; | ||
var chalk = require("chalk"); | ||
var minimist = require("minimist"); | ||
var check = require("./"); | ||
var PROGRAMS = require("./").PROGRAMS; | ||
var fs = require("fs"); | ||
var path = require("path"); | ||
function logVersionError(name, err) { | ||
if (err.stderr) { | ||
console.error(chalk.red.bold(err.stderr)); | ||
} | ||
else if (err.execError) { | ||
console.error(chalk.red.bold(err.execError.message)); | ||
} | ||
else { | ||
console.error(chalk.red.bold(err.message)); | ||
} | ||
} | ||
function printInstalledVersion(name, info) { | ||
if (info.version) { | ||
console.log(name + ": " + chalk.bold(info.version)); | ||
} | ||
if (info.notfound) { | ||
console.error(chalk.red.bold(name + ': not installed')); | ||
} | ||
if (info.error) { | ||
logVersionError(name, info.error); | ||
} | ||
} | ||
function printVersions(result, print) { | ||
Object.keys(PROGRAMS).forEach(function(name) { | ||
var info = result.versions[name]; | ||
var isSatisfied = info.isSatisfied; | ||
// report installed version | ||
if (print || !isSatisfied) { | ||
printInstalledVersion(name, info); | ||
} | ||
// display any non-compliant versions | ||
if (!isSatisfied) { | ||
var raw = info.wanted.raw; | ||
var range = info.wanted.range; | ||
console.error(chalk.red.bold("Error: Wanted " + name + " version " + raw + " (" + range +")")); | ||
console.log(chalk.red.bold(PROGRAMS[name].getInstallInstructions(raw))); | ||
} | ||
}); | ||
} | ||
var argv = minimist(process.argv.slice(2), { | ||
alias: { | ||
"print": "p", | ||
"help": "h", | ||
}, | ||
boolean: [ | ||
"print", | ||
"help", | ||
], | ||
}); | ||
if (argv.help) { | ||
var usage = fs.readFileSync(path.join(__dirname, "usage.txt"), { | ||
encoding: "utf8", | ||
}); | ||
process.stdout.write(usage); | ||
process.exit(0); | ||
} | ||
var options = Object.keys(PROGRAMS).reduce(function(memo, name) { | ||
memo[name] = argv[name]; | ||
return memo; | ||
}, {}); | ||
if (argv.package) { | ||
try { | ||
var packageJson = require(path.join(process.cwd(), 'package.json')); | ||
} catch (e) { | ||
console.log('Error: When running with --package, a package.json file is expected in the current working directory'); | ||
console.log('Current working directory is: ' + process.cwd()); | ||
process.exit(1); | ||
} | ||
if (!packageJson.engines) { | ||
console.log('Error: When running with --package, your package.json is expected to contain the "engines" key'); | ||
console.log('See https://docs.npmjs.com/files/package.json#engines for the supported syntax'); | ||
process.exit(1); | ||
} | ||
options = Object.keys(PROGRAMS).reduce(function(memo, name) { | ||
memo[name] = packageJson.engines[name]; | ||
return memo; | ||
}, {}); | ||
} | ||
check(options, function(err, result) { | ||
if (err) { | ||
console.error(err.message); | ||
process.exit(1); | ||
return; | ||
} | ||
printVersions(result, argv.print); | ||
process.exit(result.isSatisfied ? 0 : 1); | ||
}); | ||
require('./gatekeeper'); | ||
require('./cli'); |
## Releases | ||
### 4.0.0 | ||
* **Breaking:** Drop support for node versions before 8.3.0 | ||
* **Breaking:** Remove `options.getVersion` option from api (no | ||
cli change) | ||
* Improve test suite | ||
* Make CLI treat versions arguments as strings | ||
* Fix message for missing binary of Windows | ||
* Check global versions only | ||
* Make instructions valid for version ranges | ||
* Only suggest using nvm if nvm is installed | ||
### 3.3.0 | ||
@@ -4,0 +16,0 @@ |
@@ -32,12 +32,2 @@ /** | ||
/** | ||
* Extra options to run with. | ||
*/ | ||
interface Options { | ||
/** | ||
* @returns The version of a package. | ||
*/ | ||
getVersion: GetVersion; | ||
} | ||
/** | ||
* Requested version range of a package. | ||
@@ -82,17 +72,12 @@ */ | ||
/** | ||
* Whether the program version was unable to be found. | ||
* Whether the version was known to satisfy its requirements (false). | ||
*/ | ||
notfound?: boolean; | ||
isSatisfied: false; | ||
/** | ||
* Any error thrown during checking. | ||
* Whether the program version was unable to be found. | ||
*/ | ||
error?: Error; | ||
notfound?: boolean; | ||
/** | ||
* Whether the version was known to satisfy its requirements (false). | ||
*/ | ||
isSatisfied: false; | ||
/** | ||
* Retrieved version, if available. | ||
@@ -147,3 +132,2 @@ */ | ||
* @param [wanted] Which versions of programs are required. | ||
* @param [options] Extra options to run with. | ||
* @param onComplete Handles results from checking versions. | ||
@@ -153,4 +137,3 @@ */ | ||
declare function check(wanted: WantedVersions, onComplete: OnComplete): void; | ||
declare function check(wanted: WantedVersions, options: Options, onComplete: OnComplete): void; | ||
export = check; |
203
index.js
"use strict"; | ||
var exec = require("child_process").exec; | ||
var semver = require("semver"); | ||
var parallel = require("run-parallel"); | ||
var mapValues = require("map-values"); | ||
var filterObject = require("object-filter"); | ||
var assign = require("object.assign"); | ||
const { exec } = require("child_process"); | ||
const path = require("path"); | ||
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 + "`"; | ||
} | ||
}, | ||
npx: { | ||
getVersion: runVersionCommand.bind(null, "npx --version"), | ||
getInstallInstructions: function(v) { | ||
return "To install npx, run `npm install -g npx@" + v + "`"; | ||
} | ||
}, | ||
yarn: { | ||
getVersion: runVersionCommand.bind(null, "yarn --version"), | ||
getInstallInstructions: function(v) { | ||
return "To install yarn, see https://yarnpkg.com/lang/en/docs/install/"; | ||
} | ||
}, | ||
}; | ||
const filterObject = require("object-filter"); | ||
const mapValues = require("map-values"); | ||
const parallel = require("run-parallel"); | ||
const semver = require("semver"); | ||
const tools = require('./tools'); | ||
const runningOnWindows = (process.platform === "win32"); | ||
const originalPath = process.env.PATH; | ||
const pathSeparator = runningOnWindows ? ";" : ":"; | ||
const localBinPath = path.resolve("node_modules/.bin") | ||
// ignore locally installed packages | ||
const globalPath = originalPath | ||
.split(pathSeparator) | ||
.filter(p => path.resolve(p)!==localBinPath) | ||
.join(pathSeparator) | ||
; | ||
function runVersionCommand(command, callback) { | ||
exec(command, function(execError, stdin, stderr) { | ||
var commandDescription = JSON.stringify(command); | ||
if (execError && execError.code === 127) { | ||
process.env.PATH = globalPath; | ||
exec(command, (execError, stdout, stderr) => { | ||
const commandDescription = JSON.stringify(command); | ||
if (!execError) { | ||
return callback(null, { | ||
notfound: true, | ||
version: stdout, | ||
}); | ||
} | ||
else if (execError) { | ||
var runError = new Error("Command failed: " + commandDescription); | ||
if (stderr) { | ||
runError.stderr = stderr.trim(); | ||
} | ||
if (execError) { | ||
runError.execError = execError; | ||
} | ||
if ( | ||
(execError.code === 127) | ||
|| | ||
(runningOnWindows && execError.message.includes("is not recognized")) | ||
) { | ||
return callback(null, { | ||
error: runError, | ||
notfound: true, | ||
}); | ||
} | ||
else { | ||
return callback(null, { | ||
version: stdin.toString().split('\n')[0].trim(), | ||
}); | ||
// something went very wrong during execution | ||
let errorMessage = `Command failed: ${commandDescription}` | ||
if (stderr) { | ||
errorMessage += `\n\nstderr:\n${stderr.toString().trim()}\n`; | ||
} | ||
errorMessage += `\n\noriginal error message:\n${execError.message}\n`; | ||
return callback(new Error(errorMessage)); | ||
}); | ||
process.env.PATH = originalPath; | ||
} | ||
@@ -69,25 +67,19 @@ | ||
function normalizeWanted(wanted) { | ||
wanted = wanted || {}; | ||
if (!wanted) { | ||
return {}; | ||
} | ||
// 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]; | ||
}); | ||
wanted = filterObject(wanted, (_, key) => tools[key]); | ||
return wanted; | ||
} | ||
function normalizeOptions(options) { | ||
return assign({ | ||
getVersion: defaultGetVersion, | ||
}, options); | ||
} | ||
function defaultGetVersion(name, callback) { | ||
PROGRAMS[name].getVersion(callback); | ||
} | ||
module.exports = function check(wanted, options, callback) { | ||
module.exports = function check(wanted, callback) { | ||
// Normalize arguments | ||
@@ -98,48 +90,49 @@ if (typeof wanted === "function") { | ||
} | ||
if (typeof options === "function") { | ||
callback = options; | ||
options = null; | ||
} | ||
wanted = normalizeWanted(wanted); | ||
options = normalizeOptions(options); | ||
var commands = mapValues(PROGRAMS, function(program, name) { | ||
return options.getVersion.bind(null, name); | ||
}); | ||
parallel(commands, function(err, versionsResult) { | ||
const commands = mapValues( | ||
( | ||
Object.keys(wanted).length | ||
? filterObject(tools, (_, key) => wanted[key]) | ||
: tools | ||
), | ||
({ getVersion }) => ( runVersionCommand.bind(null, getVersion) ) | ||
); | ||
parallel(commands, (err, versionsResult) => { | ||
if (err) { | ||
callback(err); | ||
return; | ||
} | ||
else { | ||
var versions = mapValues(PROGRAMS, function(program, name) { | ||
var programInfo = {}; | ||
if (versionsResult[name].error) { | ||
programInfo.error = versionsResult[name].error; | ||
} | ||
if (versionsResult[name].version) { | ||
programInfo.version = semver(versionsResult[name].version); | ||
} | ||
if (versionsResult[name].notfound) { | ||
programInfo.notfound = versionsResult[name].notfound; | ||
} | ||
programInfo.isSatisfied = true; | ||
if (wanted[name]) { | ||
programInfo.wanted = new semver.Range(wanted[name]); | ||
programInfo.isSatisfied = !! ( | ||
programInfo.version && | ||
semver.satisfies(programInfo.version, programInfo.wanted) | ||
); | ||
} | ||
return programInfo; | ||
}); | ||
callback(null, { | ||
versions: versions, | ||
isSatisfied: Object.keys(wanted).every(function(name) { | ||
return versions[name].isSatisfied; | ||
}), | ||
}); | ||
} | ||
const versions = mapValues(versionsResult, (_, name) => { | ||
const programInfo = { | ||
isSatisfied: true, | ||
}; | ||
if (versionsResult[name].version) { | ||
programInfo.version = semver(versionsResult[name].version); | ||
} | ||
if (versionsResult[name].notfound) { | ||
programInfo.notfound = versionsResult[name].notfound; | ||
} | ||
if (wanted[name]) { | ||
programInfo.wanted = new semver.Range(wanted[name]); | ||
programInfo.isSatisfied = Boolean( | ||
programInfo.version | ||
&& | ||
semver.satisfies(programInfo.version, programInfo.wanted) | ||
); | ||
} | ||
return programInfo; | ||
}); | ||
callback(null, { | ||
versions: versions, | ||
isSatisfied: Object.keys(wanted).every(name => versions[name].isSatisfied), | ||
}); | ||
}); | ||
}; | ||
module.exports.PROGRAMS = PROGRAMS; |
{ | ||
"name": "check-node-version", | ||
"version": "3.3.0", | ||
"version": "4.0.0", | ||
"engines": { | ||
"node": ">=8.3.0" | ||
}, | ||
"description": "Check installed versions of node and npm", | ||
@@ -10,4 +13,11 @@ "main": "index.js", | ||
"scripts": { | ||
"test": "tape test.js" | ||
"add-docs": "git add README.md", | ||
"build-readme": "gitdown ./README_src.md --output-file ./README.md", | ||
"test": "ava" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "npx run-s test build-readme add-docs" | ||
} | ||
}, | ||
"repository": { | ||
@@ -33,9 +43,13 @@ "type": "git", | ||
"object-filter": "^1.0.2", | ||
"object.assign": "^4.0.4", | ||
"run-parallel": "^1.1.4", | ||
"semver": "^5.0.3" | ||
"semver": "^5.7.0" | ||
}, | ||
"devDependencies": { | ||
"tape": "^4.2.2" | ||
"ava": "^1.3.1", | ||
"gitdown": "^2.5.7", | ||
"husky": "^1.3.1", | ||
"npm": "3.10.10", | ||
"npm-run-all": "^4.1.5", | ||
"proxyquire": "^2.1.0" | ||
} | ||
} |
@@ -0,5 +1,17 @@ | ||
<a name="check-node-version"></a> | ||
# check-node-version | ||
[![NPM version](http://img.shields.io/npm/v/check-node-version.svg?style=flat-square)](https://www.npmjs.org/package/check-node-version) | ||
[![AppVeyor build status](https://img.shields.io/appveyor/ci/parshap/check-node-version/master.svg?style=flat-square)](https://ci.appveyor.com/project/parshap/check-node-version/branch/master) | ||
[![Travis build status](http://img.shields.io/travis/parshap/check-node-version/master.svg?style=flat-square)](https://travis-ci.org/parshap/check-node-version) | ||
Check installed versions of `node`, `npm`, and `yarn`. | ||
Check installed versions of `node`, `npm`, `npx`, and `yarn`. | ||
* [check-node-version](#check-node-version) | ||
* [Install](#check-node-version-install) | ||
* [Command Line Usage](#check-node-version-command-line-usage) | ||
* [Examples](#check-node-version-command-line-usage-examples) | ||
* [API Usage](#check-node-version-api-usage) | ||
<a name="check-node-version-install"></a> | ||
## Install | ||
@@ -13,2 +25,3 @@ | ||
<a name="check-node-version-command-line-usage"></a> | ||
## Command Line Usage | ||
@@ -55,6 +68,9 @@ | ||
Print this message. | ||
``` | ||
<a name="check-node-version-command-line-usage-examples"></a> | ||
### Examples | ||
<a name="check-node-version-command-line-usage-examples-check-for-node-6-failing"></a> | ||
#### Check for node 6, failing | ||
@@ -73,2 +89,3 @@ | ||
<a name="check-node-version-command-line-usage-examples-check-for-node-6-passing"></a> | ||
#### Check for node 6, passing | ||
@@ -84,2 +101,3 @@ | ||
<a name="check-node-version-command-line-usage-examples-check-for-multiple-versions-simultaneously"></a> | ||
#### Check for multiple versions simultaneously | ||
@@ -94,12 +112,13 @@ | ||
<a name="check-node-version-command-line-usage-examples-print-installed-versions"></a> | ||
#### Print installed versions | ||
Use the `--print` option to print all currently installed versions. | ||
Use the `--print` option to print currently installed versions. | ||
If given a tool to check, only that will be printed. | ||
Otherwise, all known tools will be printed. | ||
Notes a missing tool. | ||
```bash | ||
$ check-node-version --print | ||
$ check-node-version --print --node 11.12 | ||
node: 11.12.0 | ||
npm: 6.9.0 | ||
npx: 10.2.0 | ||
yarn: 1.13.0 | ||
$ echo $? | ||
@@ -109,10 +128,8 @@ 0 | ||
Even with a missing binary (Windows error shown), if the checks run, all is good. | ||
```powershell | ||
$ check-node-version --print --node 11.12 | ||
$ check-node-version --print | ||
node: 11.12.0 | ||
npm: 6.9.0 | ||
npx: 10.2.0 | ||
'yarn' is not recognized as an internal or external command, | ||
operable program or batch file. | ||
yarn: not installed | ||
$ $LASTEXITCODE | ||
@@ -122,4 +139,9 @@ 0 | ||
#### Use with a `.nvmrc` file | ||
> **NOTE:** | ||
> Both preceding examples show that this works equally cross-platform, | ||
> the first one being a *nix shell, the second one running on Windows. | ||
<a name="check-node-version-command-line-usage-examples-use-with-a-nvmrc-file"></a> | ||
#### Use with a <code>.nvmrc</code> file | ||
```bash | ||
@@ -129,3 +151,4 @@ $ check-node-version --node $(cat .nvmrc) --npm 2.14 | ||
#### Use with `npm test` | ||
<a name="check-node-version-command-line-usage-examples-use-with-npm-test"></a> | ||
#### Use with <code>npm test</code> | ||
@@ -144,6 +167,7 @@ ```json | ||
<a name="check-node-version-api-usage"></a> | ||
## API Usage | ||
This module can also be used programmatically. | ||
Pass it an object with the required versions of `node`, `npm`, and/or `yarn` followed by a results handler. | ||
Pass it an object with the required versions of `node`, `npm`, `npx`, and/or `yarn` followed by a results handler. | ||
@@ -150,0 +174,0 @@ ```javascript |
@@ -1,5 +0,14 @@ | ||
Usage: check-node-version [OPTIONS] | ||
SYNOPSIS | ||
check-node-version [OPTIONS] | ||
Options: | ||
DESCRIPTION | ||
check-node-version will check if the current node, npm, npx and yarn | ||
versions match the given semver version ranges. | ||
If the given version is not satisfied, information about | ||
installing the needed version is printed and the program exits | ||
with an error code. | ||
OPTIONS | ||
--node VERSION | ||
@@ -6,0 +15,0 @@ Check that the current node version matches the given semver |
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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
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
6
193
20225
6
387
5
3
- Removedobject.assign@^4.0.4
- Removedcall-bind@1.0.8(transitive)
- Removedcall-bind-apply-helpers@1.0.1(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removeddefine-properties@1.2.1(transitive)
- Removeddunder-proto@1.0.0(transitive)
- Removedes-define-property@1.0.1(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedget-intrinsic@1.2.5(transitive)
- Removedgopd@1.2.0(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-symbols@1.1.0(transitive)
- Removedhasown@2.0.2(transitive)
- Removedobject-keys@1.1.1(transitive)
- Removedobject.assign@4.1.5(transitive)
- Removedset-function-length@1.2.2(transitive)
Updatedsemver@^5.7.0