Reputation: 10340
Is it possible to read CLI arguments in a scripts
entry of a package.json
. I am looking for something like this:
{
"scripts": {
"example": "ts-node --project tsconfig.json ./examples/${1}/.ts"
}
}
where ${1}
would be replaced by the first argument passed to
npm run example yadda
and eventually run
ts-node --project tsconfig.json ./examples/yadda/.ts
I know I can write a JS file that can be called and run by npm that will read the CLI args, but I am wondering if I can read the args right from the npm script entry.
Upvotes: 0
Views: 420
Reputation: 24962
Unfortunately npm does not, nor intends to, provide a builtin feature which allows arguments to be passed to the middle of a npm script (as stated here). Arguments can only be passed to the end of a script.
Given that in your example you're wanting to pass an argument to the middle of a script, (to essentially create a new pathname), you'll need to utilize a workaround.
On *nix platforms (Linux, macOS, ...) the default shell utilized by npm is sh
. Therefore you can utilize a shell function in npm-scripts as a mechanism for handling arguments which are intended to be passed to the middle of a script.
package.json
...
"scripts": {
"example": "func() { ts-node --project tsconfig.json \"./examples/${1}.ts\"; }; func"
},
...
Explanation:
func
part, invokes the arbitrarily named shell function; func
, which is defined at the beginning of the script. Essentially the argument (e.g. yadda
) which is provided via the CLI is passed to it.func
function we execute the ts-node
command. The argument (e.g. yadda
) is referenced in the body of the function using $1
(i.e. the first positional parameter/argument).Running:
Running the following command via your command line;
npm run example yadda
will eventually run as:
ts-node --project tsconfig.json ./examples/yadda.ts
Notes:
Windows, which utilizes cmd.exe
as the default shell, will choke at the aforementioned solution.
You may want to consider also utilizing Shell Parameter Expansion to provide a default value when no argument is provided via the CLI. For instance:
package.json
...
"scripts": {
"example": "func() { ts-node --project tsconfig.json \"./examples/${1:-foobar}.ts\"; }; func"
^^^^^^^^
},
...
Note the ${1:-foobar}
part instead of just ${1}
. This means that running the script without providing an argument. For instance:
npm run example
will eventually run as:
ts-node --project tsconfig.json ./examples/foobar.ts
^^^^^^
However, when an argument is provided, such as:
npm run example yadda
it will still run as before, i.e.
ts-node --project tsconfig.json ./examples/yadda.ts
Cross-platform:
If a cross platform solution, i.e. one that runs with both sh
and cmd.exe
, is required then you're left with really only one option, which is as you say: "write a JS file that can be called and run by npm that will read the CLI args [ ...using process.argv
and shell-out the ts-node
command using execSync()
or exec()
]
Upvotes: 0
Reputation: 5484
You can set your example command to run a script
{
"scripts": {
"example": "node --project tsconfig.json ./yourscript.js"
}
}
Then in your script use the arguments
var args = process.argv.splice(process.execArgv.length + 2);
args.forEach((value, index) => {
console.log(`Argument ${index} is: ${value}`);
});
You could then call your script running npm run example arg1 arg2
and use one of the arguments to import/require another file or run the specific code conditionally.
Upvotes: 0
Reputation: 4469
You can use the following syntax (not specific to npm itself)
$MY_VAR=foo npm run example
and in your scripts section do that
"example": "ts-node --project tsconfig.json ./examples/$MY_VAR/.ts"
Upvotes: 1