Override `npm install` script for NPM project - node.js

I have an NPM project, when npm install is run, I'd like to run a custom script.
I tried using this in package.json:
"scripts": {
"ng": "ng",
"start": "ng serve",
"install": "./scripts/install.sh", // <<<<
},
but that actually just resulted in an infinite loop.
The reason I am looking for this, is because there are tools that simply call npm install, so I can't control what they run. Otherwise, if I had control, I would just call ./scripts/install.sh myself instead.
Note that this is probably not the best idea, just curious if it's possible.
Note my install script looks something like this:
#!/usr/bin/env bash
export FOO="bar";
export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD="true";
npm install

Use preinstall to run code before npm install. Don't try to override npm install in this fashion where you would end up with an infinite loop of calls to npm install.
You can also set environment variables using the config property of package.json. See docs for details

Related

npm-force-resolutions not working when installing a new package

I'm using the scripts section of the package.json to force resolutions:
"preinstall": "npx npm-force-resolutions"
in the resolutions section, I have entered graceful-fs with a specified version:
"resolutions": {
"graceful-fs": "^4.2.4",
},
When i run npm i everything is installed correctly, the set versions are taken in to account. But later on when I install an additional module, e.g. npm i random-package, my set versions are being thrown away and I endup with graceful-fs#1.2.3 and other low versions in some dependencies.
If I clear the node_modules folder and run npm i again, everything is alright again.
I also tried setting the resolution more specific, like
"resolutions": {
"glob/**/graceful-fs": "^4.2.4",
},
but this doesn't help.
I also tried:
adding the module as dependency, devDependency or peerDependency
using a shrinkwrap and overriding it there
but no luck.
what am I missing?
The best solution for me to automate this was modifying preinstall script as above:
"preinstall": "npm install --package-lock-only --ignore-scripts && npx npm-force-resolutions",
Best way is to change the preinstall script to this:
"preinstall": "([ ! -f package-lock.json ] && npm install --package-lock-only --ignore-scripts --no-audit); npx npm-force-resolutions"
This will only run npm install to create your initial package-lock.json when it does not exist yet.
This is much faster than always running both (npm + npx).
As of npm 8.3.0, you can also use npm's override:
{
"overrides": {
"graceful-fs": "^4.2.4"
}
}
in the resolutions section, you must fix version
"resolutions": {
"graceful-fs": "4.2.4",
},
Hi #NthDegree the only way which worked for me was to first run the normal npm install and then add the packages-lock.json file to git. After doing that when you add "preinstall": "npx npm-force-resolutions", it always updates the dependency resolution to the version mentioned.
I am not sure if adding packages-lock.json file to git is good or bad but by using this method the CI/CD pipeline works as well.
If all of the above answers don't work and you still get sh: npm-force-resolutions: command not found
try the following:
Just change:
"preinstall": "npx npm-force-resolutions"
To:
"preinstall": "npx force-resolutions"
npx force-resolutions does not run when no package-lock.json is detected, and allows the next command inline to be executed as normal
Credit to: https://github.com/rogeriochaves/npm-force-resolutions/issues/10#issuecomment-885458937

Reference npm script from npm script

Consider the following example package.json fragment:
{
// ...
"scripts": {
"start": "npm run b -- --watch",
"build": "builder --in src --out dest"
}
// ...
}
In this, I run build from start, and give it an extra flag. The problem with this approach is it actually creates another instance of the NPM run. It works, but it's ugly.
Is there a clean way to reference the build command from the start command without having to make another call to NPM?
Is there a clean way to reference the build command from the start command without having to make another call to NPM?
Not really.
If you just don't like npm's verbose output, you can silence that with npm run b -s -- --watch.
If you are calling multiple npm scripts from one parent script, you may want to look into an npm task runner. Here is a list of a few: https://github.com/RyanZim/awesome-npm-scripts#task-runners. (Disclaimer: awesome-npm-scripts is my personal project)

NPM install doesn't trigger babel build if dependencies not coming from NPM

