Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

fs-capacitor

mike-marcacci2.5mMIT8.0.0TypeScript support: included

Filesystem-buffered, passthrough stream that buffers indefinitely rather than propagate backpressure from downstream consumers.

stream, buffer, file, split, clone

readme

Continuous Integration Current Version Supported Node.js Versions

FS Capacitor

FS Capacitor is a filesystem buffer for finite node streams. It supports simultaneous read/write, and can be used to create multiple independent readable streams, each starting at the beginning of the buffer.

This is useful for file uploads and other situations where you want to avoid delays to the source stream, but have slow downstream transformations to apply:

import fs from "fs";
import http from "http";
import { WriteStream } from "fs-capacitor";

http.createServer((req, res) => {
  const capacitor = new WriteStream();
  const destination = fs.createWriteStream("destination.txt");

  // pipe data to the capacitor
  req.pipe(capacitor);

  // read data from the capacitor
  capacitor
    .createReadStream()
    .pipe(/* some slow Transform streams here */)
    .pipe(destination);

  // read data from the very beginning
  setTimeout(() => {
    capacitor.createReadStream().pipe(/* elsewhere */);

    // you can destroy a capacitor as soon as no more read streams are needed
    // without worrying if existing streams are fully consumed
    capacitor.destroy();
  }, 100);
});

It is especially important to use cases like graphql-upload where server code may need to stash earler parts of a stream until later parts have been processed, and needs to attach multiple consumers at different times.

FS Capacitor creates its temporary files in the directory ideneified by os.tmpdir() and attempts to remove them:

  • after writeStream.destroy() has been called and all read streams are fully consumed or destroyed
  • before the process exits

Please do note that FS Capacitor does NOT release disk space as data is consumed, and therefore is not suitable for use with infinite streams or those larger than the filesystem.

Ensuring cleanup on termination by process signal

FS Capacitor cleans up all of its temporary files before the process exits, by listening to the node process's exit event. This event, however, is only emitted when the process is about to exit as a result of either:

  • The process.exit() method being called explicitly;
  • The Node.js event loop no longer having any additional work to perform.

When the node process receives a SIGINT, SIGTERM, or SIGHUP signal and there is no handler, it will exit without emitting the exit event.

Beginning in version 3, fs-capacitor will NOT listen for these signals. Instead, the application should handle these signals according to its own logic and call process.exit() when it is ready to exit. This allows the application to implement its own graceful shutdown procedures, such as waiting for a stream to finish.

The following can be added to the application to ensure resources are cleaned up before a signal-induced exit:

function shutdown() {
  // Any sync or async graceful shutdown procedures can be run before exiting…
  process.exit(0);
}

process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
process.on("SIGHUP", shutdown);

API

WriteStream

WriteStream extends stream.Writable

new WriteStream(options: WriteStreamOptions)

Create a new WriteStream instance.

.createReadStream(options?: ReadStreamOptions): ReadStream

Create a new ReadStream instance attached to the WriteStream instance.

Calling .createReadStream() on a released WriteStream will throw a ReadAfterReleasedError error.

Calling .createReadStream() on a destroyed WriteStream will throw a ReadAfterDestroyedError error.

As soon as a ReadStream ends or is closed (such as by calling readStream.destroy()), it is detached from its WriteStream.

.release(): void

Release the WriteStream's claim on the underlying resources. Once called, destruction of underlying resources is performed as soon as all attached ReadStreams are removed.

.destroy(error?: ?Error): void

Destroy the WriteStream and all attached ReadStreams. If error is present, attached ReadStreams are destroyed with the same error.

WriteStreamOptions

.highWaterMark?: number

Uses node's default of 16384 (16kb). Optional buffer size at which the writable stream will begin returning false. See node's docs for stream.Writable. For the curious, node has a guide on backpressure in streams.

.defaultEncoding

Uses node's default of utf8. Optional default encoding to use when no encoding is specified as an argument to stream.write(). See node's docs for stream.Writable. Possible values depend on the version of node, and are defined in node's buffer implementation;

.tmpdir

Used node's os.tmpdir by default. This function returns the directory used by fs-capacitor to store file buffers, and is intended primarily for testing and debugging.

ReadStream

ReadStream extends stream.Readable;

ReadStreamOptions

