npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

readable-stream-with-safe-resolvers

v1.0.0

Published

A safe, resolver-style wrapper for ReadableStream, allowing external push, close, and error operations safely.

Readme

readable-stream-with-safe-resolvers

npm version TypeScript

A small utility to create a ReadableStream with a safe, resolver-style interface, similar to Promise.withResolvers().
It allows you to push values into a stream, close it, or error it from outside, while automatically ignoring any operations after the stream has been finalized.

Installation

npm install readable-stream-with-safe-resolvers
# or
yarn add readable-stream-with-safe-resolvers

Usage

import { withSafeResolvers } from "readable-stream-with-safe-resolvers";

async function example() {
  const { stream, enqueue, close, error } = withSafeResolvers<number>();

  // Push values
  enqueue(1);
  enqueue(2);

  // Close the stream
  close();

  // Reading from the stream
  const result = [];
  for await (const value of stream) {
    result.push(value);
  }

  console.log(result); // → [1, 2]
}

example();

API

withSafeResolvers<T>()

Returns an object containing:

  • stream: ReadableStream<T> — the underlying stream.
  • enqueue(chunk: T) — pushes a new chunk into the stream. Ignored after the stream is finalized.
  • close() — gracefully closes the stream. Ignored if already finalized.
  • error(reason: unknown) — terminates the stream with an error. Ignored if already finalized.

Important:
Once the stream is finalized—via close(), error(), or consumer cancel()—all subsequent calls to enqueue, close, or error are silently ignored.

Example: Error Handling

import { withSafeResolvers } from "readable-stream-with-safe-resolvers";

async function exampleError() {
  const { stream, enqueue, error } = withSafeResolvers<number>();

  enqueue(10);
  enqueue(20);

  error(new Error("Something went wrong"));

  try {
    for await (const value of stream) {
      console.log(value);
    }
  } catch (err) {
    console.error(err); // → Error: Something went wrong
  }
}

exampleError();

Example: Safe Multiple Calls

const { stream, enqueue, close, error } = withSafeResolvers<number>();

enqueue(1);
close();
enqueue(2);    // ignored
close();       // ignored
error(new Error("oops")); // ignored

This demonstrates that operations after the stream is finalized are safe and have no effect.

When to Use

  • You want a pushable stream controlled from outside the consumer loop.
  • You want to avoid errors from multiple close/error/enqueue calls.
  • Useful for async generators, streaming APIs, or event emitters that need a stream interface.

License

MIT