CLI utilities in local Node.js packages - node.js

Windows 10, Node.js 12.18.3. There's a project (by someone else) - let's call it "foo". It has a dependency on an NPM package called "bar". Bar has a postinstall script with a lb-clean command in it. The lb-clean command comes from the npm package #loopback/build. Bar lists #loopback/build under devDependencies in package.json. Yet when I run npm install under foo, it errors out that lb-clean is not found.
If I run npm install -g #loopback/build, then lb-clean.cmd is installed under %APPDATA%\npm, which is in PATH, and the postinstall script is happy.
In a scenario like this, are CLI commands of locally installed dependent packages supposed to be visible on the command line? In other words, is bar broken?

Related

my own NPM package not working command not found

If I don't install my own CLI globally, I can't run it with my keyword command. Only if I install the NPM package globally, the start works with my keyword. I would like to install it with the command suggested by NPM and then run it with keyword.
Visit my CLI: https://www.npmjs.com/package/sweetstack
Installation as globally it works, started with sweetstack.
npm i -g sweetstack
Installation as local not working.
npm i sweetstack
This behavior is expected, if your inspect the $PATH environment variables of your shell, you'll see that only the directory containing the globally installed packages is present.
If you want to install your tool locally (which is a good practice), you then have to run it through npx.
The associated documentation page details what it does more clearly and it's relation to npm exec : https://docs.npmjs.com/cli/v9/commands/npx
cd ./your-project
npm i sweetstack
npx sweetstack

Hook (specifically postinstall) after any npm install command

Using NPM at the command line, is there some official hook that I can configure, which means that for any npm install command (including npm install x), a certain hook is run?
Right now, I see certain limitations -
if I run npm install x it will not run hooks for another dependency (obviously) but it also doesn't seem to run hooks for the main/parent package.
Plain old npm install will run preinstall / postintall hooks for the main/parent package.
If you are on npm v6.X it's possible to run scripts on npm install <package> by using Hook Scripts.
Unfortunately it seems the functionality has been removed in newer versions.
In order to do so you need to create a script inside node_modules/.hooks/{eventname} where {eventname} is the event you want to hook on.
For example to hook on postinstall you'll need node_modules/.hooks/postinstall
There's a catch though: it won't run on Windows, because it won't be able to recognize the file as an executable since it's lacking a file extension.
A not so pretty workaround is to create, for instance, a postinstall.cmd and soft (or hard /H) linking it with mklink postinstall postinstall.cmd
This will ensure that Windows recognizes the file as a .cmd executable to correctly run it.

Attempt to install Amber.js on OS X fails because grunt client not installed?

I have installed node.js and npm on my OS X box running 10.11.5. But, following the instructions at http://docs.amber-lang.net/getting-started.html, when I type:
npm install -g amber-cli
in the Terminal, I get the following result:
npm WARN amber-cli#0.100.2 requires a peer of grunt-cli#^0.1.13 but none was installed.
And the installation halts. Since this is only a warning from npm, I wonder if I really need grunt installed.
FWIW, it does appear I have a version of grunt in my npm directory because using locate to find it produces a billion lines, one of which is:
/Users/me/.npm/grunt
In fact, it looks like I have a bunch of grunt installs (most version 0.4.0). Which makes me reluctant to install grunt again since it doesn't seem to work anyway.
Try the following command
npm install -g grunt-cli#0 grunt-init bower amber-cli
More than likely, it's a problem with your path.
If nothing returns when you execute which grunt, it means that you need to add the location of grunt to your path.
If you installed grunt using npm install -g, you'll need to add /usr/local/bin to your path.
Since you found your grunt cli under ~/.npm, you will need to add that to your path.
You should also add ./node_modules/bin to your path which will cause your shell to check for npm-installed modules in the node_modules/bin directory in your current directory.
You can always run grunt directly, irrespective of its location, by typing: npx grunt using the tool included with npm for running npm-installed commands.
It's good practice to add all of the paths above, to catch all possible npm-installed commands.
You can update your path in the ~/.*rc file for your shell (~/.bashrc for bash, etc.), by adding this line to the end of your rc file:
export PATH=/usr/local/bin:~/.npm:./node_modules/bin:$PATH

