How do I programmatically check the release status of the installed node.js version? - node.js

I want to include a check in a setup script that validates the installed node.js version is LTS. Something like this would be ideal
$ node -vvv
v16.3.0
Release v16
Status Active LTS
Codename Gallium
Initial Release 2021-04-20
Active LTS Start 2021-10-26
Maintenance LTS Start 2022-10-18
End-Of-Life 2024-04-30
Basically some way to get the information available on https://nodejs.org/en/about/releases/ but in a script. If there's some HTTP endpoint that provides this stuff in JSON that would work too.
I've looked through available options in the node, npm, nvm, and yarn CLI tools but none of them seem like they can do this.

One source of JSON info about nodejs releases is this endpoint:
https://nodejs.org/download/release/index.json
There, you get an array of objects that each look like this:
{
version: 'v16.14.1',
date: '2022-03-16',
files: [
'aix-ppc64', 'headers',
'linux-arm64', 'linux-armv7l',
'linux-ppc64le', 'linux-s390x',
'linux-x64', 'osx-arm64-tar',
'osx-x64-pkg', 'osx-x64-tar',
'src', 'win-x64-7z',
'win-x64-exe', 'win-x64-msi',
'win-x64-zip', 'win-x86-7z',
'win-x86-exe', 'win-x86-msi',
'win-x86-zip'
],
npm: '8.5.0',
v8: '9.4.146.24',
uv: '1.43.0',
zlib: '1.2.11',
openssl: '1.1.1m+quic',
modules: '93',
lts: 'Gallium',
security: false
},
If you filter that array by the lts property (any value other than false) and then sort by version, you will find the latest LTS release version and you can compare that to what is installed locally.
Here's a piece of nodejs code that gets that JSON, filters out items that aren't lts, then sorts by version. The top of the resulting array will be the latest LTS release version number. You could then programmatically compare that to what is installed locally. You could either just use process.version from within this script or you could run a child_process that captures the output from node -v.
import got from 'got';
// 'v10.16.3'
let versionRegex = /v(\d+)\.(\d+)\.(\d+)/;
// convert version string to a number for easier sorting
function calcVersion(x) {
const match = x.match(versionRegex);
if (!match) {
throw new Error(`version regex failed to match version string '${x}'`);
}
return (+match[1] * 1000000) + (+match[2] * 1000) + (+match[3]);
}
const data = await got("https://nodejs.org/download/release/index.json").json();
const lts = data.filter(item => item.lts);
// for performance reasons when sorting,
// precalculate an actual version number from the version string
lts.forEach(item => item.numVersion = calcVersion(item.version));
lts.sort((a, b) => b.numVersion - a.numVersion);
console.log("All LTS versions - sorted newest first");
console.log(lts.map(item => item.version));
console.log("Info about newest LTS version");
console.log(lts[0]);
console.log(`Newest LTS version: ${lts[0].version}`);
console.log(`Local version: ${process.version}`);
When I run this on my system at this moment, I get this output:
All LTS versions - sorted newest first
[
'v16.14.1', 'v16.14.0', 'v16.13.2', 'v16.13.1', 'v16.13.0',
'v14.19.0', 'v14.18.3', 'v14.18.2', 'v14.18.1', 'v14.18.0',
'v14.17.6', 'v14.17.5', 'v14.17.4', 'v14.17.3', 'v14.17.2',
'v14.17.1', 'v14.17.0', 'v14.16.1', 'v14.16.0', 'v14.15.5',
'v14.15.4', 'v14.15.3', 'v14.15.2', 'v14.15.1', 'v14.15.0',
'v12.22.11', 'v12.22.10', 'v12.22.9', 'v12.22.8', 'v12.22.7',
'v12.22.6', 'v12.22.5', 'v12.22.4', 'v12.22.3', 'v12.22.2',
'v12.22.1', 'v12.22.0', 'v12.21.0', 'v12.20.2', 'v12.20.1',
'v12.20.0', 'v12.19.1', 'v12.19.0', 'v12.18.4', 'v12.18.3',
'v12.18.2', 'v12.18.1', 'v12.18.0', 'v12.17.0', 'v12.16.3',
'v12.16.2', 'v12.16.1', 'v12.16.0', 'v12.15.0', 'v12.14.1',
'v12.14.0', 'v12.13.1', 'v12.13.0', 'v10.24.1', 'v10.24.0',
'v10.23.3', 'v10.23.2', 'v10.23.1', 'v10.23.0', 'v10.22.1',
'v10.22.0', 'v10.21.0', 'v10.20.1', 'v10.20.0', 'v10.19.0',
'v10.18.1', 'v10.18.0', 'v10.17.0', 'v10.16.3', 'v10.16.2',
'v10.16.1', 'v10.16.0', 'v10.15.3', 'v10.15.2', 'v10.15.1',
'v10.15.0', 'v10.14.2', 'v10.14.1', 'v10.14.0', 'v10.13.0',
'v8.17.0', 'v8.16.2', 'v8.16.1', 'v8.16.0', 'v8.15.1',
'v8.15.0', 'v8.14.1', 'v8.14.0', 'v8.13.0', 'v8.12.0',
'v8.11.4', 'v8.11.3', 'v8.11.2', 'v8.11.1', 'v8.11.0',
... 74 more items
]
Info about newest LTS version
{
version: 'v16.14.1',
date: '2022-03-16',
files: [
'aix-ppc64', 'headers',
'linux-arm64', 'linux-armv7l',
'linux-ppc64le', 'linux-s390x',
'linux-x64', 'osx-arm64-tar',
'osx-x64-pkg', 'osx-x64-tar',
'src', 'win-x64-7z',
'win-x64-exe', 'win-x64-msi',
'win-x64-zip', 'win-x86-7z',
'win-x86-exe', 'win-x86-msi',
'win-x86-zip'
],
npm: '8.5.0',
v8: '9.4.146.24',
uv: '1.43.0',
zlib: '1.2.11',
openssl: '1.1.1m+quic',
modules: '93',
lts: 'Gallium',
security: false,
numVersion: 16014001
}
Newest LTS version: v16.14.1
Local version: v16.13.2

