Installing "global" npm dependencies via package.json [duplicate] - node.js

This question already has answers here:
Install dependencies globally and locally using package.json
(7 answers)
Closed 8 years ago.
I have a few "global" dependencies (jshint, csslint, buster, etc..) that I'd like to have automatically installed and executable via the command line when my package is installed via npm install. Is this possible?
Currently, I'm doing the following manually:
npm install -g <package_name>
from within my project: npm link <package_name>
Update:
Just came across this feature request for npm. It seems like the scripts config within package.json is the way to go?
Update Again:
Or, after reading the npm docs, maybe I'm supposed to use a .gyp file? I'm confused.

It's not possible to specify dependencies as "global" from a package.json. And, this is by design as Isaac states in that feature request you referenced:
Yeah, we're never going to do this.
But, "binaries" can still be used when a package is installed locally. They'll be in .../node_modules/.bin/. And, you should be able to queue them up with a preinstall script.
Though, if the series of commands is rather lengthy (as "jshint, csslint, buster, etc.." would suggest), you may want to look into using a build tool such as grunt to perform the various tasks:
{
// ...,
"scripts": {
"preinstall": "grunt"
}
}

I really like the pattern where you install local dependencies, then use a bash script that sets your PATH to ./node_modules/.bin.
File: env.sh
# Add your local node_modules bin to the path for this command
export PATH="./node_modules/.bin:$PATH"
# execute the rest of the command
exec "$#"
Then, you can use this script before any bash command. If you pair that with a Makefile or npm script:
File: Makefile
lint :
./env.sh csslint my_styles
File: package.json
"scripts": {
"lint": "./env.sh csslint my_styles"
}
This tasks in these files look like they reference csslint in some global location, but they actually use the version in your node_modules bin.
The really awesome benefit of this is that these dependencies can be versioned easily, just like your other node modules. If you stick with a global install solution, you could be clobbering some specific version on the user's system that is required for one of their other projects.

You should try this: https://github.com/lastboy/package-script
I've been using it to install global npm packages straight from the package.json. It works well for clients who aren't technically literate.
It even checks if the packages are already installed, if not install them!

Related

What's the difference between "npm install -g" (no args) and "npm link" to create CLI command?

To make a local node.js package work as a global commandline tool, I first add this to package.json
"bin": {
"myCommand": "./index.js"
}
According to the npm docs, I then have two options:
Within that folder, run npm install -g. According to the node docs:
npm install (in package directory, no arguments) ... In global mode
... installs the current package context (ie, the current working
directory) as a global package.
OR
Within that folder, run npm link. The node docs say
npm link in a package folder will create a symlink in the global
folder ... will also link any bins in the package to
{prefix}/bin/{name}
Both of these routes lets me run myCommand anywhere in the terminal while local edits are reflected in the tool without reinstalling/linking.
For local CLI tool purposes, these commands seem functionally identical. Is this true? Why would I want to use npm install -g (no args) when npm link seems functionally identical, plus affording extra capability?
Note: this question is purely about a local node project, nothing to do with anything in a remote package registry

Custom CLI similar to "npm install" that will install libs in folder other than "node_modules"

