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 🙏

© 2026 – Pkg Stats / Ryan Hefner

retried

v1.0.0

Published

A minimal, type-safe asynchronous operation retry utility for TypeScript.

Readme

retried.ts

A minimal, type-safe asynchronous operation retry utility for TypeScript.

License: MIT

Why retired?

Retrying failed asynchronous operations (like network requests) is a common requirement. While libraries like async-retry existed already in this space, retried.ts aims to provide:

  1. Simplicity: The core logic is straightforward and contained within a single, small function.
  2. Type Safety: Built with TypeScript, providing clear interfaces and type checking out-of-the-box.
  3. Modern Approach: Uses modern async/await syntax.
  4. Maintainability: Addresses the fact that async-retry appears less actively maintained and lacks first-class TypeScript support.

Copy, Don't Install

This library is intentionally simple. Instead of adding another dependency to your package.json for such a small utility, I strongly encourage you to copy the src/retry.ts code directly into your project.

Benefits:

  • Zero Dependencies: No extra baggage in your node_modules.
  • Full Control: Easily understand, modify, and adapt the code to your specific needs without waiting for library updates.
  • Transparency: You know exactly what code is running.
  • Reduced Complexity: Avoids potential version conflicts or the overhead of managing another dependency.

Keep your codebase lean and maintain control over simple utilities like this!

Usage

  1. Copy: Copy the contents of src/retry.ts (including the RetryConfig interface and the retry function) into your project (e.g., src/utils/retry.ts).
  2. Import: Import the retry function where needed.
  3. Wrap: Wrap your asynchronous function call with retry.

Basic Example

import { retry } from "./utils/retry"; // Adjust path as needed

async function mightFail(): Promise<string> {
    const random = Math.random();
    if (random < 0.7) {
        console.log("Operation failed, throwing error...");
        throw new Error("Failed to complete operation");
    }
    console.log("Operation succeeded!");
    return "Success!";
}

async function run() {
    try {
        const result = await retry(mightFail);
        console.log(`Final Result: ${result}`);
    } catch (error) {
        console.error(`Operation ultimately failed after retries: ${error}`);
    }
}

run();

Example with Options

import { retry, RetryConfig } from "./utils/retry"; // Adjust path

async function fetchData(url: string): Promise<Response> {
    const response = await fetch(url);
    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
}

async function getImportantData() {
    const retryOptions: Partial<RetryConfig> = {
        retries: 5, // Try 5 times total (1 initial + 4 retries)
        baseTimeout: 500, // Start with 500ms delay
        strategy: "exponential", // Double the delay each time
        onRetry: (error) => {
            console.warn(`Attempt failed: ${error}. Retrying...`);
        },
    };

    try {
        const data = await retry(() => fetchData("https://api.example.com/data"), retryOptions);
        console.log("Successfully fetched data:", data);
    } catch (error) {
        console.error("Failed to fetch data after multiple retries:", error);
    }
}

getImportantData();

⚙️ Configuration Options (RetryConfig)

You can pass an optional configuration object as the second argument to retry.

| Option | Type | Default | Description | |--------------|-----------------------------------------|-----------|--------------------------------------------------------------------------------------------------| | retries | number | 3 | Total number of attempts (initial attempt + retries). | | baseTimeout| number | 100 | Initial delay in milliseconds before the first retry. | | maxTimeout | number | 300000 | Maximum delay in milliseconds between retries. | | strategy | 'exponential' | 'fixed' | exponential | 'exponential': Doubles the timeout each retry. 'fixed': Keeps timeout constant. | | onRetry | (error: unknown) => void | undefined | undefined | Callback function executed before each retry attempt (after a failure). |

Note: The actual delay includes a small random jitter (0-1000ms by default) added to the calculated timeout to help prevent thundering herd issues.

Testing

The retry function is designed to be testable. It accepts an optional third argument, delayFn, which defaults to a function using setTimeout. You can provide a mock delay function (e.g., using vi.fn().mockResolvedValue(undefined) from vitest) to test the retry logic without actual delays. See the accompanying test file (retry.test.ts if you copied it) for examples.

Acknowledgements

This utility is heavily inspired by the excellent async-retry library by Vercel. It aims to provide a similar core functionality with a focus on TypeScript and simplicity, encouraging direct integration rather than dependency installation.

License

MIT License - see the LICENSE file for details. (You'll need to add an MIT license file to your repo if you don't have one).