How to make npm use the lowest version that matches all requirements - npm

We're using NodeJS for some projects and are faced with an issue that must have a simple solution (seeing as nobody else seems to have the problem).
In the packages.json there are a bunch of dependencies mentioned with a minimum version, each of which may have overlapping dependencies of their own. The default way a dependency is added is using the ^ operator which seems to mean 'compatible with' or 'same major version, but minor versions may differ'.
The way I understand npm to work is on npm install to take the highest minor version available that matches. Unfortunately 'compatible with' is not quite as enforced as you'd hope.
The situation this puts us in is that for instance on a developer machine version 1.1.0 is installed, but between development and publishing a new version 1.2.0, that has a bug, is introduced. On our build machine a fresh build is made which ends up using 1.2.0 and we've introduced a bug that wasn't there in development.
We tried changing the ^ operator to = for instance, but this gives us trouble when dependencies have subdependencies that aren't compatible with the requested version.
All in all I'm a bit confused, but this thing keeps biting us anytime something changes since the development machines don't do anything on npm install if the package is already there, but the build machine always gets fresh copies.
I know from NuGet that it always takes the lowest version that matches all combined requirements. Since this is always the same for a given set of dependencies, I much prefer this approach. Is there a way to make npm work like this too?

To answer my own question:
npm has introduced a new command npm ci which does something similar to npm install but enforces that the specific versions are used that were also used when a package was initially added by using the package-lock file.
See https://docs.npmjs.com/cli/ci for more information

Related

How to limit acceptable version ranges for an entire product dependency tree?

Recently new versions of packages came out, which required new versions of another library (which in turn broke my production builds). However, they both only increased their patch version number (one was #types/prettier and the other one cheerio).
My projects use these libs only indirectly, so even though I set all my dependencies to a fixed version number, these changes affected my builds and cause a lot of grief.
If I could tell NPM not to consider newer versions of a package and always use only the specified one, this kind of problem would probably not appear. Is it possible to force NPM not to install newer versions of dependencies, even if they allow ranges?

Upgrading NPM from 5.8 to latest

I want to look at upgrading NPM on a project I'm working on from 5.8.0 to the latest version.
Is this something that is safe to do without breaking any packages i have installed? And if there's a chance it might, what is the best method for testing those packages to make sure everything is running correctly still?
Updating NPM is unlikely to break anything. However your packages may require a certain version of Node.js to function properly.
There also isn't really a "best method" to check if everything runs correctly. Ill refer you to this answer which has a few options you can try.

How to install the latest SNAPSHOT version in npm?

We have a private nexus repository and publishing all the npm modules there. We have Module A and Module B, B is dependent on A. Here I am getting an issue with installing the latest SNAPSHOT version. For example:
Module A has published versions like
'1.0.0-SNAPSHOT', '1.0.1-SNAPSHOT', and '1.0.0'
In Module B package.json, I added the dependency like
"Module A": "^1.0.0-SNAPSHOT"
As I mentioned "^" in the dependency, it should install the latest version (i.e, 1.0.1-SNAPSHOT), But I am not sure why it is installing '1.0.0' instead '1.0.1-SNAPSHOT.
Your help would be greatly appreciated. Thanks in Advance.
Avoid releasing and using snapshot dependencies. When you publish a release, it should not contain -SNAPSHOT. Referring to a proper release is mandatory in order to be sure you are testing/executing the right code without side effects due to regression problems. You need to know in every moment which version you are using, that is very important, so relying on latest versions of your modules might not be the best solution, it doesn't worth it either if you are precise with major, minor and patch bits in order to avoid breaking changes or unexpected behaviors.
If you really need to develop them together you can use npm link command instead.

Any way to check that package.json engines satisfies version of global installed packages/binaries?

As I understand, the engines object is only for cases where someone installs my application. I would like to have something similar where I can prevent compiling errors on employee systems (because of wrong node versions etc.) before they happen.
I found that there are two packages:
https://github.com/jgillich/npm-check-engines/blob/master/index.js
https://github.com/kruppel/check-engines
But they are not working or not doing what I want.
It would be nice to have a script running before npm install that checks these engines versions and if they are available in path.
I created a package that does this.
https://github.com/muuvmuuv/npm-supervisor
It can be run via npm before installation and will check if a version in engines satisfies the global or local installed version.

Is it possible to blacklist a NPM package version either in the project or on the machine config?

Given the news that npm 5.7.0 had some issues in production, I'm wondering if it's possible to blacklist a package version either in package.json or on the machine level perhaps in .npmrc or .yarnrc.
The behaviour I'm expecting is that upgrades are possible, so this is not a fixed semver version. SemVer has intentionally avoided defining version skipping in the spec because,
SemVer is meant to communicate what type of changes have occurred, not
'how much' change has occurred. If a user wants to know the details of
how much has changed, they should look at the changelog. A long
changelog tells them it's a big update.
But as a user I may know beforehand that I never want this version. For example, never use 5.7.0 but 5.7.1 is ok.
If you have package A that depends on B and B has a known bad version, you can define a version range with a hole in it. See last paragraph of https://docs.npmjs.com/misc/semver. I am not aware of any way to globally black-list such a version on your system however, so if you install A and it doesn't have a version hole on its dependency on B, you might have gotten the bad version, but in the example you state above, the offending version was pulled from publication as the news was released regarding the defect.
One thing you can do is purge your cache of any bad package versions to insure that they can't be used to resolve dependencies.