27

I have a package.json that looks similar to this:

"scripts": {
    "dev": "cross-env BABEL_ENV=client webpack --config webpack/client.development.js && yarn dev:stub-server | cross-env BABEL_ENV=server babel-node src/server/server.js",
    "dev:stub-server": "./node_modules/.bin/robohydra ./stubs/robohydra-config.json -p 3100"
}

I added some logic in the code to change the way the dev:stub-server is configured depending on a command line argument. So, whenever I run the following I get what I expect:

yarn dev:stub-server --results=4
$ ./node_modules/.bin/robohydra ./stubs/robohydra-config.json -p 3100 -- --results=4

As you can see, the options are forwarded to the underlying script and everything works as expected.

My problem is that I cannot have the --results propagated from the yarn dev command to dev:stub-server in the correct position. The parent script runs dev:stub-server but the argument is forwarded to the underlying script at the end as follows:

yarn dev --results=2
$ cross-env BABEL_ENV=client webpack --config webpack/client.development.js && yarn dev:stub-server | cross-env BABEL_ENV=server babel-node src/server/server.js --results=2

Is there a way to make the above work as follows instead?

yarn dev --results=2
$ cross-env BABEL_ENV=client webpack --config webpack/client.development.js && yarn dev:stub-server --results=2 | cross-env BABEL_ENV=server babel-node src/server/server.js

Thanks in advance!

RobC
  • 20,007
  • 20
  • 62
  • 73
Luciano M. L.
  • 499
  • 1
  • 4
  • 9

9 Answers9

33

On mac I am using:

"scripts": {
  "benchmark": "sh -c 'ng run ${0}:benchmark'",
}

Which I then call yarn benchmark editor where editor is my parameter.

Philippe
  • 533
  • 5
  • 9
  • 2
    This will fail on windows, of course, unless you can tell everyone using your package that they need to install `bash` (either via cygwin or git for windows). I don't think this is reasonable for open source, but I use it all over the place for my closed-source project. – mrm Apr 06 '19 at 19:59
  • Hi, this is awesome, but can I pass the argument to somewhere inside executed script? I need something like `yarn semistandard --fix $(git diff --name-only HEAD HEAD~${0})` – Zennichimaro Sep 17 '20 at 03:10
  • Holy crap this saved me - thank you SO MUCH! Do you know why it starts at 0 not 1 though? – Geoff Davids Oct 06 '21 at 15:04
  • So is there a way to do this on Windows without bash? – marvc1 May 03 '22 at 12:22
26

Yarn's run only supports appending your args to the end of the command chain, and at least as of date 2018-06-14, there isn't a way to override that.

When I've needed this in the past, I've cooked up my own dev.js script that was called by my package.json, and pulled args out environment variables.

Sunil Garg
  • 12,670
  • 19
  • 110
  • 153
mrm
  • 4,553
  • 2
  • 29
  • 27
16

A straightforward way to achieve this is to write an inline Bash function using parameter expansion with $*:

"scripts": {
    "dev": "wrap () { node index.js \"$*\" | cat; }; wrap"
}

Calling the above with yarn dev foo bar will run node index.js foo bar and then pipe the result into cat as a demo.
You can tack on commands both to the start and the end, simply keep in mind that semis are required here.

For anything more involved you'll probably want a standalone script.

Etheryte
  • 22,936
  • 11
  • 65
  • 109
  • @Etheryte I'm missing something very basic here. On Windows, I'm running similar inline bash function in git bash, but getting `wrap is not recognized as an internal or external command...`. Any idea what could cause that? – M.Pogorzelski Jan 31 '22 at 15:17
  • For anyone encountering the same issue as a YARN user. Yarn by default uses `bin\sh`, in which this particular inline Bash function cannot be run. You need to set Yarn to use `bin\bash` by executing this `yarn config set script-shell bin\bash` – M.Pogorzelski Feb 01 '22 at 13:04
  • For those who use this solution, `"wrap () { node index.js $* | cat; }; wrap"` try this if it doesn't work without any parameters – shapeless Mar 28 '22 at 06:47
2

As an alternative you could use a *.env file and cat the variables out of it in your script.

"run":"docker build -t --build-arg VAR=`cat vars.env` -f Dockerfile .

for example

Daniel Einars
  • 126
  • 14
2

Do it like these. As yarn will deliver parameters essentially.

"scripts": {
  "runSomeShellScriptAlpha": "path/to/script_name.sh  $1 $2 $3", // redundant $x
  "runSomeShellScriptBeta": "path/to/script_name.sh",            // better 
}
yarn runSomeShellScriptBeta p1 p2 p3

The alpha one works only on Mac/Linux, not on Win10. It's bad.

The beta one works both on Mac/Linux and Win10.

W.Perrin
  • 3,181
  • 29
  • 28
  • This isn't working for me -- it doesn't replace `{script_name}` -- is it possible I'm missing something? – slifty Aug 27 '20 at 16:20
  • `{script_name}` means a customed file name. It is not a variable and won't be substituted by `shell`. Sorry for the brackets leading misunderstanding – W.Perrin Aug 28 '20 at 01:50
2

As for now, using yarn 1.22.4 you can do yarn exec tsc -- --help. Appending the -- does the trick

Ivan Gonzalez
  • 360
  • 1
  • 4
  • 12
2

You can dissect your script in preScript, Script and postScript.

Example with a git typescript library project i have:

"predeploy": "yarn build",
"dodeploy": "yarn config set version-git-message ",
"postdodeploy": "yarn version --minor && yarn config set version-git-message 'v%s'"

and then run

yarn dodeploy "my custom message"       
  • Can you elaborate? What is `v%s`? Why is `set` called twice? What happens when the command is run? – iamfrank Sep 27 '21 at 18:44
  • 1
    Frank, this is because yarn or npm version command has his own commit message specified by version-git-message git parameter, and by default his value is 'v%s'. This parameter 'v%s', is the version number. So when i do dodeploy "my custom message", im setting version-git-message parameter form 'v%s'. to "my custom message". Before that, a yarn build command is executed. and after dodeploy script is completed, postdeploy command is executed. here im only restoring default version-git-message parameter. – Felipe Rodriguez Herrera Sep 28 '21 at 14:11
0

I have posted something here (2 lines of code). https://stackoverflow.com/a/65265945/12463120

The thing is to be aware that Webpack is not forwarding the CLI. So, you have to save them first.

// webpack.config.js 
process.env.MY_APPLICATION_NAME_ARGS = JSON.stringify(process.argv)
// your.script.js
const myArgs = JSON.parse(env.MY_APPLICATION_NAME_ARGS )
0

use the npm ability to pass named custom arguments to command line as a proxy for your yarn commands:

 "scripts": {
      "yarn-cmd": "npm run npm-cmd --foo=bar",
      "npm-cmd": "echo \"foo value is $npm_config_foo\""
    }

run yarn yarn-cmd

read more: https://docs.npmjs.com/cli/v7/using-npm/config

Artem Kozlenkov
  • 667
  • 6
  • 11