How to check if npm script exists?
Asked Answered
V

3

32

I am creating a bash script which runs through each of my projects and runs npm run test if the test script exists.

I know that if I get into a project and run npm run it will give me the list of available scripts as follows:

Lifecycle scripts included in www:
  start
    node server.js
  test
    mocha --require @babel/register --require dotenv/config --watch-extensions js **/*.test.js

available via `npm run-script`:
  dev
    node -r dotenv/config server.js
  dev:watch
    nodemon -r dotenv/config server.js
  build
    next build

However, I have no idea how to grab that information, see if test is available and then run it.

Here is my current code:

#!/bin/bash

ROOT_PATH="$(cd "$(dirname "$0")" && pwd)"
BASE_PATH="${ROOT_PATH}/../.."

while read MYAPP; do # reads from a list of projects
  PROJECT="${MYAPP}"
  FOLDER="${BASE_PATH}/${PROJECT}"
  cd "$FOLDER"
  if [ check here if the command exists ]; then
    npm run test
    echo ""
  fi
done < "${ROOT_PATH}/../assets/apps-manifest"
Vervain answered 4/6, 2018 at 15:21 Comment(0)
F
49

EDIT: As mentioned by Marie and James if you only want to run the command if it exists, npm has an option for that:

npm run test --if-present

This way you can have a generic script that work with multiple projects (that may or may not have an specific task) without having the risk of receiving an error.

Source: https://docs.npmjs.com/cli/run-script

EDIT

You could do a grep to check for the word test:

npm run | grep -q test

this return true if the result in npm run contains the word test

In your script it would look like this:

#!/bin/bash

ROOT_PATH="$(cd "$(dirname "$0")" && pwd)"
BASE_PATH="${ROOT_PATH}/../.."

while read MYAPP; do # reads from a list of projects
  PROJECT="${MYAPP}"
  FOLDER="${BASE_PATH}/${PROJECT}"
  cd "$FOLDER"
  if npm run | grep -q test; then
    npm run test
    echo ""
  fi
done < "${ROOT_PATH}/../assets/apps-manifest"

It just would be a problem if the word test is in there with another meaning Hope it helps

Foskett answered 4/6, 2018 at 15:34 Comment(6)
FYI: Answer below (to use npm run test --if-present) is a better solutionCoughlin
I will add your suggestion @MarieHoeger as for the user case present it is indeed a better solution, I will still leave my other solution because for the exact description of the question (How to check if npm script exists?) my solution can be used in more cases and may help other users.Foskett
Awesome, thank you @Denis! I think my wording was also more blunt than I meant it to be. Apologies!Coughlin
Is it just me or is the --if-present solution... wrong? Not defining a "test" script and then running npm test, npm run test npm run-script test etc. both with and without the --is-present flag gives the same result: > echo 'Error: no test specified' Error: no test specifiedHerat
I checked and got the same behaviour here.. but it seems specific to the "test" command, for any other command it works. I think there is some sort of default test script if you don't define one, so it's always present (at least for the --if-present) but I couldn't anything on the documentation that back this upFoskett
Would change my vote if possible. See https://mcmap.net/q/447487/-how-to-check-if-npm-script-exists.Varick
M
19

The right solution is using the if-present flag:

npm run test --if-present

Magill answered 17/11, 2018 at 0:1 Comment(7)
Why is this the right solution? What does --if-present do? Please expand on this answer.Gypsum
The --if-present flag will only run the specified script if it is defined.Magill
So clarify that in your answer. Expand it, make it a truly great answer.Gypsum
Thank you @James!! This answer saved me :) Here's a link to the npm docs: docs.npmjs.com/cli/run-scriptCoughlin
I wish this were also applicable to yarnVesica
If you need to run the script if it exists ELSE do something else, this is not necessarily "the right solution".Donnadonnamarie
See https://mcmap.net/q/447487/-how-to-check-if-npm-script-existsVarick
V
2

--if-present doesn't allow you to "check if a npm script exists", but runs the script if it exists. If you have fallback logic this won't suffice. In my case, I want to run npm run test:ci if it exists and if not check for and run, npm run test. Using --if-present would run the test:ci AND test scripts if both exists. By checking if one exists first, we can decide which to run.

Because I have both "test" and "test:ci" scripts, the npm run | grep approach wasn't sufficient. As much as I'd like to do this with strictly npm, I have jq in my environments so I decided to go that route to have precision.

To check for a script named "test:ci":

if [[ $(jq '.scripts["test:ci"]' < package.json;) != null ]]; then
  // script exists
fi
Varick answered 5/12, 2022 at 20:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.