Reference npm script from npm script - node.js

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)

Related

execute several "npm scripts" in order

I would like to command "electron-packer ." (it takes some time) and then "asar pack app app.asar"
Is it possible to do this?
Or should I simply wait for the first one and command the second?
You can queue commands like this.
npm run pack1 && npm run pack2
Or you can add another line that does the above and just run that alone.
"scripts": {
"pack": "npm run pack1 && npm run pack2"
}
Add this inside your "scripts" and you can just run npm run pack to run both of those commands.

Passing arguments to combined npm script

I have in my package.json the following
"scripts": {
...
"prod": "gulp build --production && webpack --env.config=production"
}
I now want to pass a parameter "theme" to both gulp and webpack to be able to adjust the output of the build process from the command line.
I figured out how to pass it to webpack: npm run prod -- --env.theme=themename but gulp does not take care of this. I also played around with the yargs-package, processs.argv and bash string substitution by changing the npm script to "gulp build --production \"$1\" && webpack --env.config=production" but that did not work out either.
How can this be achieved? What am I missing? Any hints highly appreciated!
If you're using Bash you can use a function in your npm-script.
For instance:
"scripts": {
...
"prod": "func() { gulp build --production \"$1\" && webpack --env.config=production \"$1\"; }; func"
}
However, for a cross-platform solution you'll need to consider invoking a nodejs script which exec's the commands - in a similar way shown in Solution 2 of my answer here.

Override `npm install` script for NPM project

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

Pass npm script command line arguments to a specific script inside it

I have a scenario where I have to run three npm script to achieve some result in my application. I combined them in one npm script. This is my package.json:
"scripts": {
"setup": "npm install && npm run some-script && npm install",
"some-script": "gulp some-other-script"
}
what I would like to do is to pass arguments to setup script from command line which will be passed further to the some-script script.
If I run npm run script -- --abc=123 the arguments are added at the end of the script but I would like to pass it to specific script (in this case to npm run some-script). I also tried to rewrite script definition like this:
"setup": "npm install && npm run some-script -- --sample=sample&& npm install" but with no luck.
I'm aware of shell functions (described here: Sending command line arguments to npm script and here https://github.com/npm/npm/issues/9627) but I need a solution which will work cross-platform.
Is there a way to do that?
Ok I found a work around.
1st goal was to be able to use some script with arguments, and cascade this to the calls of other scripts :
npm run main -- --arg1
"main": "npm run script1 && npm run script2"
Problem with this approach is that the cascading would only be done by adding the arg passed to npm run main at the END of the line "npm run script1 && npm run script2". I could find no way to pass it to the 1st element : npm run script1
Here is the work around I found :
1st you need to add in package.json:
"config": {
"arg1": "ARG_VALUE"
},
Then in your script you can add it to the call like this :
"main": "npm run script_no_arg1 && npm run scrip1 -- --%npm_package_config_arg1% && npm run script2 -- --%npm_package_config_component% && npm run script_no_arg2"
Finally, You don't need to call it with any arg : npm run main
But you need to modify ARG_VALUE before launc the script :)
Last thing : in my case I was calling gulp tasks :
"cleardown": "rimraf build lib",
"inline-build-templates": "gulp inline-build-templates",
"step1": "npm run cleardown && npm run inline-build-templates -- --%npm_package_config_arg1%",
It works you can get the argument into the gulp task that way :
gulp.task('inline-build-templates', function() {
let component = process.argv[3];
component = component.split('--')[1];
console.log('RUNNING GULP TASK : inline-build-templates for component ' + component);
// whatever task gulp
});
Hope it helps.

Silencing errors on failures for npm run-script

When you run npm test and it fails, you get the test outputs + a single error message, like so:
npm ERR! Test failed. See above for more details.
However, I made a custom script called lint, like so:
// package.json
{
// ...
"scripts": {
// ... definition for test ...
"lint": "./node_modules/jsxhint/cli.js src/",
}
}
Alright, simple enough. But when you run npm run lint and it fails, Rather than the nice looking error for npm test, you get a massive error message after the output of the linter:
npm ERR! Darwin 14.0.0
npm ERR! argv "node" "/usr/local/bin/npm" "run-script" "lint"
npm ERR! node v0.10.32
npm ERR! npm v2.1.7
npm ERR! code ELIFECYCLE
# and ~15 more lines...
Is there a way to silence all this junk so I can have a clean output like the npm test script? I see how they caught the error in the npm source code, but I don't think I can just add a custom command without forking npm like that... Hope I'm wrong!
But if I am, would I be better off just pushing off a task like this to a tool like Grunt? Thanks!
Use the npm run --silent option:
$ npm run --silent test
Even less typing if you define a shell alias:
$ alias run='npm run --silent'
$ run test
If you don't care about preserving the return code of the linter process, you can always configure your package.json like this:
{
// ...
"scripts": {
// ...
"lint": "eslint . || true",
}
}
I've just been trying to figure out the same. Not a perfect answer but it kind of worked to specify linting as a pretest script (docs) like so:
// package.json
{
// ...
"scripts": {
// ... definition for test ...
"pretest": "./node_modules/jsxhint/cli.js src/",
}
}
Then, when you type in npm test the first time, you will only get a single-line error from NPM. Obviously, that means you won't be able to run your tests if you haven't linted.
The other option is to use some kind of third party task runner like Make, Grunt or Gulp.
I've only used Make, and I think it's the most painless to set up (at least on OSX and Linux, not sure about Windows).
Create a Makefile in your root that looks like so:
lint:
./node_modules/.bin/jslint ./*.js # or whatever your lint command is
test:
./node_modules/.bin/mocha test/*.js # or whatever your test command is
.PHONY: lint test
Then type make test and make lint to run those commands.
You can silence the errors by redirecting the stderr to /dev/null. For example:
{
"test": "karma start" (package.json)
}
running:
$ npm run test 2> /dev/null
will now send all npm errors to /dev/null but normal input will still be visible in the console.
Because the error is thrown by npm, after karma exiting with a non-zero status, doing the following is not enough:
{
"test": "karma start 2> /dev/null"
}
but you can overcome it by creating another task that calls that task with stderr redirection:
{
"test": "karma start",
"test:silent": "npm run test 2> /dev/null"
}
this will ensure that the npm error messages are hidden

Resources