I understand that "npm install" in NodeJS will actually install libraries into a folder called "node_modules".
I am actually wanting to achieve something similar but to use my own CLI instead (eg using commands like "myproject install" instead of "npm install") and then the libraries (proprietary ES6 source codes from my company's Enterprise Git Repo) will be installed into a specific folder (eg "myown_modules" rather than "node_modules").
Question is, how do I achieve that, assuming that I want dependencies checking as well on the libraries that are going to be installed? Also, how do we control versions using own CLI?
Use this repo and modify it to do what you want.
You need to change the install folder and change the process with the name you want.
NPM repo : https://github.com/npm/npm
OR :
Create a bash script who will do npm install xxxx when you use myscript xxxx, so you can't change the node_modules with this.

Package and distribute Bash script with NPM to allow installation globally into developer workstation's paths with npm install

I have some scripts that I want to distribute with npm for developers to be able to install globally on their workstations and then use the commands of the scripts on their computers in their development workflow.
I can't work out how to get npm to actually add the script in its package to the path though.
I see that the firebase tools have this in their package.json:
"preferGlobal": true,
"bin": {
"firebase": "./bin/firebase"
},
...but I can't quite work out how this relates to my project.
The first project I am trying to distribute with npm is for controlling a Belkin WeMo light switch, it includes an executable 'wemo' and an included functions.inc.sh file, this can be seen # https://github.com/agilemation/Belkin-WeMo-Command-Line-Tools.git
If anyone can point me in the right direction it will be really appreciated!!!
Thanks,
James
Any key/value pairs placed into the bin key of the package.json will be symlink'ed into the NPM bin-dir path.
The key is what you want the command to be named and the value part is the script in your package it should run.
Ergo, in your example, when npm install finishes running it'll create a symlink from [package-install-path]/bin/firebase to /usr/local/bin/firebase (or whatever bin directory prefix NPM is using (npm bin -g will tell you where this is).
If you only have one script you can also do:
{
"name": "my-awesome-package",
"bin": "./myscript.sh"
}
And it'll symlink myscript.sh to my-awesome-package
Although you should be wary of including bash scripts since they won't work on Windows.
Here are the docs for this.

Locally-installed cli NPM project that is easy to execute

I'm building a cli node module. I would like people to be able to npm install it and use it right away with a command like npm my-project --arg=foo. It's meant for local project CLI use as a dev tool, not global installation.
It seems like the standard is to use bin in the package.json, but I don't understand some things about it:
When should I use bin and when should I use scripts?
How to I run the command in the including project? npm my-project doesn't do it.
Here is what I am doing now in package.json:
{
"name": "my-project",
"bin": "./cli.js"
}
And I can run it locally:
node cli.js --arg=foo
But when I npm-install my-project somewhere else, I don't know how to run the script it puts in bin (npm run my-project doesn't work), or if I'm using this correctly.
Let's start by explaining the difference between bin and scripts: the former you use if you want to provide a command line tool, the latter you use if you want to provide an additional command to npm (with some caveats though, see below).
In your situation, I think you want to use bin. However, instead of the user using npm my-project --arg=foo, they will use my-project --arg=foo, provided that your script is called my-project. To make that happen, your package.json will contain something like this:
"bin" : "./bin/my-project"
During installation, this will copy ./bin/my-project to a "bin" directory (usually /usr/local/bin on Unix-like OS'es). During development, you can call it as node bin/my-project, or even just ./bin/my-project, provided that it has correct permissions and "shebang".
EDIT: so I forgot that npm will use the package name, and not the name of the file in ./bin, as the executable name (if bin is a string). If your package is called my-project, and you install the package (you need to use the -g flag before npm will install the executable), it will create an executable called my-project, regardless of where the bin property points to.
In other words:
package.json:
"name" : "my-project"
"bin" : "./cli.js"
npm install -g:
copies ./cli.js to /usr/local/bin/my-project and sets executable permissions
END EDIT
FWIW, storing CLI tools in ./bin is convention, but not mandatory.
The scripts directive is useful for more internal purposes. For instance, you can use it to run a test suite, or linters, or pre/post install scripts.
Lastly, there are various modules available to help with command line parsing. I like docopt, but other often-used modules are commander or nomnom. You already mentioned yargs.

How to put local node package on path?

Newbie question. I have chosen not to install express with -g option. I did not use npm -g which would put it on the path globally. Instead it is installed in my local mac user directory. What I am not clear on is exactly what or how you put a package like express on the path so it can be invoked etc? What exactly needs to be on the path (node_modules?) so these packages are available just like a -g installation? I could have used home-brew I suppose but anyway, I now have all node packages and everything local. Another situation is that I am not able to run any of the nodejs tutorials. Although there might be smarter ways to do this, I wonder if sudo is really such a good way to install a development package ....
Now for example, I want to run the tutorial javascripting which is a nodejs tutorial. How do I do this. If I just type:
Mac1$ javascripting
it finds nothing.
Same for
Mac1$ express
UPDATE: THIS WAS ANSWERED IN THE COMMENTS
The commands exist in a hidden directory after a regular
install npm install express
in my case this the command goes here: /users/MAC1/node_modules/.bin
It is this path that needs to be placed on the $PATH as described in the first comment.
Thanks guys.
npm installes executable to two places. By default running a npm install in a project will install any binaries in ./node_modules/.bin. When you use the -g flag (npm install -g package-name) it will install into a global path. You can find out the global path by running npm bin -g. Add that to your path and globally installed executables will be accessible.
You can also add ./node_modules/.bin to your path to allow easy access to executables added by packages in your project folder. I admit to using this on a trusted local machine. However, this is very dangerous and not a recommended way to expose the executables in the node_modules directory.
Best alternative is to add the executable to the scripts section of the package.json file and then use npm run-script <command> which will auto prepend the ./node_modules/.bin when executing.
package.json
{
"scripts": {
"foo": "foo --arguments"
}
}
Example
$ npm install foo
$ ls ./node_modules/.bin
foo
$ npm run-script foo
# Executes:
./node_modules/.bin/foo --arguments

Resources