execa icon indicating copy to clipboard operation
execa copied to clipboard

Add `childProcess.readable` and `childProcess.writable`

Open ehmicky opened this issue 2 years ago • 2 comments

Background: #143

New feature

We could add the following properties:

  • childProcess.readable: like childProcess.stdin, but as a ReadableStream. This is undefined if childProcess.stdin is undefined, i.e. if the stdin option is not pipe (its default value).
  • childProcess.writable: same but for childProcess.stdout, as a WritableStream. If childProcess.stdout is undefined but childProcess.stderr is not, the latter is used instead. If the all option is true, childProcess.all is used instead. I.e. users can choose stdout, stderr or both. Any error thrown by the child process is propagated to childProcess.writable.

This can be easily implemented using Stream.Readable.toWeb() and Stream.Writable.toWeb().

TransformStream

Having a readable and writable properties would allow childProcess to be used as a TransformStream (even if it's not an instance of it) in Stream.pipeline(), Stream.compose() and ReadableStream.pipeThrough().

This is also useful for users who want to manipulate stdin/stdout/stderr directly but prefer web streams.

Example

import { pipeline } from 'stream/promises'

await pipeline(
  execa(...),
  execa(...),
  myTransformingStream,
  createReadStream('filePath'),
)

This also works well with $.

await pipeline(
  $`ls mydir`,
  $`sort`,
  $`head -n 20`,
)

ehmicky avatar Dec 14 '23 18:12 ehmicky

👍

sindresorhus avatar Dec 14 '23 22:12 sindresorhus

I have pushed a readable-writable branch which implements this. However, this seems rather unstable and needs more work. Notably, the tests are randomly failing.

The main issue is about how to propagate errors between the web streams (readable/writable), the Node.js streams (process.stdin|stdout|stderr) and the child process. It is not very easy because the web streams API does not allow consumers to error a stream, only producers.

So, in that branch, childProcess can be used as a TransformStream. However, when a child process errors, the stream does not emit an error event.

This is quite a hard issue to solve. :thinking:

ehmicky avatar Dec 17 '23 03:12 ehmicky

Closed by https://github.com/sindresorhus/execa/issues/143#issuecomment-2002306393 and https://github.com/sindresorhus/execa/pull/912

ehmicky avatar Mar 17 '24 04:03 ehmicky