Related

How can I force rustqlite to be built as statically linked when using sqlcipher?

I'm using rustqlite and am trying to configure it to use sqlcipher via a Cargo feature. In the usual case, rustqlite has a bundled feature to include the sqlite source. When changing to sqlcipher, the source isn't bundled anymore.
Locally I was able to install sqlcipher and compile my project (installed via brew install sqlcipher on Mac).
The resulting binary dynamically links to the local sqlcipher installation so I can no longer distribute the binary to customers
How I can I embed the library libsqlcipher.0.dylib into the binary? Customers can't be expected to install sqlcipher on their own.
For reference, looking at the linked libraries for a dummy project:
/tmp/try-sqlite/cipher$ otool -L target/release/cipher
target/release/cipher:
/usr/local/opt/sqlcipher/lib/libsqlcipher.0.dylib (compatibility version 9.0.0, current version 9.6.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
My project is simple:
Cargo.toml
[package]
name = "cipher"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[dependencies.rusqlite]
version = "0.24.2"
features = ["sqlcipher"]
main.rs
use rusqlite::{params, Connection, Result, NO_PARAMS};
use std::thread::sleep;
#[derive(Debug)]
struct Person {
id: i32,
name: String,
data: Option<Vec<u8>>,
}
fn main() -> Result<()> {
let conn = Connection::open("/tmp/enc2.db")?;
conn.execute("PRAGMA KEY='passphrase'", NO_PARAMS);
conn.execute(
"CREATE TABLE IF NOT EXISTS person (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
data BLOB
)",
NO_PARAMS,
)?;
let me = Person {
id: 0,
name: "Steven".to_string(),
data: None,
};
conn.execute(
"INSERT INTO person (name, data) VALUES (?1, ?2)",
params![me.name, me.data],
)?;
let mut stmt = conn.prepare("SELECT id, name, data FROM person")?;
let person_iter = stmt.query_map(NO_PARAMS, |row| {
Ok(Person {
id: row.get(0)?,
name: row.get(1)?,
data: row.get(2)?,
})
})?;
for person in person_iter {
println!("Found person {:?}", person.unwrap());
}
Ok(())
}
EDIT
I have a partial solution to static linking (not tested robustly yet) by exporting
SQLCIPHER_STATIC=1
otool -L /private/tmp/try-sqlite/cypher/target/debug/cypher
/private/tmp/try-sqlite/cypher/target/debug/cypher:
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
/usr/local/opt/openssl#1.1/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
Open issues
how to auto-export this environment variable (through toml config / build.rs - still working on that)
developer ergonomics - how to ensure that sqlcipher is installed on a dev machine (through build.rs / toml dev etc. config)
ensure that CI will run with SQLCIPHER_STATIC=1 (and have it installed)
It looks like this is currently not possible with the version published on crates.io.
But there is an open Pull Request that you can probably use for that.
First clone the working branch locally and then use it as a patch in your Cargo.toml like that:
[dependencies]
rusqlite = { version = "0.24.2", features = ["bundled-sqlcipher"] }
[patch.crates-io]
rusqlite = { path = "../path/to/your_patch" }
Note that I did not test this and because the feature only exists in the patch it might be that you need to include the feature branch like that:
[dependencies]
rusqlite = { path = "../path/to/your_patch", features = ["bundled-sqlcipher"] }
A word of Warning: As stated in the PR it is not clear if zetetic (the vendor of sqlcipher) is fine with that, so you should be cautious when you use this (especially in a commercial product).
Edit
This Issue / Comment is also relevant.

