1

I have the following script in my package.json:

{
  "build-dist": "tsc -p src/main/ts/tsconfig.json --outDir build/dist/npm-fs && cp LICENSE.txt README.md build/dist/npm-fs && node scripts/build/build-dist.mjs"
}

My script at scripts/build/build-dist.mjs requires a command line argument to be passed. Would it be possible to have this custom script at the beginning of this script chain and still receive and process passed command line arguments?

{
  "build-dist": "node scripts/build/build-dist.mjs && tsc -p src/main/ts/tsconfig.json --outDir build/dist/npm-fs && cp LICENSE.txt README.md build/dist/npm-fs"
}

It requires (and validates input) and throws an error if validation fails and since it requires a command line argument it has to be the last script called to correctly consume command line arguments. As a result, the first two scripts in the chain tsc -p src/main/ts/tsconfig.json --outDir build/dist/npm-fs && cp LICENSE.txt README.md build/dist/npm-fs are always executed regardless of whether validation fails or not. I'd much rather have fast-fail behavior and have execution completely halt if that script throws an error.

This question is essentially a duplicate of this. I'm hoping there's a new feature now available or maybe someone has figured out a more elegant solution.

Snap
  • 492
  • 5
  • 14
  • @RobC Thanks for the link! I'll have to look into it more when I get a chance. It looks promising but still more hackey than I'd prefer. I was really hoping npm had a more built in feature to achieve this. But hey, if it works it works, and I'll be more than happy with that! – Snap Dec 29 '20 at 10:31
  • AFAIK there's no built-in feature. If you're using _*nix_ then wrap your script in a [shell function](https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Functions) as per this example: `"build-dist": "func() { node scripts/build/build-dist.mjs \"$1\" && tsc -p src/main/ts/tsconfig.json --outDir build/dist/npm-fs && cp LICENSE.txt README.md build/dist/npm-fs; }; func"`. For cross-platform you'll need to utilize a custom node.js script. Also see the other answer, however that involves setting an environment variable - so also not ideal. – RobC Dec 29 '20 at 10:38
  • Unfortunately npm does not, nor intends to, provide a builtin feature which allows arguments to be passed to the middle of script - as stated [here](https://github.com/npm/npm/pull/5518#issuecomment-46915480). – RobC Dec 29 '20 at 10:55
  • Shoot, I had a feeling that might be the case. That's disappointing, I was hoping to leverage its cross-platform compatibility while also being able to adhoc scripts together in the `package.json`. Fortunately creating custom scripts to wrap up everything is certainly an option, but some of the npm module api's are *not* very friendly to use programmatically – Snap Dec 29 '20 at 18:25

1 Answers1

0

There is no built-in feature for that. A third-party tools may be of help.

Here is a cross-platform solution:

{
  "devDependencies": {
    "run-z": "^1.6.2",
    "shx": "^0.3.3"
  },
  "scripts": {
    "valid": "run-z --then node scripts/build/build-dist.mjs",
    "tsc": "run-z valid --then tsc -p src/main/ts/tsconfig.json --outDir build/dist/npm-fs",
    "copy": "run-z valid --then shx cp LICENSE.txt README.md build/dist/npm-fs",
    "build-dist": "run-z tsc,copy"
  }
}

Then run it like this:

npm run build-dist -- +valid <your options here>

Note that tsc and copy tasks would run in parallel to each other, while both require the valid task to complete first.

lorus
  • 131
  • 5
  • Thanks for the solution. There's a package to help out with everything, gotta love npm. I was wondering if there was a native solution, the less dependencies the better after all, but hey, I'm more than happy to leverage someone else's work :D – Snap Dec 29 '20 at 18:28