Cross-platform pipe command in NPM script
Asked Answered
I

3

7

Considering we have NPM script with a pipe, similarly to what's suggested in Istanbul documentation:

"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls"

It obviously doesn't take Windows into account.

How can such command with a pipe be made cross-platform in Node.js package?

The question is specific to Coveralls but isn't limited to it; this could be any command with a pipe.

Idealism answered 17/9, 2018 at 15:36 Comment(1)
Can you do this programmatically with node? I know that's overkill for a simple pipe command, but it will at least guarantee cross-platform compatibility.Apennines
M
4

Both Bash and the Windows command line (e.g. cmd.exe and PowerShell) have the pipe operator (|) so that shouldn't be a concern regarding cross-platform compatibility.

Given your example npm-script, the primary incompatibility regarding cross-platform support is usage of Bash's cat command. Usage of cat will fail via Windows cmd.exe, however cat is supported via Windows PowerShell.

To circumvent the aforementioned cross-platform issue regarding cat, consider utilizing a nodejs utility script as follows. Let's name the file cat.js:

cat.js

const fs = require('fs');

fs.readFile(process.argv[2], function(err, data) {
  process.stdout.write(data);
});

As you can see, it utilizes nodes builtin:

  • fs.readFile to read the contents of a file.
  • The file path of the file to read will be provided as an argument to the script and captured using process.argv.
  • The contents of the file is the written to process.stdout

Note: For the sake of brevity cat.js doesn't include any error capturing/handling, so you may wish to add some.

npm script

Then in your scripts section of your package.json we invoke cat.js and pass the path to the file (i.e. ./coverage/lcov.info) as an argument. For instance:

"scripts": {
  "coveralls": "node cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls"
},

Note: The npm-script above assumes cat.js resides in the same directory and level as package.json. If you choose to locate it elsewhere the path to it will need to be redefined. E.g. "node path/to/cat ./coverage/lcov.info | ..."

So long as the nodejs file specified on the right hand of the pipe (|) utilizes process.stdin to read from stdin, i.e file descriptor 0, (as coveralls.js does) using the pipe cross-platform will be OK.

Mcroberts answered 18/9, 2018 at 14:3 Comment(2)
I tried to avoid custom scripts if possible because they defy the purpose of using NPM scripts. If there's a script, it's tempting to move everything to it. Thanks for cat example, I just discovered github.com/shelljs/shx , I suppose shx cat will be drop-in replacement.Idealism
Yes shx cat is an ideal replacement. Interesting, I found it too tempting a while back and now all custom build logic and tooling reside in a separate .js script - analogous to what eslint do in package.json and Makefile.js. I use shelljs methods extensively in the .js script to address cross-platform. npm-script's alone were becoming too cryptic, non-human readable, lacked commenting, lacked customization of logic, etc...Mcroberts
A
1

While I have not used Windows in some time, its CMD.EXE command line processor supports command redirection as well as “piping” the output of one program to the input of another.

See Syntax Redirection for more information.

For piping programmatically, see the pipe-operator NPM module for a Node/JavaScript implementation of shell piping.

Altostratus answered 17/9, 2018 at 23:14 Comment(2)
Thanks, I guess the main problem here is cat, as suggested in another answer. I suppose windows native counterpart would look very different and possibly without |.Idealism
Under Windows, the type PATH can be used to pipe the contents of a file to another program.Altostratus
P
1

About

We have made a package exactly for this: https://github.com/cpuabuse/cross-cat

A cross platform cat command, behaving exactly like linux cat command. You can call it as cat or cross-cat from a script. It works with windows cmd and coveralls as well.

Install

npm install cross-cat --save-dev

Use

"scripts": {
    "coveralls": "cross-cat coverage/lcov.info | coveralls"
}

Philender answered 22/3, 2020 at 3:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.