How to pass options to dependent package installs for npm?

My node.js project has a dependency on node-sqlite, but unfortunately the default libsqlite binary embedded there was not built with options I need.
Now I can invoke npm install on that package alone to get it to build correctly:
CFLAGS=-DSQLITE_ENABLE_STAT4 npm install sqlite3 --build-from-source
Essentially, this sets the environment variable and passes an option to the tool.
However, npm install by itself should just install all the project dependencies, including sqlite. How do I encode package.json or elsewhere so that npm install will install the sqlite dependency with the above command line?
You could use a preinstall or a postinstall script to do this.
#!/bin/bash
CFLAGS=-DSQLITE_ENABLE_STAT4 npm install sqlite3 --build-from-source;
Put this in scripts/install_sqlite3_from_source.sh, and set scripts.preinstall or scripts.postinstall in your package.json to it.

What does the -g option for npm install and npm list do?

The Node.js npm (Node Package Manager) has a -g command line argument, which I often see referenced. For example, the documentation for the Microsoft Azure x-plat (cross-platform) CLI tool says to install it by using npm install -g azure-cli.
Question: What does the -g option do?
What options do I have to install node modules?
After writing this I quickly found and old but still applicable post by Isaac (yes, the npm #isaacs). But I still think the below post is informational.
You can install npm modules globally or locally - you already know that, but why?
Globally: npm install -g some-module-a: This module is intended to be used as an executable (i.e. CLI, file watcher, code minifier, logger, etc.).
Locally: npm install some-module-b: To be imported and used in your app via import, var someModule = require('some-module)
global modules are one of the best ideas of npm. We can easily create executables using node/javascript. If your node app is meant to be run as an executable, then you will want others to install it globally. If it's a utility, helper, application, etc. then you usually don't want it installed globally. So, unless the module explicitly states that you should install it with -g, then don't.
One more time: if you are wanting to use some module called some-module in your node app - var someModule = require('some-module'), then npm install some-module from the root of your node app to pull it into your local node_modules directory. If you've installed some-module globally and not locally, it will usually not load and will show you an error about not finding the module (even though it can be made to load the global module - hint: just don't!)
So what exactly happens when you install globally?
npm install -g [some module] installs the specified node module in a directory higher up in your file system (i.e. usually /usr/local/lib/node_modules in unix systems). The biggest use case for global modules is for CLIs written using node (think npm, bower, gulp, grunt, et. al.).
Let's look at what happens when you install bower globally:
*follow these steps in your command line/terminal
step: npm install -g bower
explanation: the module - all of it's files and dependencies - are saved in your global directory (e.g. /usr/local/lib/node_modules/bower).
Something else happened here. Somehow you can now run bower in your command line. Awesome!
step: bower -v --> results in the installed bower version (i.e. 1.6.5)
explanation: It's now a fully executable node app using bower as the keyword. Inside bower's package.json file you'll find a bin property:
"bin": {
"bower": "bin/bower"
}
So how did that all work?
npm will create a symlink from where most executables live, /usr/local/bin/bower over to /usr/local/lib/node_modules/bower/bin/bower, where the module lives. That symlink makes it so when the executable runs, it can reference other files in the original module, including it's local node_modules. Pretty cool, huh?
*Note on executables: If you create a file called awesomeness in /usr/local/bin/ and chmod u+x (user + executable) it. Then write some scripting in it (in this case javascript using #!/usr/bin/env node at the top). Then you can run it anywhere in your command line/terminal just by typing awesomeness.
Hope that helped. I know doing a deeper dive into it helped me early on.
Node.js packages can be installed one of two ways:
Globally
Locally
The -g option instructs npm to install the package globally. You would install a Node.js package globally, if you want to be able to call the command directly from the terminal.
From the documentation:
There are two ways to install npm packages: locally or globally. You choose which kind of installation to use based on how you want to use the package.
If you want to use it as a command line tool, something like the grunt CLI, then you can want to install it globally. On the other hand, if you want to depend on the package from your own module using something like Node's require, then you want to install locally.
To download packages globally, you simply use the command npm install -g , e.g.:

Resources