MongoDB node.js: index created ignoring TTL

I'm trying to create an index with TTL using the MongoDB driver for Node.js and a Mongo server hosted at mLab.
Node version 9.3.0.
Driver version 3.0.0.rc0
mongod version: 3.4.10 (MMAPv1)
Code in node.js:
var processCollection;
async function init (options) {
processCollection = await options.db.collection('processes');
await processCollection.dropIndexes();
await processCollection.createIndex(
{ 'modified': 1 },
{ expireAfterSeconds: 3600 }
);
}
Results in DB:
db['system.indexes'].find()
{
"v": 2,
"key": {
"modified": 1
},
"name": "modified_1",
"ns": "e-consular.processes"
}
The option expireAfterSeconds is missing in the resulting index. What am I doing wrong?
Collection.createIndex is broken in versions 3.0.0rc0 and 3.0.0 of the Node mongodb driver. It will ignore the options object argument.
This was fixed in version 3.0.1 of the driver. (You can see the fix here).
Update your driver to the latest version (e.g. npm i mongodb#3.0.4) and it should work as expected.

How I can start IE in 32bit mode in webdriver.io

I am running an WebDriver.io test using gulp-wdio npm pakage
on selenium-standalone
The Code that I run in gulp is:
gulp.task('e2e', function () {
return gulp.src('wdio.conf.js')
.pipe(wdio({
wdio: {
specs: './test/features/**/*.feature'
}
}));
});
And my wdio.conf.js define browsers this way:
capabilities: [
{
browserName: 'internet explorer',
version: 'ANY'
}
],
How ever the typing is very slow, i had found on the internet that running 32 bit version of the web-driver resolves the issue, how ever I can't find how to configure the capabilities or some other place to run the IE32 bit driver by default...
Any help will be appreciated #:-)
After 2 days of research I had found the solution !!!
There is a configuration file that need to be supplied to the selenium standalone
as shown in this Example
so our final setup is done in this way:
We have a configuration file called wdio.browsers.setup.js that contains the browsers setup:
module.exports = {
baseURL: 'https://selenium-release.storage.googleapis.com',
version: '3.3.1',
drivers: {
chrome: {
version: '2.29',
arch: process.arch,
// - Recent versions of the driver: https://sites.google.com/a/chromium.org/chromedriver/
baseURL: 'https://chromedriver.storage.googleapis.com'
},
ie: {
version: '3.0.0',
arch: 'ia32',
// - Recent versions of the driver: http://selenium-release.storage.googleapis.com/index.html
baseURL: 'https://selenium-release.storage.googleapis.com'
},
firefox: {
version: '0.15.0',
arch: process.arch,
baseURL: 'https://github.com/mozilla/geckodriver/releases/download'
}
}
};
and then inside wdio.conf.js we load it and assign to a special parameters
let browsersSetup = require('./wdio.browsers.setup');
exports.config = {
seleniumArgs: browsersSetup,
seleniumInstallArgs: browsersSetup,
After that all is working fine #:-)
Note: if you have your web-driver installed globally remove the global setup first it's located in:
C:\Users\%USERNAME%\AppData\Roaming\npm
Then you can run the local installation using:
./node_modules/.bin/selenium-standalone install --config=../../wdio.browsers.setup.js
Please find the below working solution for IE browser to install 32 bit:
services: ["selenium-standalone"],
seleniumArgs: {
drivers: {`enter code here`
ie: {
version: "3.4.0", // or whatever latest is
arch: "ia32", // forces use of 32 bit driver
baseURL: "https://selenium-release.storage.googleapis.com"
},
},
},
seleniumInstallArgs: {
drivers: {
ie: {
version: "3.4.0", // or whatever latest is
arch: "ia32", // forces use of 32 bit driver
baseURL: "https://selenium-release.storage.googleapis.com"
},
},
},

Mocha tests passing on localhost but not when running on TravisCI

I've written a test suite like so:
this.slow(1000)
this.timeout(6000)
var response, client
before(function(done) {
client = new UsergridClient()
client.GET(_collection, function(err, r) {
response = r
done()
})
})
it('should not fail when a callback function is not passed', function() {
// note: this test will NOT fail gracefully inside the Mocha event chain
client.GET(_collection)
})
it('should return a 200 ok', function() {
// ******** LOGGING ********* //
console.log(response)
// ******** LOGGING ********* //
response.statusCode.should.equal(200)
})
it('response.entities should be an array', function() {
response.entities.should.be.an.Array
})
it('response.first should exist and have a valid uuid', function() {
response.first.should.be.an.Object.with.property('uuid').with.a.lengthOf(36)
})
it('response.entity should exist and have a valid uuid', function() {
response.entity.should.be.an.Object.with.property('uuid').with.a.lengthOf(36)
})
it('response.last should exist and have a valid uuid', function() {
response.last.should.be.an.Object.with.property('uuid').with.a.lengthOf(36)
})
When running this test locally, all tests pass. When running on TravisCI though, the response variables are being reported as undefined even inside the tests. This suggests to me that there's some sort of asynchronous mixup, but using the done() callback on the before() should mitigate that, shouldn't it? I even tried adding done callbacks to every subsequent test, but that still isn't working.
The notable error here is:
TypeError: Cannot read property 'property' of undefined
and it looks like that's being thrown from:
response.first.should.be.an.Object.with.property('uuid').with.a.lengthOf(36)
which makes me think Travis' environment doesn't like Object.with or maybe even just .with?
Here's my .travis.yml file:
language: node_js
node_js:
- '5.1.0'
install:
- 'npm install'
- 'npm -g install mocha'
script:
- 'mocha tests'
And here's the run log:
Using worker: worker-linux-docker-7421b08d.prod.travis-ci.org:travis-linux-8
system_info
Build system information
Build language: node_js
Build group: stable
Build dist: precise
Build image provisioning date and time
Thu Feb 5 15:09:33 UTC 2015
Operating System Details
Distributor ID: Ubuntu
Description: Ubuntu 12.04.5 LTS
Release: 12.04
Codename: precise
Linux Version
3.13.0-29-generic
Cookbooks Version
a68419e https://github.com/travis-ci/travis-cookbooks/tree/a68419e
GCC version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
clang version 3.4 (tags/RELEASE_34/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
Pre-installed Ruby versions
ruby-1.9.3-p551
Pre-installed Node.js versions
v0.10.36
Pre-installed Go versions
1.4.1
Redis version
redis-server 2.8.19
riak version
2.0.2
MongoDB version
MongoDB 2.4.12
CouchDB version
couchdb 1.6.1
Neo4j version
1.9.4
RabbitMQ Version
3.4.3
ElasticSearch version
1.4.0
Installed Sphinx versions
2.0.10
2.1.9
2.2.6
Default Sphinx version
2.2.6
Installed Firefox version
firefox 31.0esr
PhantomJS version
1.9.8
ant -version
Apache Ant(TM) version 1.8.2 compiled on December 3 2011
mvn -version
Apache Maven 3.2.5 (12a6b3acb947671f09b81f49094c53f426d8cea1; 2014-12-14T17:29:23+00:00)
Maven home: /usr/local/maven
Java version: 1.7.0_76, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-7-oracle/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "3.13.0-29-generic", arch: "amd64", family: "unix"
git.checkout
0.36s$ git clone... cloning
remote: Counting objects: 315, done.
remote: Compressing objects: 100% (153/153), done.
remote: Total 315 (delta 74), reused 0 (delta 0), pack-reused 161
Receiving objects: 100% (315/315), 48.32 KiB | 0 bytes/s, done.
Resolving deltas: 100% (156/156), done.
Checking connectivity... done.
$ cd path/to/proj
$ git checkout -qf <hash>
This job is running on container-based infrastructure, which does not allow use of 'sudo', setuid and setguid executables.
If you require sudo, add 'sudo: required' to your .travis.yml
See http://docs.travis-ci.com/user/workers/container-based-infrastructure/ for details.
3.13s$ nvm install 5.1.0
######################################################################## 100.0%
Checksums empty
Now using node v5.1.0
$ node --version
v5.1.0
$ npm --version
3.3.12
$ nvm --version
0.23.3
install.1
17.95s$ npm install
npm WARN engine underscore.inflection#1.3.0: wanted: {"node":">=0.10.0 <0.12"} (current: {"node":"5.1.0","npm":"3.3.12"})
npm WARN deprecated lodash#0.9.2: lodash#<3.0.0 is no longer maintained. Upgrade to lodash#^3.0.0.
npm WARN deprecated lodash#2.4.2: lodash#<3.0.0 is no longer maintained. Upgrade to lodash#^3.0.0.
app#2.0.0 /home/travis/build/path/to/app
... list of packages
npm WARN EPACKAGEJSON app#2.0.0 No repository field.
install.2
1.71s$ npm -g install mocha
/home/travis/.nvm/versions/node/v5.1.0/bin/mocha -> /home/travis/.nvm/versions/node/v5.1.0/lib/node_modules/mocha/bin/mocha
/home/travis/.nvm/versions/node/v5.1.0/bin/_mocha -> /home/travis/.nvm/versions/node/v5.1.0/lib/node_modules/mocha/bin/_mocha
/home/travis/.nvm/versions/node/v5.1.0/lib
... list of packages
1.50s$ mocha tests
init() / initSharedInstance()
✓ should be an instance of Client
Client
initialization
✓ should fail to initialize without an orgId and appId
✓ should initialize using properties defined in config.json
✓ should initialize when passing orgId and appId as arguments, taking precedence over config
✓ should initialize when passing an object containing orgId and appId, taking precedence over config
GET()
IncomingMessage {
_readableState:
... omitted
readable: false,
domain: null,
headers:
... omitted
client:
... omitted
req:
... omitted
request:
... omitted
toJSON: [Function: responseToJSON],
caseless:
Caseless {
dict:
{ 'access-control-allow-origin': '*',
'content-type': 'application/json',
date: 'Sun, 29 Nov 2015 22:44:54 GMT',
server: 'Apache-Coyote/1.1',
'set-cookie': [Object],
'transfer-encoding': 'chunked',
connection: 'Close' } },
read: [Function],
body:
{ action: 'get',
application: '19748000-24b6-11e3-9877-6d1a3f81ba2f',
params: {},
path: '/tests',
uri: 'https://api.mydomain.com/myorg/sandbox/tests',
entities:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
timestamp: 1448837094623,
duration: 65,
organization: 'myorg',
applicationName: 'sandbox',
cursor: 'LTU2ODc0MzQzOkdCcGJDbVpTRWVXVndibnE5RUdORGc',
count: 7 },
entities:
[ ],
first:
{ uuid: 'b3037a1a-4cd6-11e5-8aa2-0b8eb3ce43ee',
type: 'test',
name: '01',
created: 1440692071473,
modified: 1440692071473,
food: 'pizza',
metadata: { path: '/tests/b3037a1a-4cd6-11e5-8aa2-0b8eb3ce43ee' },
value: 1 },
entity:
{ uuid: 'b3037a1a-4cd6-11e5-8aa2-0b8eb3ce43ee',
type: 'test',
name: '01',
created: 1440692071473,
modified: 1440692071473,
food: 'pizza',
metadata: { path: '/tests/b3037a1a-4cd6-11e5-8aa2-0b8eb3ce43ee' },
value: 1 },
last:
{ uuid: '181a5b0a-6652-11e5-95c1-b9eaf4418d0e',
type: 'test',
created: 1443493848240,
modified: 1443493848240,
metadata: { path: '/tests/181a5b0a-6652-11e5-95c1-b9eaf4418d0e' },
title: 'Charlotte\'s Web' } }
✓ should not fail when a callback function is not passed
✓ should return a 200 ok
✓ response.entities should be an array
1) response.first should exist and have a valid uuid
2) response.entity should exist and have a valid uuid
3) response.last should exist and have a valid uuid
POST()
✓ should not fail when a callback function is not passed
✓ should return a 200 ok
4) response.entities should be an array
5) response.entity should exist and have a valid uuid
✓ response.entity.author should equal "Sir Arthur Conan Doyle"
PUT()
✓ should not fail when a callback function is not passed
✓ should return a 200 ok
6) response.entities should be an array
7) response.entity should exist and its uuid should the uuid from the previous POST requets
✓ response.entity.narrator should equal "Peter Doyle"
DELETE()
✓ should not fail when a callback function is not passed
✓ should return a 200 ok
✓ response.error.name should equal "service_resource_not_found"
authenticateApp()
✓ should return a 200 ok
✓ should have a valid token
✓ client.appAuth.token should be set to the token returned from
✓ client.appAuth.expiry should be set to a future date
appAuth / setAppAuth()
✓ should initialize by passing a list of arguments
✓ should initialize by passing an object
✓ should initialize by passing an instance of AppAuth
✓ should initialize by setting to an instance of AppAuth
Query
_type
✓ query._type should equal "cats" when passing "type" as a parameter to Query
✓ query._type should equal "cats" when calling .type() builder method
✓ query._type should equal "cats" when calling .collection() builder method
_limit
✓ query._limit should equal 10
_ql
✓ should support complex builder syntax (chained constructor methods)
✓ not operator should precede conditional statement
✓ string values should be contained in single quotes
✓ boolean values should not be contained in single quotes
✓ float values should not be contained in single quotes
✓ integer values should not be contained in single quotes
✓ uuid values should not be contained in single quotes
36 passing (696ms)
7 failing
1) Client GET() response.first should exist and have a valid uuid:
TypeError: Cannot read property 'property' of undefined
at Context.<anonymous> (tests/lib/client.test.js:69:48)
2) Client GET() response.entity should exist and have a valid uuid:
TypeError: Cannot read property 'property' of undefined
at Context.<anonymous> (tests/lib/client.test.js:73:49)
3) Client GET() response.last should exist and have a valid uuid:
TypeError: Cannot read property 'property' of undefined
at Context.<anonymous> (tests/lib/client.test.js:77:47)
4) Client POST() response.entities should be an array:
TypeError: Cannot read property 'a' of undefined
at Context.<anonymous> (tests/lib/client.test.js:108:50)
5) Client POST() response.entity should exist and have a valid uuid:
TypeError: Cannot read property 'property' of undefined
at Context.<anonymous> (tests/lib/client.test.js:112:49)
6) Client PUT() response.entities should be an array:
TypeError: Cannot read property 'a' of undefined
at Context.<anonymous> (tests/lib/client.test.js:146:50)
7) Client PUT() response.entity should exist and its uuid should the uuid from the previous POST requets:
TypeError: Cannot read property 'property' of undefined
at Context.<anonymous> (tests/lib/client.test.js:150:49)
The command "mocha tests" exited with 7.
Done. Your build exited with 1.
Somehow, I'm not entirely sure how, this syntax was working fine using whatever version of should.js I had installed locally. When deploying to TravisCI, it must have installed a newer version which caused any type-checking assertion to fail.
Where this previously worked (according to this):
response.first.should.be.an.Object.with.property('uuid').with.a.lengthOf(36)
It actually needed to be called with parentheses:
response.first.should.be.an.Object().with.property('uuid').with.a.lengthOf(36)
// ^^
... as indicated in the official docs.

