3

I've searched for days but did not find an answer that worked for my problem.

I want to run a npm script through cmd or Powershell in Windows and pass values for script variables. I would like the bellow script in package.json:

"scripts": {
    "happy-birthday": "echo Happy birthday $NAME and many returns!"
    }

To output:

Happy birthday Danny and many returns!

With a command like:

npm run happy-birthday --NAME=Danny

Everything I tested so far gives me:

Happy birthday $NAME and many returns!

It feels like npm does not recognize this as a variable and prints it like it is a string. I also tested %NAME%.

Npm version - 6.12.1

Danny Boy
  • 355
  • 3
  • 10

1 Answers1

2

You can't pass arguments to the middle of npm scripts, argument(s) can only be passed to the end of them. See my answer here for further explanation.

Given your example, consider the following solution which will work successfully across all platforms:

  1. In your package.json file define your happy-birthday npm script as follows:

    "scripts": {
      "happy-birthday": "node -e \"console.log('Happy birthday %s and many returns!', process.argv[1] || 'Jane')\""
    }
    
  2. Then run the following command via cmd or Powershell (or any other command line tool).

    npm run happy-birthday -- Danny
    

    This will print:

    Happy birthday Danny and many returns!

    Note: If you just run the following command, i.e. without passing an argument:

    npm run happy-birthday
    

    It will print the default name instead:

    Happy birthday Jane and many returns!


Explanation:

  • The npm script utilizes the nodejs command line option -e to evaluate the inline JavaScript as follows:

    console.log('Happy birthday %s and many returns!', process.argv[1] || 'Jane')
    
  • The arguments passed via the CLI, e.g. Danny, are read using process.argv - whereby we reference the Array element at index 1.

  • The Logical OR Operator, i,e. || is utilized to return Jane when no argument is passed.


Edit: Setting environment variables instead

Alternatively may want to consider setting an environment variable and referencing it in your npm script.

  1. In your npm script define your happy-birthday npm script as follows:

    "happy-birthday": "echo Happy birthday %NAME% and many returns!"
    

    Note the %NAME% notation used by Windows only to reference the variable.

  2. Using cmd

    When using cmd (i.e. Command Prompt) you'll need to run the following command:

    set NAME=Danny&& npm run happy-birthday
    

    Using Powershell

    When using Powershell you'll need to run the following command instead:

    $env:NAME="Danny" ; npm run happy-birthday
    

Note: The default shell that npm utilizes for npm scripts is sh on *nix and cmd on windows. Therefore the aforementioned methods defined in steps 1 and 2 will fail on *nix platforms.

If cross-platform support is requirement and you do want to take this approach of setting environment variables and referencing them via npm scripts, then consider utilizing the cross-env package.

Community
  • 1
  • 1
RobC
  • 22,977
  • 20
  • 73
  • 80
  • 1
    Thanks a lot for the quick answer! It worked! Could you please also provide an example with passing more arguments than just one? – Danny Boy Apr 27 '20 at 09:53
  • 1
    For more than one argument you'll need to set your npm script to something like this: `"foo": "node -e \"console.log('First: %s Second: %s Third: %s', process.argv[1], process.argv[2], process.argv[3])\""`. Then if you run: `npm run foo -- A B C` it will print: `First: A Second: B Third: C`. I've also updated the answer to show you you can set environment variables and reference them. – RobC Apr 27 '20 at 10:29