Sending command line arguments to npm script
npm 2 and newer
It's possible to pass args to npm run
since npm 2 (2014). The syntax is as follows:
npm run <command> [-- <args>]
Note the --
separator, used to separate the params passed to npm
command itself, and the params passed to your script.
With the example package.json
:
"scripts": {
"grunt": "grunt",
"server": "node server.js"
}
here's how to pass the params to those scripts:
npm run grunt -- task:target // invokes `grunt task:target`
npm run server -- --port=1337 // invokes `node server.js --port=1337`
Note: If your param does not start with -
or --
, then having an explicit --
separator is not needed; but it's better to do it anyway for clarity.
npm run grunt task:target // invokes `grunt task:target`
Note below the difference in behavior (test.js
has console.log(process.argv)
): the params which start with -
or --
are passed to npm
and not to the script, and are silently swallowed there.
$ npm run test foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js', 'foobar']
$ npm run test -foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js']
$ npm run test --foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js']
$ npm run test -- foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js', 'foobar']
$ npm run test -- -foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js', '-foobar']
$ npm run test -- --foobar
['C:\\Program Files\\nodejs\\node.exe', 'C:\\git\\myrepo\\test.js', '--foobar']
The difference is clearer when you use a param actually used by npm:
$ npm test --help // this is disguised `npm --help test`
npm test [-- <args>]
aliases: tst, t
To get the parameter value, see this question. For reading named parameters, it's probably best to use a parsing library like yargs or minimist; nodejs exposes process.argv
globally, containing command line parameter values, but this is a low-level API (whitespace-separated array of strings, as provided by the operating system to the node executable).
Edit 2013.10.03: It's not currently possible directly. But there's a related GitHub issue opened on npm
to implement the behavior you're asking for. Seems the consensus is to have this implemented, but it depends on another issue being solved before.
Original answer (2013.01): As a some kind of workaround (though not very handy), you can do as follows:
Say your package name from package.json
is myPackage
and you have also
"scripts": {
"start": "node ./script.js server"
}
Then add in package.json
:
"config": {
"myPort": "8080"
}
And in your script.js
:
// defaulting to 8080 in case if script invoked not via "npm run-script" but directly
var port = process.env.npm_package_config_myPort || 8080
That way, by default npm start
will use 8080. You can however configure it (the value will be stored by npm
in its internal storage):
npm config set myPackage:myPort 9090
Then, when invoking npm start
, 9090 will be used (the default from package.json
gets overridden).
Pass command line args to npm scripts in package.json
Short Answer:
Essentially, what you're wanting is to have an npm-script something like this, whereby <arg-here>
is provide via the CLI;
...
"scripts": {
"my-build": "npm run vumper <arg-here> && npm run format",
...
},
...
However, unfortunately npm does not have a built-in feature to achieve this.
The special npm option --
, (refer to the end of Solution 1 below for further info about this option), can only be used to pass an argument to the END of a script but NOT into the MIDDLE. So, if your two commands were in the opposite order, the --
option could be used like this:
...
"scripts": {
"my-build": "npm run format && npm run vumper --",
...
},
...
To overcome the limitation of there being no built-in feature to pass an argument into the MIDDLE of a script consider the following solutions:
For a Bash only solution refer to the "Solution 1" section.
If cross platform support is required then follow the solution described in the "Solution 2" section.
Solution 1 - Bash (MacOS/Linux/ etc..):
Configure your my-build
script in the scripts
section of package.json to invoke a Bash shell function, as shown below:
package.json
...
"scripts": {
"my-build": "func() { npm run vumper \"$1\" && npm run format; }; func",
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
...
Explanation:
The Bash function named func
does the following:
- Firstly runs
npm run vumper <arg>
. Whereby<arg>
will be the shell argument passed via the CLI. It is referenced in the script using$1
(i.e. the first positional parameter/argument). - Subsequently it runs the script named
format
via the commandnpm run format
.
These two npm run
commands are chained using the &&
operator, so the second npm run format
command will only run if the initial npm run vumper <arg>
command completes successfully (i.e. returns a 0
exit code).
Running my-build
script:
To invoke my-build
via your CLI you'll need to run:
npm run my-build -- dv
Note:
In this instance the trailing
dv
part is the argument that will be passed to yourvumper
script.The special option
--
must be specified before the argument. The docs describe the--
option as:... The special option
--
is used bygetopt
to delimit the end of the options. npm will pass all the arguments after the--
directly to your script: ... The arguments will only be passed to the script specified afternpm run
and not to any pre or post script.
Solution 2 - Cross-platform:
For a cross-platform solution, (one which works successfully with Bash, Windows Command Prompt / cmd.exe, and PowerShell etc..), you'll need to utilize a nodejs helper script as follows.
run.js
Let's name the nodejs script run.js and save it in the projects root directory, at the same level as package.json.
const execSync = require('child_process').execSync;
const arg = process.argv[2] || 'dv'; // Default value `dv` if no args provided via CLI.
execSync('npm run vumper ' + arg, {stdio:[0, 1, 2]});
execSync('npm run format', {stdio:[0, 1, 2]});
package.json
Configure your my-build
script to invoke run.js as follows:
...
"scripts": {
"my-build": "node run",
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
...
Running my-build
script:
As per Solution 1, to invoke my-build
via your CLI you'll need to run:
npm run my-build -- dv
Explanation:
run.js utilizes
process.argv
to obtain the argument passed via the CLI (e.g.dv
). If no argument is provided when runningnpm run my-build
the default value, (i.e.dv
), is passed to thevumper
npm-script.run.js also utilizes
child_process.execSync(...)
to shell-out/invoke the twonpm run
commands.
Pass parameter to npm run my command and use that parameter in my functions
const params = process.argv.slice(2)
Now this param variable has all the parameters passed with the npm run command.
npm run send myEmail@domain.com
params[0] // this will provide you with the value myEmail@domain.com
Pass arguments to npm script in order to execute
This is easier than you think. Just get rid of the $USER= and $PASS= parts of your command.
Command should look like this:
npm run e2e --params.login.user=User1 --params.login.password=Pass01
You also need to modify your script in the package.json. Change it to the following and you will be all set.
"e2e": "protractor dist/out-tsc/e2e/cucumberconfig.js"
How to pass command-line variable in package.json script, in NPM?
I found the magic recipe
I simply have this in my package.json
"scripts": {
"build": "npm ci && gulp build"
}
and use the following command line
$ npm run build -- --gitTag 1.0.0
and get the wanted packageName-1.0.0.zip
artifact.
Run npm script with optional params
You can achieve it using the https://www.npmjs.com/package/@naholyr/cross-env package, which supports default values for variables. On top of that, it will make your script OS-agnostic. Here's how:
"scripts": {
"example": "cross-env INPUT=${npm_config_input:false} npm run _example",
"_example": "cross-env command $INPUT"
},
For a reason yet unknown to me, using echo
as the command
will not print the variable value. But I'm successfully using this pattern to run sass
with arguments, and fallback values, if no arguments are passed.
Related Topics
Chrome Doesn't Delete Session Cookies
How to Detect My Browser Version and Operating System Using JavaScript
What Does It Mean Global Namespace Would Be Polluted
Change Type of Input Field with Jquery
Convert a String to a Template String
Find by Key Deep in a Nested Array
Rotate the Elements in an Array in JavaScript
Firing a Keyboard Event in Safari, Using JavaScript
Uncaught Referenceerror: Function Is Not Defined with Onclick
How to List the Properties of a JavaScript Object
Why Is It Necessary to Set the Prototype Constructor
How to Detect Internet Speed in JavaScript
Calling a Parent Window Function from an Iframe