statusboard icon indicating copy to clipboard operation
statusboard copied to clipboard

BREAKING CHANGE(bin): remove command

Open darcyclarke opened this issue 3 years ago • 2 comments

darcyclarke avatar Aug 22 '22 11:08 darcyclarke

Why is this being removed?

styfle avatar Aug 24 '22 02:08 styfle

npm bin currently does not accurately represent everywhere npm looks for a bin when one is asked for. Providing it as a command invites folks to add it to their $PATH which is discouraged: npm should be finding those, not your os. The bin discovery of npm is more than just looking in the one folder, it actually walks up from whatever folder the package is in, looking for a .bin folder in any node_modules it finds. This is how scripts that call npm run can get the version of a given package they asked for, instead of whichever one "wins" by being hoisted.

In global mode, bin is simply where node is.

wraithgar avatar Sep 01 '22 17:09 wraithgar

If the command is going to be removed, it would be great if the algorithm itself was documented.

styfle avatar Sep 03 '22 21:09 styfle

(Posting here for visibility.) There is a discussion at https://github.com/npm/feedback/discussions/807 to find an alternative for a use case broken by this change.

ngraef avatar Nov 16 '22 20:11 ngraef

If npm run behaved more like yarn run then I would think this change was acceptable. However npm run still does not execute ./node_modules/.bin it appears.

nmccready avatar Nov 17 '22 20:11 nmccready

Looks like $(npm root)/.bin is the closest you can get to this now?

nmccready avatar Nov 17 '22 20:11 nmccready

@nmccready that's what npx is for.

ljharb avatar Nov 17 '22 21:11 ljharb

Thank you I will look into this.

nmccready avatar Nov 17 '22 22:11 nmccready

There's a lot of discussion of npm bin here but there's a slightly different use case for npm bin -g. What is the replacement for npm bin -g to find the folder where npm installs globally-available executables?

Providing it as a command invites folks to add it to their $PATH which is discouraged: npm should be finding those, not your os.

Surely the global install path should be in your $PATH variable, right? This was one thing npm bin -g checked for.

molisani avatar Nov 21 '22 20:11 molisani

Surely the global install path should be in your $PATH variable, right? This was one thing npm bin -g checked for.

The global install path should already be in your path because that is where node itself is. npm is installed into a given version of node alongside the node binary, the assumption being that if you can run node, npm can link bins into the same directory to have them also available to the end user without an extra $PATH entry.

The nuance here comes from the fact that Windows installs node/npm into a different directory structure than osx and linux. There is no bin directory in Windows. There is also no lib in Windows, the node_modules is also an immediate subdirectory of the one in which the node binary lives.

The npm bin command kind of put the cart before the horse and introduced a bit of bad "discovery" of this path based on npm, instead of node.

So for instance in fish shell this would be a more appropriate way of knowing where those bins lived

$ dirname (which node)
/Users/wraithgar/.nvm/versions/node/v18.12.0/bin

They really have nothing to do with npm, but with node itself.

wraithgar avatar Nov 21 '22 21:11 wraithgar

In the Windows Node installer, it's more than just the different directory structure, the global packages are installed in a completely separate directory from the node installation. Being able to run node does not necessarily mean that the user is also able to run the globally installed packages. Taken from the installer, updating the PATH variable is split into two different "features".

* Add to PATH
  * Node.js and npm - Add Node.js and npm (if installed) to the PATH environment variable
  * npm modules - Add modules that are installed globally by npm to the PATH environment variable. This option works for the current user only.

With a clean install of node on Windows with these two features selected, it will add two separate locations to the PATH:

C:\Program Files\nodejs
C:\Users\<username>\AppData\Roaming\npm

This is because of the value of prefix decided by the builtin config, which is set to %APPDATA%\npm by default:

$ npm config ls
; "builtin" config from C:\Program Files\nodejs\node_modules\npm\npmrc

prefix = "C:\\Users\\<username>\\AppData\\Roaming\\npm"

If I then install a package (ex: typescript) with npm i -g typescript, this installs tsc to C:\Users\<username>\AppData\Roaming\npm\tsc which I'm only able to invoke successfully because of the second new entry in my PATH variable. This logic is entirely custom to npm, as it's derived from npm's prefix config value.

This all works seamlessly in the ideal case, but speaking as someone that handles troubleshooting for a large population of developers that are not always primarily doing Node/npm/JS development, incomplete or inaccurate PATH variables have been an uncommon yet consistent issue. It was useful for us to have npm bin -g as that could prompt the user to add the global package location to their PATH if it wasn't already set (as it would warn with (not in PATH env variable)).

Given the nature of Windows' two-location installation, this does seem like a Windows-only problem. As such, I'm not sure what the cleanest fix would be. For this use case we do not need any of the "non-global" functionality of npm bin without -g that allowed for the aforementioned bad behavior, so I'm not suggesting that this command be added back as it was. If the functionality to check the global install location (and also if that was in the PATH variable) could be added to an existing command (maybe npm prefix -g) or even a new command, that would work well for us. I'd be happy to contribute such a feature (whatever it may look like) if that sounds like a good idea to all involved.

molisani avatar Nov 21 '22 23:11 molisani

This is very good feedback @molisani thank you for laying it out so clearly. Can you open a new issue in https://github.com/npm/rfcs suggesting we reintroduce a global only bin command? Your last comment can be copy/pasted there as a starting point I think. This closed issue definitely has no greater visibility w/in the org so discussion here is unlikely to result in any npm change.

wraithgar avatar Nov 22 '22 15:11 wraithgar