Choosing module installation, javascript or native module - node.js

I have a module and I'd like to let the user decide which version he wants to use, the purely written in javascript or the native written in C (so he needs to compile it first).
The npm install command doesn't have any option but you can choose the version so I can create two branches: v1.x for the js and v2.x for the native.
If the user wants to install the module written in javascript:
"dependencies": {
"my-module": "1.x"
}
If the user wants to install the native module:
"dependencies": {
"my-module": "2.x"
}
Are there other better ways to publish the purely and native modules with the same module name?

OK, that's not exactly what you are looking for, but here goes…
You are trying to find an NPM equivalent to Gentoo Use Flags, which doesn't exist. The closest thing you could do it publish your pure-JS version and have users directly link to the git repo instead if they want to use the native version.
In package.json:
"dependencies": {
"mymodule": "1.2.3" // js version
}
"dependencies": {
"mymodule": "http://github.com/mymodule-native" // native version
}
You users won't have to change their require to switch between versions, only a single line in package.json.
Another solution would be to attempt to build the native version without raising an error if it fails. Then you can have a simple setting in your module to switch between implementations. You can have a look at this other stackoverflow thread.

Related

How to dynamically install a particular version of a NPM package based on local Node.js version?

I did Google about this but no luck.
Basically, I need a particular version of a NPM package (A) to be installed if the local Node.js version is X, if not then install version B of that NPM package. This needs to be a part of build process, so its all dynamic.
If there was a way to have this config in package.json, then it would have been a straightforward solution for me.
How do I achieve this?
You can achieve this by using Yarn as your dependency management tool in combination with the Selective Versions Resolutions feature.
More specifically in your case you'd use it as described in the "Mapping version specifications" format, based on that your package.json you would include something like the following, assuming that version X=1.0.3 and version B=2.0.0 in the following example:
"devDependencies": {
"a": "1.0.3"
},
"resolutions": {
"a#==1.0.3": "a#2.0.0"
}

How can I express alternative dependencies in NPM?

When expressing the dependencies of a Debian package, you can use syntax like exim | mail-transport-agent to indicate that your package needs either exim or mail-transport-agent, but it doesn't care which.
I want to express something similar in NPM. Is there a way to do it? Specifically suppose I want my application to express a dependency on either mikesthing-impl1 v1.7 better or mikesthing-impl2 v2.1 or better. I'd like to be able to say something like:
dependencies: {
"mikesthing": {
"mikesthing-impl1": "^1.7",
"mikesthing-impl2": "^2.1"
}
}
Is there a way?
No, there is no functionality within a package.json to specify that sort of logic. However, you can implement a postinstall script in the scripts that will be executed after all other dependencies have been installed and in which you can script out this kind (or any kind) of behavior.
e.g. (in package.json)
"scripts": {
"postinstall": "./bin/postinstall"
A good place to start is to run npm view {package} to get back a JSON object that details what versions are available in the registry.

How to fix broken Typescript definitions when definitions files are updated

I have a project that uses Typescript, using the newer #types/foo style of installing typings packages.
When my build server installs all npm modules, sometimes I get a complete failure when compiling the typescript as some dependent definitions are no longer matching up.
For instance, I now have a problem with #types/gulp. In its package.json, dependencies are listed as:
"dependencies": {
"#types/node": "*",
"#types/orchestrator": "*",
"#types/vinyl": "*"
},
But now #types/orchestrator has updated, and it now breaks the version of #types/gulp that I have defined in my apps package.json.
How am I supposed to lock down version of dependencies like this so I no longer get this problem, or is there another workaround?
Unfortunately, I suddenly get these issues which sets development back by hours trying to sort it out. This makes using Typescript in a fast moving environment difficult.
How am I supposed to lock down version of dependencies like this so I no longer get this problem
Run npm shrinkwrap or just specify an exact version:
"#types/vinyl": "6.3.12"

How to specify/enforce a specific node.js version to use in package.json?

I am searching for a way to break the build, if a user is using a different node.js version as defined in the project.
Ideally to put some checks in grunt or bower or npm to stop, if a certain npm/node version is not used to run the current build.
Even though engineStrict is deprecated, you can still accomplish this behavior without needing to use an additional script to enforce a Node version in your project.
Add the engines property to your package.json file. For example:
{
"name": "example",
"version": "1.0.0",
"engines": {
"node": ">=14.0.0"
}
}
Create a .npmrc file in your project at the same level as your package.json.
In the newly created .npmrc file, add engine-strict=true.
engine-strict=true
This will enforce the engines you've defined when the user runs npm install. I've created a simple example on GitHub for your reference.
You can use the "engineStrict" property in your package.json
Check the docs for more information: https://docs.npmjs.com/files/package.json
Update on 23rd June 2019
"engineStrict" property is removed in npm 3.0.0.
Reference : https://docs.npmjs.com/files/package.json#enginestrict
"engineStrict" has been removed and "engines" only works for dependencies. If you want to check Node's runtime version this can work for you:
You call this function in your server side code. It uses a regex to check Node's runtime version using eremzeit's response It will throw an error if it's not using the appropriate version:
const checkNodeVersion = version => {
const versionRegex = new RegExp(`^${version}\\..*`);
const versionCorrect = process.versions.node.match(versionRegex);
if (!versionCorrect) {
throw Error(
`Running on wrong Nodejs version. Please upgrade the node runtime to version ${version}`
);
}
};
usage:
checkNodeVersion(8)
You can use the engines property in the package.json file
For example, if you want to make sure that you have a minimum of node.js version 6.9 and a maximum of 6.10, then you can specify the following
package.json
{
"name": "Foo",
....
"engines": {
"node": ">=6.9 <=6.10"
}
}
If you want to enforce a specific version of npm, you might use:
https://github.com/hansl/npm-enforce-version
If you want to enforce a version of node when executing you can read the version of node that is currently running by checking against:
process.versions
For more info: https://nodejs.org/api/process.html#process_process_versions

Determine NPM modules used from a running node.js application

Other than grabbing the package.json file at the project root is there a way to determine the list of dependencies of a running node.js application? Does node keep this meta information available as some var in the global namespace?
If you are just looking for the currently installed npm packages in the application directory, then you can install the npm package (npm install -g npm) and programatically invoke ls to list the installed packages and the dependency trees.
Obviously, this has no bearing on whether the installed packages are actually require'd in the application or not.
Usage is not that well documented but this should get you started.
var npm = require('npm');
npm.load(function(err, npm) {
npm.commands.ls([], true, function(err, data, lite) {
console.log(data); //or lite for simplified output
});
});
e.g.:
{ dependencies:
{ npm: { version: '1.1.18', dependencies: [Object] },
request: { version: '2.9.202' } } }
Otherwise, I believe the only other option is to introspect the module module to get information pertaining to the currently loaded/cached module paths. However this definitely does not look to have been developed as a public API. I'm not sure if there are any alternatives so would be keen to hear if there are e.g.
var req = require('request'); // require some module for demo purposes
var m = require('module');
// properties of m contain current loaded module info, e.g. m._cache
I believe you could use require-analyzer, which sort of works according to Isaacs(could miss some). You could hear this in Nodeup's first podcast from 11:55.
Or you could try James node-detective which probably will find your dependencies better(but not by running code), but because of Javascript dynamic nature(12:46).
detective
Find all calls to require() no matter how crazily nested using a
proper walk of the AST.
P.S: to expose those package.json variables to node.js you could use node-pkginfo

Resources