Sasgorilla
Sasgorilla

Reputation: 3130

What shell-like syntax is supported by node in package.json scripts?

In my Node package.json scripts, I can use some light shell syntax:

scripts: {
  detect-cheese: "echo 'Is there cheese?' $($* | grep -q cheese && echo yep || echo nope)"
}
$ yarn run detect-cheese apple cheese banana
Is there cheese? yep

But this seems to be a subset of Bash (or some other shell's) syntax. For instance, optional arguments are hard to do:

scripts: {
  fox: "echo fox $1", 
  cat: "echo cat ${1-Rufus}"
}

$ yarn run fox
Unbound argument #1
$ yarn run cat Chester
Unbound variable "1-Rufus"

Are the details of this shell-like syntax documented somewhere?

Upvotes: 3

Views: 339

Answers (1)

Matt
Matt

Reputation: 74811

npm and yarn v1

The shell on unix like systems is sh so stick to POSIX sh definitions.

A default for a null or undefined value in sh is ${VAR:-default}

cat: "echo \"cat ${1:-Rufus}\""

yarn 2+ berry

Use a minimal sh implementation yarnpkg-shell which supports the basic shell syntax but is not fully POSIX compliant. This enables all environments, with or without sh, to execute package.json scripts in the same manner.


Test running the following:

printf 'VAR=  %s\n' "$VAR"
printf 'VAR-  %s\n' "${VAR-def}"
printf 'VAR:- %s\n' "${VAR:-def}"
printf 'VAR+  %s\n' "${VAR+def}"
printf 'VAR:+ %s\n' "${VAR:+def}"

via:

{
  "name": "so36729207-npm-sh",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "sh": "printf 'VAR=  %s\n' \"$VAR\"; printf 'VAR-  %s\n' \"${VAR-def}\"; printf 'VAR:- %s\n' \"${VAR:-def}\"; printf 'VAR+  %s\n' \"${VAR+def}\"; printf 'VAR:+ %s\n' \"${VAR:+def}\""
  }
}

Produces the same results for sh in dash/Debian, ash/Alpine and zsh/macos environment

$ docker run --rm so36729207/alpine npm run sh      

> [email protected] sh
> printf 'VAR=  %s
> ' "$VAR"; printf 'VAR-  %s
> ' "${VAR-def}"; printf 'VAR:- %s
> ' "${VAR:-def}"; printf 'VAR+  %s
> ' "${VAR+def}"; printf 'VAR:+ %s
> ' "${VAR:+def}"

VAR=  
VAR-  def
VAR:- def
VAR+  
VAR:+ 
$ docker run --rm --env VAR= so36729207/alpine npm run sh

> [email protected] sh
> printf 'VAR=  %s
> ' "$VAR"; printf 'VAR-  %s
> ' "${VAR-def}"; printf 'VAR:- %s
> ' "${VAR:-def}"; printf 'VAR+  %s
> ' "${VAR+def}"; printf 'VAR:+ %s
> ' "${VAR:+def}"

VAR=  
VAR-  
VAR:- def
VAR+  def
VAR:+ 
$ docker run --rm --env VAR=a so36729207/alpine npm run sh

> [email protected] sh
> printf 'VAR=  %s
> ' "$VAR"; printf 'VAR-  %s
> ' "${VAR-def}"; printf 'VAR:- %s
> ' "${VAR:-def}"; printf 'VAR+  %s
> ' "${VAR+def}"; printf 'VAR:+ %s
> ' "${VAR:+def}"

VAR=  a
VAR-  a
VAR:- a
VAR+  def
VAR:+ def

Upvotes: 2

Related Questions