Force yarn install instead of npm install for Node module?
UPDATE: Alexander's answer is the better solution and uses the same technique I describe here. I am leaving my answer in tact for posterity. The original point of my answer was to show that you can execute a small node script which should work on all platforms.
In your preinstall script you can run a mini node script which should work on all platforms, whereas things like pgrep
(and other common *nix commands and operators) won't work on Windows until Windows 10 has received widespread adoption.
I tested the below script on Node v4.7.0 (npm v2.15.11) and Node v7.2.1 (npm v3.10.10). I assume it works on everything in between. It works by checking the environment variables on the currently running process - the npm_execpath
is the path to the currently running "npm" script. In the case of yarn, it should point to /path/to/yarn/on/your/machine/yarn.js
.
"scripts": {
"preinstall": "node -e \"if(process.env.npm_execpath.indexOf('yarn') === -1) throw new Error('You must use Yarn to install, not NPM')\""
}
You can read more about npm scripts here: https://docs.npmjs.com/misc/scripts
As far as the npm_execpath
environment variable, while not documented I doubt that it will ever change. It's been around for multiple major releases of npm
and it doesn't really pass the "there's a better name for this" test.
Like the other answers, I'd recommend using a preinstall
script and checking your environment. For a portable solution that won't have false-positives if another npm process happens to be running, using node -e 'JS_CODE'
is probably the best option.
In that JS code, you can check the package manager's path using the following:
process.env.npm_execpath
Yarn's binary is yarn.js
, compared to npm-cli.js
used by NPM. We can use a regex like the following to check that this string ends with yarn.js
.
/yarn\.js$/
By using this regex, we can be sure it won't accidentally match somewhere earlier in the file system. Most-likely yarn
won't appear in the file path, but you can never be too sure.
Here's a minimal example:
{
"name": "test",
"version": "1.0.0",
"scripts": {
"preinstall": "node -e 'if(!/yarn\\.js$/.test(process.env.npm_execpath))throw new Error(\"Use yarn\")'"
}
}
Of course, the user will still be able to get around this check be editing the JSON or using the --ignore-scripts
options:
npm install --ignore-scripts