Bug in NPM version - blacklist the patch version - npm

Say we publish an NPM package that ends up having a bug say it is version 1.0.056.
is there a way to tell NPM to blacklist it, meaning if users have this in package.json:
^1.0.05
that it would endeavor to only install 1.0.057 or 1.0.055?
The idea is when you patch the bug, if it doesn't impact any of the exposed API, then not much reason to make a big semver change? Or maybe on the other hand an important bugfix should call for a minor version change?
Obviously NPM doesn't encourage people to delete packages, we want immutability, but unless a user explicitly requests that version, I want NPM to avoid installing it at all costs?

npm deprecate covers a historical version when you discover problem later:
npm deprecate <pkg>[#<version>] <message>
This command will update the npm registry entry for a package, providing a deprecation warning to all who attempt to install it.
If it was only just published (72 hours) then there is also:
npm unpublish [<#scope>/]<pkg>[#<version>]
This removes a package version from the registry, deleting its entry and removing the tarball.
https://www.npmjs.com/policies/unpublish
https://docs.npmjs.com/cli/unpublish

Related

npm deprecated package [duplicate]

This question already has answers here:
npm WARN deprecated tar#2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asap
(4 answers)
Closed 1 year ago.
npm WARN deprecated tar#2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.
changed 67 packages, and audited 68 packages in 7s
4 packages are looking for funding
run `npm fund` for details
2 high severity vulnerabilities
Some issues need review, and may require choosing
a different dependency.
Run `npm audit` for details.
This kind of problem is quite common for npm users. Your package.json file mentions multiple npm packages you need. And, each of those package's package.json file in turn refers to other packages, and so on. Somewhere in there some package refers to version 2.2.2 of tar. But the current version of tar is 6.2.2.
You can, as the error message says, run npm audit to find the offending package: that is, the package that wants the old version of tar (tar#2.2.2).
How to try to fix this?
If it's your package.json that loads tar#2.2.2 try doing these two commands.
npm remove tar --save
npm install tar --save
to get the latest.
Try running npm update --save. It will examine your nest of npm packages, and bring them up to more recent versions. That may, or may not, replace the offending package with a more recent version. It does this by updating a file called package-lock.json containing the explicit versions. If that doesn't work ...
Try running npm audit again to see what the situation is. Then, try npm audit --fix . If that doesn't work ...
File an issue on the github repository of the offending package asking for an update.
Look for another package with the same functionality as the offending package and replace it.
Decide you will live with the warning. (If your software is used in production, that may be unwise, because cybercreeps.)
Ask another question here and mention the offending package.

What does "npm audit fix" exactly do?

npm audit fix is intended to automatically upgrade / fix vulnerabilities in npm packages. However, I haven't found out what it exactly does to fix those vulnerabilities.
I assumed that npm audit fix would upgrade dependencies and dependencies' dependencies to the latest versions that are allowed by the semver-definitions of the packages – effectively the same as rm package-lock.json; npm install. However npm audit fix still performs a lot of changes after lock file removal + reinstall.
What exactly does npm audit fix do? Does it for example install versions of dependencies newer than those allowed by the corresponding package.json (but still semver-compatible)?
From NPM's site on their audit command:
npm audit fix runs a full-fledged npm install under the hood
And it seems that an audit fix only does semver-compatible upgrades by default. Listed earlier in the document:
Have audit fix install semver-major updates to toplevel dependencies, not just semver-compatible ones:
$ npm audit fix --force
As for the lock file, it is regenerated each time you run a command that changes package.json. There is more information about that in an answer here as well as in the official documentation.
In my understanding is not only "upgrading" but sometimes also downgrading in order to install the stable version that fix the issue, sometimes those issues comes in newer versions that maybe have introduced bugs or simply do not match with previous package's API etc.
E.g in my case for example npm install have upgrade react-script to 5.0.0 that has some issue and after have run:
npm audit fix --force
The force flag does : To address all issues (including breaking changes), run: npm audit fix --force
it installed the 3.0.1 with following message:
npm WARN audit Updating react-scripts to 3.0.1,which is a SemVer major change.
So it does the upgrade to the stable version of that package that fix the issue.
On top, though docs state "is running npm install under the hood" but not in the sense of installing newest version of a dependency, but could be useful also to check what happens with npm ci What is the difference between "npm install" and "npm ci"?

Is npm install package#latest stable or does it also include alpha/beta version?

I just want some confirmation as I've always been using #latest for a while with my packages and want to know if I'm really installing a stable version or can possibly install a alpha/beta version of the package.
I'm pretty sure this is meant for stable versions as they tell you to install#latest for npm (unless it's special syntax like npm start).
The more I think about it, the more paranoid I get, any confirmation would be greatly appreciated. :)
Using npm install <pkg>#latest is equivalent to using npm install <pkg> by itself or listing * as the dependency version in package.json. npm documents this here:
npm install will use the latest tag by default.
So in practical terms, latest is semantically equivalent to stable.
However, if a prerelease version of a package is published to npm without specifying a prerelease tag such as --beta or --rc, that version becomes the latest by default:
By default, npm publish will tag your package with the latest tag.
As a result, it's possible to mess up and publish a prerelease version that will be installed by default. This happened to Bootstrap in late 2015.
This article from early 2016 by Mike Bostock explains how even specifying alpha or beta as part of the version number won't prevent npm from making that version the latest.
So unfortunately if you want to be certain that you get only stable versions, you need to monitor this manually or trust the package developers to always specify a prerelease tag for non-stable versions.
You can also view the tags assigned for a package like this:
$ npm view express dist-tags
{ latest: '4.16.2', rc: '4.0.0-rc4' }

What is the difference between npm-shrinkwrap.json and package-lock.json?

With the release of npm#5, it will now write a package-lock.json unless a npm-shrinkwrap.json already exists.
I installed npm#5 globally via:
npm install npm#5 -g
And now, if a npm-shrinkwrap.json is found during:
npm install
a warning will be printed:
npm WARN read-shrinkwrap This version of npm
is compatible with lockfileVersion#1,
but npm-shrinkwrap.json was generated for lockfileVersion#0.
I'll try to do my best with it!
So my take-away is that I should replace the shrinkwrap with the package-lock.json.
Yet why is there a new format for it? What can the package-lock.json do that the npm-shrinkwrap.json cannot?
The files have exactly the same content, but there are a handful of differences in how npm handles them, most of which are noted on the docs pages for package-lock.json and npm-shrinkwrap.json:
package-lock.json is never published to npm, whereas npm-shrinkwrap is by default
package-lock.json files that are not in the top-level package are ignored, but shrinkwrap files belonging to dependencies are respected
npm-shrinkwrap.json is backwards-compatible with npm versions 2, 3, and 4, whereas package-lock.json is only recognized by npm 5+
You can convert an existing package-lock.json to an npm-shrinkwrap.json by running npm shrinkwrap.
Thus:
If you are not publishing your package to npm, the choice between these two files is of little consequence. You may wish to use package-lock.json because it is the default and its name is clearer to npm beginners; alternatively, you may wish to use npm-shrinkwrap.json for backwards compatibility with npm 2-4 if it is difficult for you to ensure everyone on your development team is on npm 5+. (Note that npm 5 was released on 25th May 2017; backwards compatibility will become less and less important the further we get from that date, as most people will eventually upgrade.)
If you are publishing your package to npm, you have a choice between:
using a package-lock.json to record exactly which versions of dependencies you installed, but allowing people installing your package to use any version of the dependencies that is compatible with the version ranges dictated by your package.json, or
using an npm-shrinkwrap.json to guarantee that everyone who installs your package gets exactly the same version of all dependencies
The official view described in the docs is that option 1 should be used for libraries (presumably in order to reduce the amount of package duplication caused when lots of a package's dependencies all depend on slightly different versions of the same secondary dependency), but that option 2 might be reasonable for executables that are going to be installed globally.
Explanation from NPM Developer:
The idea is definitely for package-lock.json to be the Latest and
Greatest in shrinkwrap technology, and npm-shrinkwrap.json to be
reserved for those precious few folks out there who care very much
about their libraries having an exact node_modules -- and for people
who want CI using npm#>=2 to install a particular tree without having
to bump its npm version.
The new lockfile ("package-lock.json") shares basically all of the
same code, the exact same format as npm-shrinkwrap (you can rename
them between one another!). It's also something the community seems to
understand: "it has a lockfile" seems to click so much faster with
people. Finally, having a new file meant that we could have relatively
low-risk backwards-compat with shrinkwrap without having to do weird
things like allow-publication mentioned in the parent post.
I think the idea was to have --save and shrinkwrap happen by default but avoid any potential issues with a shrinkwrap happening where it wasn't wanted. So, they just gave it a new file name to avoid any conflicts. Someone from npm explained it more thoroughly here:
https://www.reddit.com/r/javascript/comments/6dgnnq/npm_v500_released_save_by_default_lockfile_better/di3mjuk/
The relevant quote:
npm publishes most files in your source directory by default, and
people have been publishing shrinkwraps for years. We didn't want to
break compatibility. With --save and shrinkwrap by default, there was
a great risk of it accidentally making it in and propagating through
the registry, and basically render our ability to update deps and
dedupe... null.
So we chose a new name. And we chose a new name kind of all of a
sudden. The new lockfile shares basically all of the same code, the
exact same format
package-lock.json versions are guaranteed with only npm ci (since npm install overwrites package-lock.json if there is a conflict with package.json).
npm-shrinkwrap.json versions are guaranteed with both npm ci and npm install.

Are yarn and npm interchangeable in practice?

I have a project with a package.json file and an install bash script that, among other steps, runs npm install.
I'm thinking of updating the script so that it runs yarn install if yarn is available (to take advantage of yarn's caching, lockfile, etc), and falls back to npm install otherwise. As far as I can tell, all the packages seem to install and work ok either way.
Are yarn and npm interchangeable enough for this to be a viable approach, though? Or are there potential issues that this could lead to? Are we meant to just pick one, or is yarn interchangeable with npm in practice?
(nb. I've read this closely related question, but I'm asking this as a separate question because it's about explicitly supporting both yarn and npm install processes in a project)
Yarn and npm (version >=3.0.0) should be relatively compatible, especially moving from npm to Yarn, because compatibility is one of the stated goals of Yarn. As stated in Migrating from npm:
Yarn can consume the same package.json format as npm, and can install any package from the npm registry.
So, in theory, any package.json that is valid for npm should also work equally well for Yarn. Note that I say that npm v2 is probably less compatible - this is because npm migrated from a nested node_modules structure to a flat layout (which is what Yarn uses). That said, Yarn and npm v3 should produce very similar layouts, because, as stated in the issue I linked:
To a first approximation we should try to be very compatible with the node_modules layout for people who need that compatibility, because it'll be the most likely way to avoid long-tail compatibility problems.
However, you will not be able to take advantage of the Yarn.lock generated by Yarn, because (as the name suggests) it's only supported by Yarn, and npm shrinkwrap is not compatible.
Also, as noted by #RyanZim, older versions of Yarn don't support pre- and post-install hooks, but versions later than v0.16.1 do. If you rely on these hooks, you will need to specify to users that versions greater than v0.16.1 are required.
In summary, as long as you encounter no bugs and only use features that are shared by both package managers, you should have no issues whatsoever.