Search code examples
node.jsdependenciesnpmversioningdependency-management

"npm update" is installing a beta version of the module over the stable version that installed after "npm install"


Currently the npm package mongoose is on version 3.8.12. Running npm install mongoose --save correctly installs version 3.8.12 and saves the dependency to package.json as follows:

"dependencies": {
  "mongoose": "^3.8.12"
}

If you look in node_modules/mongoose/package.json you can see that the installed version is indeed 3.8.12. However, if I now run npm update then npm will go ahead and install an unstable version of mongoose (3.9.0). I assume this is because of the caret in the dependency entry which tells npm to go ahead and upgrade minor versions (i.e. 3.8 to 3.9). That's fine, except I don't want any prerelease versions. If I modify the dependency and remove the caret then npm update works as expected, except of course that I now have to manually upgrade the dependency version even for minor and patch updates.

You can see from running npm info mongoose that they have a "latest" tag and an "unstable" tag.

So clearly npm install uses latest unless otherwise specified, while npm update is ignoring the tag altogether and grabbing the latest minor version it's aware of.

Is there a way to modify the dependency so npm update will pull in the latest minor version but ignore any prerelease versions?

UPDATE

Same issue occurs if I try to use 3.x.x as the dependency. I was hoping that would still allow me to upgrade through minor versions without prerelease versions but that's not the case :/

Tilde (~3.8.12) technically works but it's a bandaid. The only reason it "works" is because the breaking changes being introduced are in 3.9.0-unstable and tilde doesn't allow npm to upgrade across minor versions. If these "unstable" changes were introduced in 3.8.13-unstable then this same issue would occur even when using the tilde.

UPDATE 2

I also tried manually specifying the "latest" tag: ^3.8.12-latest. That didn't change anything; npm update ignores the tag entirely, even if it's explicitly in the dependency listing itself :/


Solution

  • semver does not specify a way to tell apart stable and unstable versions.

    As you said the caret would allow for npm update to install any 3.x.x version, while the tilde would allow any 3.8.x version even if the next version is called 3.8.13-broken.

    Sadly, the same happens with any semver operator, so there's no escape.

    As you see, you are better off using the specific version 3.8.12.