How do I require a minimum version of node.js in my script? - node.js

I just found out that a script I wrote only works on node 0.10 because it uses readable events.
How do I require a minimum version of node.js in my script so that users know that they need to upgrade?

In package.json:
{ "engines" : { "node" : ">=0.10.3" } }
From the docs.
Edit, a programmatic way:
var pkg = require('./pacakge'),
semver = require('semver');
if(!semver.satisfies(process.version, pkg.engines.node)) {
// Not sure if throw or process.exit is best.
throw new Error('Requires a node version matching ' + pkg.engines.node);
}

Add this to top the top of your script.
var versionComps = process.versions['node'].split('.');
if (parseInt(versionComps[0]) === 0 && parseInt(versionComps[1]) < 10) {
console.log('Script requires node.js version >= 0.10');
process.exit(1);
};

Related

Loopback getting error - Major change in User validatePassword function in the same release itself (3.0.0)

I am using loopback 3.0.0, and I have set up a new server recently, about one week ago. For that, I have ran the command npm install by putting the package.son file.
But in that installed files, the node_modules/loopback/common/user.js module has changed with major changes.
Egs:
Old file:
// Copyright IBM Corp. 2014,2016. All Rights Reserved.
User.validatePassword = function(plain) {
var err;
if (plain && typeof plain === 'string' && plain.length <= MAX_PASSWORD_LENGTH) {
return true;
}
if (plain.length > MAX_PASSWORD_LENGTH) {
err = new Error(g.f('Password too long: %s', plain));
err.code = 'PASSWORD_TOO_LONG';
} else {
err = new Error(g.f('Invalid password: %s', plain));
err.code = 'INVALID_PASSWORD';
}
err.statusCode = 422;
throw err;
};
New File:
// Copyright IBM Corp. 2014,2018. All Rights Reserved.
User.validatePassword = function(plain) {
var err;
if (!plain || typeof plain !== 'string') {
err = new Error(g.f('Invalid password.'));
err.code = 'INVALID_PASSWORD';
err.statusCode = 422;
throw err;
}
// Bcrypt only supports up to 72 bytes; the rest is silently dropped.
var len = Buffer.byteLength(plain, 'utf8');
if (len > MAX_PASSWORD_LENGTH) {
err = new Error(g.f('The password entered was too long. Max length is %d (entered %d)',
MAX_PASSWORD_LENGTH, len));
err.code = 'PASSWORD_TOO_LONG';
err.statusCode = 422;
throw err;
}
};
I have developed my code with the same version but with old code which they have provided in the same version(3.0.0.). Here you can see, in the new code there is no return statement, so the code is infinitely waiting for the return and being time out. In both places the package.json file contains the same version: "loopback": "^3.0.0"
I hope it's not recommended to copy the node_modules from our developement server to production server.
So how can we handle these type of issues?
When specifying a version number in the package.json there are a few different ways https://docs.npmjs.com/files/package.json#dependencies:
The way you have is the default, ^ which means
compatible with version
So ^3.0.0 will only install 3.0.0 if it is the latest minor and fix versions otherwise it will take whatever the latest version of loopback is on that day. Today that is 3.19.3.
The issue was introduced in version v3.10.1(thanks #vasan) so locally maybe you had version 3.10.0 then on the server you had 3.10.1
There is a good explanation about the version numbers in this question What's the difference between tilde(~) and caret(^) in package.json?
I would suggest using an exact version, i.e. 3.19.3 then using a service like rennovate, https://github.com/renovate-bot, to update your project to keep up to date with security patches
There is also another guard against this, package-lock.json https://docs.npmjs.com/files/package-lock.json introduced in version 5 of npm. If you check this file in it will make sure that wherever you run npm install the exact version of the npm module is installed wherever you run it.

Check whether script is Node or Phantom

I have a common module, providing the common directories for my project, which is used by both NodeJS and PhantomJS scripts. Anyone is aware of a simple clear function on how to return which script is running, if node.js or phantom.js?
For now, I use this method, but I don't know if it is the best approach
//parent directory of project directory tree
//tries to get according to Engine, Node or PhantomJS
var ROOT_DIR;
if (typeof __dirname !== 'undefined'){//nodeJS has __dirname
ROOT_DIR = path.resolve(__dirname, '.') + "/";
console.log("ROOT_DIR got on Node: " + ROOT_DIR);
}
else {//PhantomJS?
try{
var fs = require('fs');
ROOT_DIR = fs.absolute("./"); //it already leaves a trailing slash
console.log("ROOT_DIR got PhantomJS: " + ROOT_DIR);
}
catch(err){
throw "Engine not recognized, nor NodeJS nor PhantomJS";
}
}
Edit: this issue is slightly different from merely detecting node, since here we try also to detect PhantomJS, i.e., the difference is not between node and a browser but between node and phantomjs. Of course that the detection of node is similar, but many approaches to detect whether node is running or not, might in PhantomJS throw an exception.
Could this work?
const isNode = () => {
return process && process.argv[0] === 'node';
};
I used this to detect whether is nodeJS
if ((typeof process !== 'undefined') &&
(process.release.name.search(/node|io.js/) !== -1)){//node
}
else{//not node, im my case PhantomJS
}
It uses the node process object and since other modules might have that object name, within it it assures that attribute process.release.name has 'node' or 'io.js' within it.

What version of Node does my library support?

I'm hoping for a library or a tool which will run through my code and tell me what version of Node is required in order to run it. Perhaps better would be it alerts me to areas of the code which could be changed to support older versions.
Is there anything like that in the wild?
I'm not sure if this exactly what you are looking for, but there is an existing package.json property called "engines" where package developers can specify what version(s) they require. Not too difficult to use glob and semver packages to look through all package.json files with an "engines" requirement and compile that into an object of:
{
[version1]: [{ packageName, currentlySupported }, { ... }],
[version2]: [...],
...
}
Here is a rudimentary example of a script which will create that object for you:
npm install glob semver
checkversions.js:
const glob = require('glob');
const path = require('path');
const semver = require('semver');
const currentVersion = process.version;
const versions = {};
glob('node_modules/*/package.json', (err, files) => {
files.forEach((file) => {
const pkg = require(path.resolve(__dirname, file));
// only check add package if it specifies "engines"
if (pkg.engines && pkg.engines.node) {
const reqdVersion = pkg.engines.node.replace(/\s+/g, '');
// assume you are using a supported version
let currentlySupported = true;
// check if current node version satisfies package requirements
if (!semver.satisfies(currentVersion, reqdVersion)) {
currentlySupported = false;
}
if (!Array.isArray(versions[reqdVersion])) {
versions[reqdVersion] = [];
}
versions[reqdVersion].push({
package: file.replace(/node_modules\/(.*)\/package.json/, '$1'),
currentlySupported,
});
}
});
console.log(versions);
});
Run it:
node checkversions.js

Get list of all NPM dependencies minimum node.js engine version

We have an NPM project X. I want to get a distinct list of all the dependencies in the project and the minimum Node.js (engine) version that they need.
How can I do this?
The motivation is of course to discovery what the minimum Nodejs version we need to run in development and production.
npm ls | grep "engines"
something like that, except the above won't work, hopefully there is something more robust
I was able to accomplish this like so:
let npm = require('npm');
npm.load({}, function(err, npm) {
if(err) throw err;
npm.config.set('global', false); // => we don't want to consider global deps
npm.commands.list([], true, function(err, pkgInfo) {
let enginesList = Object.keys(pkgInfo.dependencies).map(function(k){
return {
dep: k,
engines: pkgInfo.dependencies[k].engines || {}
}
});
enginesList.forEach(function(val){
console.log(val.dep + ' => ', val.engines);
});
});
});

How can I check if npm packages support Node.js v0.8.x?

I have a deployed version 0.6 of Node.js with a considerable number of packages installed for various projects.
Is there a straight-forward way to check all of the packages that were installed using NPM to see if they support Node.js v 0.8.x?
I can see that the package.json files should say what version of Node they are for though I'm guessing that many will not include this - so I'm really only interested in packages that say they are definately not compatible with Node v 0.8.x
e.g. They have something like this in package.json:
"engines": {
"node": "<0.8.0"
},
or
"engines": {
"node": "=0.6.*"
},
I just want a simple list of packages that are incompatible.
Try this in the base directory of your application:
find . -name package.json -exec node -e 'var e = JSON.parse(require("fs").readFileSync(process.argv[1]))["engines"]; if (e && e.node) { var bad = false; if (e.node.match(/<\s*0\.[0-8]([^.]|\.0)/)) bad = true; if (e.node.match(/(^|[^>])=\s*0\.[^8]/)) bad = true; if (bad) console.log(process.argv[1], "appears no good (", e.node, ")") }' '{}' \;
Translation into normal style:
var fs = require("fs");
var contents = fs.readFileSync(process.argv[1]);
var package = JSON.parse(contents);
var engines = package.engines;
if (engines && engines.node) {
var node = engines.node,
bad = false;
if (node.match(/<\s*0\.[0-8]([^.]|\.0)/)) {
// Looks like "< 0.8.0" or "< 0.8" (but not "< 0.8.1").
bad = true;
}
if (node.match(/(^|[^>])=\s*0\.[^8]/)) {
// Looks like "= 0.7" or "= 0.9" (but not ">= 0.6").
bad = true;
}
if (bad) {
console.log(process.argv[1], "appears no good (", node, ")");
}
}
We then use find to run this on every package.json we can find.
Here's what I get when I run it over my express-template.coffee package:
./node_modules/jade/node_modules/commander/package.json appears no good ( >= 0.4.x < 0.8.0 )
./node_modules/mocha/node_modules/commander/package.json appears no good ( >= 0.4.x < 0.8.0 )
./node_modules/mocha/package.json appears no good ( >= 0.4.x < 0.8.0 )
It seems TJ has a thing against 0.8 ;-)
npm view <packageName> engines
See the npm view documentation for more info.
For example:
npm view jest verson returns the latest version, in my case 27.1.0
npm view jest engines gives you:
{ node: '^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0' }
Which tells you the latest version of jest, v27, supports node 10.13, 12.13, 14.15, and 15.
npm view jest#25 engines however, tells you it supports anything over node 8.3:
jest#25.5.2 { node: '>= 8.3' }
jest#25.5.3 { node: '>= 8.3' }
jest#25.5.4 { node: '>= 8.3' }
(this response is to an old question, but it still come up on my Google search)

Resources