Search code examples
node.jsnpmnpm-scriptsworking-directory

Set CWD for NPM script that runs a binary


I have a super-project that hosts sub-projects and contains common dependencies:

super
  node_modules
    .bin
      foo-binary
      foo-binary.exe
    foo
  sub
    node_modules
    package.json
  package.json

I need to be able to call foo either as super NPM script:

super/package.json

"scripts": {
  "foo": "foo-binary" <-- should run with super/sub/ as CWD
}

In this case foo-binary runs with super/ as CWD, while it should run with super/sub/. The use of cd results in cross-platform problems; cd sub && ..\\node_modules\\.bin\\foo-binary with backslashes works on Windows but not *nix OSes, while cd sub && ../node_modules/.bin/foo-binary with forward slashes fails on Windows (tested on Windows 7):

".." is not recognized as an internal or external command, operable program or batch file

Or I need to be able to call foo either as super NPM script:

super/sub/package.json

"scripts": {
  "foo": "../node_modules/.bin/foo-binary"
}

In this case platform-specific paths fail on Windows, too.

There are several reasons why sub cannot have foo as its own dependency, one of them is that all sub-projects should consistently use the same foo version and not occupy space with multiple foo copies.

How can current working directory be set in this case, cross-platform and preferably without adding custom scripts to the project?


Solution

  • Enclose the path that is defined in your npm-script with JSON escaped double quotes i.e. \"...\".

    For instance:

    "scripts": {
      "foo": "cd sub && \"../node_modules/.bin/foo-binary\""
    }
    

    This will now run successfully cross-platform - via windows cmd.exe and *nix sh.