Check for current Node Version

I need to programmatically access the current node version running in a library I am writing. Can't seem to find this in the docs.
Look at process.version property.
process.version.match(/^v(\d+\.\d+)/)[1]
if process.version is 'v0.11.5', then get 0.11 .
Actually it would be better to use process.versions object which provides a lot of versions for the different node components.
Example:
{
http_parser: '2.5.2',
node: '4.4.3',
v8: '4.5.103.35',
uv: '1.8.0',
zlib: '1.2.8',
ares: '1.10.1-DEV',
icu: '56.1',
modules: '46',
openssl: '1.0.2g'
}
Use semver to compare process.version:
const semver = require('semver');
if (semver.gte(process.version, '0.12.18')) {
...
}
If you need to only check for the major version, you can use this quick-and-dirty snippet:
const NODE_MAJOR_VERSION = process.versions.node.split('.')[0];
if (NODE_MAJOR_VERSION < 12) {
throw new Error('Requires Node 12 (or higher)');
}
Notes:
process.versions.node is easier to work with than process.version, as you do not have to worry about whether the version starts with a leading v.
If you still need to distinguish between ancient versions (e.g., 0.10 and 0.12), this will not work, as they will all be considered version "0".
I refined alsotang's answer a bit to compare versions:
const m = process.version.match(/(\d+)\.(\d+)\.(\d+)/);
const [major, minor, patch] = m.slice(1).map(_ => parseInt(_));
To perform an assertion, do it like this:
if (major >= 13 || (major >= 12 && minor >= 12)) {
console.log("NodeJS is at least v12.12.0. It is safe to use fs.opendir!");
}
This can be shortened to a one-liner to use in bash:
NODE_VERSION=$(node -e "const v = process.version.match(/(\\d+)\.(\\d+)\.(\\d+)/).slice(1).map(_ => parseInt(_)); console.log(v[0] >= 13 || (v[0] >= 12 && v[1] >= 12))")
if $NODE_VERSION -eq "true" ;
then
echo "NodeJS is at least v12.12.0."
fi
or PowerShell:
$nodeVersion = $(node -e "const v = process.version.match(/(\d+)\.(\d+)\.(\d+)/).slice(1).map(_ => parseInt(_)); console.log(v[0] >= 13 || (v[0] >= 12 && v[1] >= 12))")
if ($nodeVersion -eq "true") {
Write-Host "NodeJS is at least v12.12.0."
}
If you access node js running environments, there are 2 main entries: (one simeple, one detail)
process.version will give you:
'v10.16.0'
process.versions will give you:
{ http_parser: '2.8.0',
node: '10.16.0',
v8: '6.8.275.32-node.52',
uv: '1.28.0',
zlib: '1.2.11',
brotli: '1.0.7',
ares: '1.15.0',
modules: '64',
nghttp2: '1.34.0',
napi: '4',
openssl: '1.1.1b',
icu: '64.2',
unicode: '12.1',
cldr: '35.1',
tz: '2019a' }
I had the similar issue with my codebase. I wanted to know the current NodeJs version I am going to use to run my server at runtime. For that, I wrote a code which can be run before starting the Server using npm run start script.
Found below code helpful from this question.
'use strict';
const semver = require('semver');
const engines = require('./package').engines;
const nodeVersion = engines.node;
// Compare installed NodeJs version with required NodeJs version.
if (!semver.satisfies(process.version, nodeVersion)) {
console.log(`NodeJS Version Check: Required node version ${nodeVersion} NOT SATISFIED with current version ${process.version}.`);
process.exit(1);
} else {
console.log(`NodeJS Version Check: Required node version ${nodeVersion} SATISFIED with current version ${process.version}.`);
}
My package.json looks like this:
{
"name": "echo-server",
"version": "1.0.0",
"engines": {
"node": "8.5.0",
"npm": "5.3.0"
},
"description": "",
"main": "index.js",
"scripts": {
"check-version" : "node checkVersion.js",
"start-server" : "node app.js"
"start" : "npm run check-version && npm run start-server",
"test": "npm run check-version && echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bluebird": "^3.5.1",
"express": "^4.16.3",
"good-guy-http": "^1.10.3",
"semver": "^5.5.0"
}
}
Do run npm install command before you run npm run start command to run your project.
also instead of writing this whole as suggested by #alsotang
Number(process.version.match(/^v(\d+\.\d+)/)[1])
(not saying this is a bad solution).
you can simply write
parseFloat(process.versions.node); it is versions (plural) not version
to get same or (similar) result and is easy to read
How about this, for major, minor
const [NODE_MAJOR_VERSION, NODE_MINOR_VERSION] = process.versions.node.split('.')

Resources