For example, if in my package.json, i have this:
"dependencies": {
"cacheman": "2.1.0" }
it works and it will trigger the building script inside cacheman when I do npm install.
however, if i do this:
"dependencies": {
"cacheman": "https://github.com/cayasso/cacheman.git" }
it won't work. npm install will not trigger the build process for cacheman.
why is that?
The script you are referring is pre-publish script which runs before publishing the npm module to npm registry. Check here package.json#L9
Extract shown here
"scripts": {
"test": "make test",
"prepublish": "make"
}
When you install it from github there is no publish step so the script is not run.
If you want to install from github only and have the script run, you can add it as postinstall script of cacheman (you will have to fork the repo to make changes if you are not owner of cacheman).
"scripts": {
"test": "make test",
"prepublish": "make",
"postinstall": "make"//Added postinstall
}
Check examples in npm scripts documentation for more details.

Run npm scripts using local deps

Currently I run npm scripts using local deps this way:
package.json:
"scripts": {
"test": "node ./node_modules/karma/bin/karma start",
"node-test": "node ./node_modules/jasmine/bin/jasmine",
"build": "node ./node_modules/gulp/bin/gulp build"
},
I don't want to use global deps, since I can forgot to add deps to the package.json. This way when a local dep is missing, then I got an error message and I don't have problems because some deps are not installed globally, e.g. karma plugins.
Is there a better (shorter) way to define npm scripts using the local libs? Is this travis compatible?
edit:
If it wasn't obvious I have the same libs installed globally, but I want to use the local installs by these projects. That means when I start karma with karma start then the globally installed version will start the karma server, which means that if I don't have all of the karma plugins globally installed, then I got error.
Another problem that I have windows, so the solutions described here: How to use package installed locally in node_modules? do not work. Windows does not recognize the #!/bin/sh and the #!/usr/bin/env node head sections and there is no sh command as far as I can tell. At least not in webstorm terminal. Git bash has the sh command, but I want to run these npm scripts from webstorm terminal.
One possible solution could be to fix somehow webstorm so it could use sh from terminal. After that I could use $(npm bin) I assume. But that's just a guess. I am not sure whether this can be done.
npm automatically puts prepends the path ./node_modules/.bin to your PATH env before it executes commands run by using npm run (including the two "magic" shortcuts npm start and npm test)
npm scripts docs
You can just set this up with:
"scripts": {
"test": "karma start",
"node-test": "jasmine",
"build": "gulp build"
}
Assuming that you have karma, jasmine and gulp-cli listed in either your devDependencies or dependencies (so that they're install when doing npm install)
And yes, it is travis-compatible. Here is an example of a package that is tested on travis using tap which is installed locally as a module:
https://github.com/scriptoLLC/couchdown/

How can I invoke npm on heroku command line (to install bower components)?

Bower is for client side Javascript what npm is for the server side and reads a component.json file to recognize dependencies that should be fetched at deploy time so I'd be happy it heroku would run it at slug compilation time.
Unfortunately I can not invoke npm or bower from a heroku console or one-off command (heroku run "npm help") (heroku run bash -> npm help) as it's possible with ruby's rake. I've put npm and node (latest/x versions) in my package.json but in the engines section, not the dependencies.
I think this could be solved by customizing the node buildpack but I consider this a little too heavy task just for activating something so obvious.
You can also setup a postintall command, something like this in your package.json
"dependencies": {
"bower": "0.6.x"
},
"scripts": {
"postinstall": "./node_modules/bower/bin/bower install"
}
Then npm install will also install bower dependencies.
Pros : one command to rule them all.
Cons : you unnecessarily embed bower as a dependency.
You can use run like this:
heroku run npm install git://github.com/webjay/kaiseki
You should declare NPM dependencies in the package.json file
All you install from shell will be deleted on exit shell. You are in a cloned instance.
You can use bower directly like this
"dependencies": {
"bower": "^1.7.9"
},
"scripts": {
"postinstall": "sudo bower install --allow-root "
}

Resources