.highWaterMark

Uses node's default of 16384 (16kb). Optional value to use as the readable stream's highWaterMark, specifying the number of bytes (for binary data) or characters (for strings) that will be bufferred into memory. See node's docs for stream.Readable. For the curious, node has a guide on backpressure in streams.

.encoding

Uses node's default of utf8. Optional encoding to use when the stream's output is desired as a string. See node's docs for stream.Readable. Possible values depend on the version of node, and are defined in node's buffer implementation.

changelog

fs-capacitor changelog

1.0.0

  • Initial release.

1.0.1

  • Use default fs flags and mode

2.0.0

  • Update dependencies.
  • Add tests for special stream scenarios.
  • BREAKING: Remove special handling of terminating events, see jaydenseric/graphql-upload#131

2.0.1

  • Update dependencies.
  • Move configs out of package.json
  • Use wx file flag instead of default w (thanks to @mattbretl via #8)

2.0.2

  • Update dev dependencies.
  • Fix mjs structure to work with node v12.
  • Fix a bug that would pause consumption of read streams until completion. (thanks to @Nikosmonaut's investigation in #9).

2.0.3

  • Emit write event after bytes have been written to the filesystem.

2.0.4

  • Revert support for Node.js v12 --experimental-modules mode that was published in v2.0.2 that broke compatibility with earlier Node.js versions and test both ESM and CJS builds (skipping --experimental-modules tests for Node.js v12), via #11.
  • Use package browserslist field instead of configuring @babel/preset-env directly.
  • Configure @babel/preset-env to use shipped proposals and loose mode.
  • Give dev tool config files .json extensions so they can be Prettier linted.
  • Don't Prettier ignore the lib directory; it's meant to be pretty.
  • Prettier ignore package.json and package-lock.json so npm can own the formatting.
  • Configure eslint-plugin-node to resolve .mjs before .js and other extensions, for compatibility with the pre Node.js v12 --experimental-modules behavior.
  • Don't ESLint ignore node_modules, as it's already ignored by default.
  • Use the classic TAP reporter for tests as it has more compact output.

3.0.0

  • Update dev dependencies.
  • Add support for Node.js v13 by no longer extending ReadStream and WriteStream from node's fs library.
  • Specify 0o600 for buffer file permissions instead of node's default 0o666
  • BREAKING: Remove several undocumented properties that existed for consistency with the extended classes.
  • BREAKING: No longer listen for SIGINT, and instead warn the application to add handlers for terminating signals.

4.0.0

  • Update source to typescript.
  • Add WriteStream.release replacing the functionality of an error-free WriteStream.destroy()
  • BREAKING: Change WriteStream.destroy() to immediately destroy attached ReadStreams even without an error.
  • BREAKING: Reluctantly remove exported .mjs files now that we have an external commonjs dependency and are still missing clear interop guidance from node.

4.0.1

  • Add cleanup example to README.md
  • Remove warnings about signal listeners.

5.0.0

  • Update dev dependencies.
  • Remove dependency on readable-stream to expose new (but internally unused) features of streams in node v13.
  • BREAKING: Remove support for node v8.

5.0.1

  • Add cleanup example to README.md
  • Remove warnings about signal listeners.

6.0.0

  • Update dev dependencies.
  • Add the ability to specify encoding and highWaterMark in createReadStream().
  • BREAKING: Remove "name" argument from createReadStream().

6.1.0

  • Add the ability to specify defaultEncoding and highWaterMark in new WriteStream().
  • Export ReadStreamOptions and WriteStreamOptions interfaces.
  • Add tests for highWaterMark option in createReadStream.
  • Add documentation of configuration options to README.

6.2.0

  • Upgrade dependencies.
  • Update option types to match changes in @types/node.

7.0.0

  • Upgrade dependencies.
  • Prevent Node.js max listeners exceeded warnings if many fs-capacitor ReadStream instances are created at the same time, fixing #30 via #42.
  • Ensure initialization failures are reported, fixing #45 via #46.
  • BREAKING: Drop support for node 13.
  • BREAKING: Drop support for node 10.
  • BREAKING: Change module type to ES module.

7.0.1

  • Publish TS definitions and map via #54.

8.0.0

  • Upgrade development dependencies.
  • BREAKING: Drop support for node 12.