Why pnpm has two stores when using with nvm? - pnpm

I did found pnpm is using two stores when installed in nvm environment.
/Users/me/.pnpm-global/1
/Users/me/.nvm/versions/node/v10.15.3/pnpm-global/1
Trying to understand, why it is so.

~/.pnpm-global is not the store. It is the location where the global packages are installed. For instance, when you run pnpm i -g webpack-cli, webpack will be installed into ~/.pnpm-global.
It is probably some bug that you have two of those. There should be one global folder, probably this one only: /Users/me/.nvm/versions/node/v10.15.3/pnpm-global/1
The global store is located at ~/.pnpm-store

Related

How do I avoid lock file conflicts with PNPM?

Our team uses PNPM and a recurring problem is that we seem to have different versions of the pnpm command installed, causing lock files git conflicts when adding or updating packages. PNPM is a global tool, so I am not totally sure how to handle this situation. Some Node tools have a global CLI interface (Grunt), but utilize a locally installed package to avoid this issue. Does PNPM have a way to ensure consistent behavior across the team to avoid lock file conflicts and such?
The current recommended approach is to declare which pnpm version should be used in the project. It may be done via the engines field of packages.json. For instance, if your project should be used with pnpm v6, add this to package.json:
{
"engines": {
"pnpm": "6"
}
}
If someone will run pnpm install using a different version of pnpm, an error will be thrown.
In the future we might automatically download the right version of pnpm and use it. Kind of how Yarn does it with version policies.

Do NPM packages have to be installed globally to access their functionality via the command line?

I am having trouble understanding how the -g flag works in NPM. Specifically I'm struggling to understand how it relates to command-line functionality exposed by NPM modules.
I assumed that the difference between installing a package locally and globally was simply that a local package would not be available outside of the particular project. And of course that a globally installed package would be available in any project. I'm from a Rails background so this for me would be similar to installing a gem into a particular RVM versus installing it into the global RVM. It would simply affect which places it was available.
However there seems to be more significance than just scope in NPM. For packages that have command-line functionality, like wait-on, the package (as far as I can tell) is not available on the command line unless it's installed globally.
Local install doesn't make the command-line functionality available:
$ npm install wait-on
$ wait-on
=> -bash: /usr/local/bin/wait-on: No such file or directory
Global install does expose the command-line functionality
$ npm install wait-on -g
$ wait-on
=> Usage: wait-on {OPTIONS} resource [...resource]
Description:
wait-on is a command line utility which will wait for files, ports,
sockets, and http(s) resources to become available (or not available
using reverse flag). Exits with success code (0) when all resources
are ready. Non-zero exit code if interrupted or timed out.
Options may also be specified in a config file (js or json). For
example --config configFile.js would result in configFile.js being
required and the resulting object will be merged with any
Can you expose the command-line functionality using a local install?
Is it possible to install locally but also get the command line functionality? This would be very helpful for my CI setup as it's far easier to cache local modules than global modules so where possible I'd prefer to install locally.
If you are using npm 5.2.0 or later, the npx command is included by default. It will allow you to run from the local node modules: npx wait-on
For reference: https://www.npmjs.com/package/npx
I think you can access locally installed modules from the command line only if you add them to your "scripts" section of your package.json. So to use the locally installed version of wait-on, you can add an entry in "scripts" section of package.json like so "wait-on": "wait-on". Then to run it, you would have to do npm run wait-on. You can also do "wo": "wait-on" and then do npm run wo basically meaning what comes after the run is the script entry. In node_modules, there is a .bin folder and inside of this folder is all the executables that you can access this way.
Installing locally makes the package available to the current project (where it stores all of the node modules in node_modules). This is usually only good for using a module like so var module = require('module'); or importing a module.
It will not be available as a command that the shell can resolve until you install it globally npm install -g module where npm will install it in a place where your path variable will resolve this command.
You can find a pretty decent explanation here.
It is also useful to put commands in the scripts block in package.json as it automatically resolve local commands. That means you could have a script that depended on a package without having an undocumented dependency on the same.
If you need to run it locally on cmd, you have to go inside the node_modules and run from the path.

How to remove a package from pnpm store, or force re-download it?

I use pnpm to manage npm project, and I modified the content of an installed package by accident, say, I cleared the content of node_modules/jquery/dist/jquery.js.
The problem is no matter how i reinstall jquery(pnpm install jquery), the content of this file is always empty. I even tried to delete jquery from pnpm store ~/.pnpm-store/, but that doesn't work(maybe I deleted wrong package)
Finally, I have to delete all the files in ~/.pnpm-store, to download everything, it fixes my problem, but I want to know if there is any easier way to do it.
{ My answer will cover pnpm v2.16.2 }
Short answer: run pnpm install --force. (pnpm update might work as well)
Long answer. When you just run pnpm install, pnpm compares the wanted shrinkwrap file (project/shrinkwrap.yaml) to the current one (project/node_modules/.shrinkwrap.yaml). They equal in your case, so node_modules is not touched.
When --force is used, packages are reverified and relinked from the store. Reverification means that its integrity is checked. You removed a file from jquery, so verification will fail and the package will be reunpacked to the store and relinked to node_modules.
Alternatively, you could remove your project's node_modules and run pnpm install. That would also check the integrity of jquery before linking it to the store.
That being said, I think pnpm install jquery should also probably verify the integrity of jquery. We'll create an issue for this in the pnpm repo.
And maybe we can add some additional commands for reverifying every package in node_modules and re-unpacking all modified dependencies.
A related command currently available is pnpm store status which prints a list of mutated packages

What's the proper way to install a go package to the system path?

I'm trying to install a go project (the keybase client, in particular), but I want to install it globally for all the users on my system.
I've searched around and found a few people who accidentally install things to /usr/local/go/bin or something to that effect, but no instructions on how I actually should be installing things to such locations.
But that's what I want to do - globally install the application. How should I be doing that with go?
I'm not using any of the pre-built packages because none exist for Raspbian Jesse.
Have you tried setting $GOBIN like:
GOBIN=/usr/local/bin/ or GOBIN=/usr/bin/ or any directory in the PATH?
and then:
export GOBIN
and then install the app?
According to the manual the default $GOBIN is $GOROOT/bin so I guess those users set GOROOT to /usr/local/go
The approach that I've taken is this:
PATH="$PATH:/usr/local/go/bin" GOPATH=/usr/local/go/ go get github.com/keybase/client/go/keybase
PATH="$PATH:/usr/local/go/bin" GOPATH=/usr/local/go/ go install -tags production github.com/keybase/client/go/keybase
Which ends out installing keybase to /usr/local/go/bin/keybase. It's possible that there's a better way, but so far I haven't seen one.

Script name collision in terminal

I just installed
npm install -g angular-cli
And attempted to initialize a new project
ng new foo
Unfortunately I already have nailgun installed which also uses the ng keyword.
How can I set which has precedence? Better yet, is there an easy way to rename one of them?
The first one found in the path is the one that will be called, so you could re-order your path as a first option. When you needed nailgun, you could swap the order for the nailgun and global npm modules directories in your path.
You could rename ng in the .bin directory in your global install location, but this could have side effects if other angular tools expect to be able to call ng.

Resources