Shell scripting with Node.js
You can buy the offline version of this book (HTML, PDF, EPUB, MOBI) and support the free online version.
(Ad, please don’t block.)

11 Stream recipes



11.1 Writing to standard output (stdout)

These are three options for writing to stdout:

11.1.1 Writing to stdout via `console.log()

console.log(format, ...args) writes to stdout and always appends a newline '\n' (even on Windows). The first argument can include placeholders which are interpreted in the same way as they are by util.format():

console.log('String: %s Number: %d Percent: %%', 'abc', 123);

const obj = {one: 1, two: 2};
console.log('JSON: %j Object: %o', obj, obj);

// Output:
// 'String: abc Number: 123 Percent: %'
// 'JSON: {"one":1,"two":2} Object: { one: 1, two: 2 }'

All arguments after the first one always show up in the output, even if there are not enough placeholders for them.

11.1.2 Writing to stdout via a Node.js stream

process.stdout is an instance of stream.Readable. That means that we can use it like any other Node.js stream – for example:

process.stdout.write('two');
process.stdout.write(' words');
process.stdout.write('\n');

The previous code is equivalent to:

console.log('two words');

Note that there is no newline at the end in this case because console.log() always adds one.

If we use .write() with large amounts of data, we should take backpressure into consideration, as explained in §9.5.2.1 “writable.write(chunk).

The following recipes work with process.stdout: §11.4 “Node.js stream recipes”.

11.1.3 Writing to stdout via a web stream

We can convert process.stdout to a web stream and write to it:

import {Writable} from 'node:stream';
const webOut = Writable.toWeb(process.stdout);
const writer = webOut.getWriter();
try {
  await writer.write('First line\n');
  await writer.write('Second line\n');
  await writer.close();
} finally {
  writer.releaseLock()
}

The following recipes work with webOut: §11.5 “Web stream recipes”.

11.2 Writing to standard error (stderr)

Writing to stderr works similarly to writing to stdout:

See the previous section for more information.

11.3 Reading from standard input (stdin)

These are options for reading from stdin:

11.3.1 Reading from stdin via a Node.js stream

process.stdin is an instance of stream.Writable. That means that we can use it like any other Node.js stream:

// Switch to text mode (otherwise we get chunks of binary data)
process.stdin.setEncoding('utf-8');
for await (const chunk of process.stdin) {
  console.log('>', chunk);
}

The following recipes work with webIn: §11.4 “Node.js stream recipes”.

11.3.2 Reading from stdin via a web stream

We first have to convert process.stdin to a web stream:

import {Readable} from 'node:stream';
// Switch to text mode (otherwise we get chunks of binary data)
process.stdin.setEncoding('utf-8');
const webIn = Readable.toWeb(process.stdin);
for await (const chunk of webIn) {
  console.log('>', chunk);
}

The following recipes work with webIn: §11.5 “Web stream recipes”.

11.3.3 Reading from stdin via module 'node:readline'

The built-in module 'node:readline' lets us prompt users to enter information interactively – for example:

import * as fs from 'node:fs';
import * as readline from 'node:readline/promises';

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const filePath = await rl.question('Please enter a file path: ');
fs.writeFileSync(filePath, 'Hi!', {encoding: 'utf-8'})

rl.close();

For more information on module 'node:readline', see:

11.4 Node.js stream recipes

Readable streams:

Writable streams:

11.5 Web stream recipes

Creating a ReadableStream from:

Reading from a ReadableStream:

Transforming ReadableStreams:

Using WritableStreams: