Search code examples
node.jsspawn

How to present node spawn arguments


Before people start crying "duplicate", I've already examined

The first of these is basically the same question in a different use case and as a result the answers do not address my use case.

So... how do you encode a command line like the following with named parameters separated from their values by a space?

arduino-cli compile --fqbn arduino:avr:nano

Should it look like this (1)?

let cp = child.process(
  "/path/to/arduino-cli.exe", 
  [
    "compile", 
    "--fqbn arduino:avr:nano"
  ]
);

or this (2)?

let cp = child.process(
  "/path/to/arduino-cli.exe", 
  [
    "compile", 
    "--fqbn", 
    "arduino:avr:nano"
  ]
);

or this (3)?

let cp = child.process(
  "/path/to/arduino-cli.exe", 
  [
    "compile", 
    "fqbn", 
    "arduino:avr:nano"
  ]
);

or this (4)?

let cp = child.process(
  "/path/to/arduino-cli.exe", 
  {
    _: ["compile"],
    fqbn: "arduino:avr:nano"
  }
);

TypeScript won't allow the last option even though I suspect it is the right answer, so I submit the problem for wider consideration.


Solution

  • After setting up for repeatable testing

        let args: any[] = [];
        args.push(["compile", `--fqbn ${selectedBoard.board.fqbn}`]);
        args.push(["compile", "--fqbn", selectedBoard.board.fqbn]);
        args.push(["compile", "fqbn", selectedBoard.board.fqbn]);
        args.push({ _: ["compile"], fqbn: selectedBoard.board.fqbn });
        let cp = child_process.spawn(cliPath, args[1], { cwd: getInoPath() });
        cp.stdout.on("data", (data: any) => outputChannel.append(data.toString()));
        cp.stderr.on("data", (data: any) => outputChannel.append(data.toString()));
        cp.on("error", (err: any) => {
          outputChannel.append(err);
        });
    

    I found that @jfriend00 was right, it is indeed the second arguments version

    ["compile", "--fqbn", selectedBoard.board.fqbn]
    

    but there was another problem causing it to fail – the CWD needed to be set in the options.

    let cp = child_process.spawn(cliPath, args[1], { cwd: getInoPath() });
    

    The key insight here is to capture both error events and stderr. The failure was reported on stderr and no error event was raised. After exposing stderr the problem was quickly resolved.