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

@resili/fetch

v0.1.0-alpha.1

Published

Native fetch adapter for Resili.

Downloads

22

Readme

@resili/fetch

Native fetch adapter for Resili.

@resili/fetch wraps a fetch-compatible function with @resili/core, returning a function with the same call shape as native fetch(input, init?).

Use this package when you want retry, timeout, circuit breaker, bulkhead, rate limiting, fallback, or custom policies around fetch calls without changing the rest of your code to a different HTTP client.

For the full framework overview, see the repository README.

Installation

pnpm add @resili/core @resili/fetch
npm install @resili/core @resili/fetch
yarn add @resili/core @resili/fetch

Node.js 20 or newer is required. By default, the adapter uses globalThis.fetch. You may also inject a fetch-compatible implementation for tests.

Quick Start

import { createFetch } from "@resili/fetch";

const resilientFetch = createFetch({
  timeout: { perAttemptMs: 1_000 },
  retry: { maxAttempts: 3, jitter: "none" },
});

const response = await resilientFetch("https://api.example.com/users", {
  method: "GET",
});

The returned function is typed as:

(input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;

createFetch()

import { createFetch, type FetchImplementation } from "@resili/fetch";

const fetchImplementation: FetchImplementation = async (input, init) => {
  return await fetch(input, init);
};

const resilientFetch = createFetch({
  fetch: fetchImplementation,
  timeout: { perAttemptMs: 2_000 },
});

createFetch() accepts the implemented @resili/core configuration fields:

| Field | Purpose | | ---------------- | ------------------------------------------- | | retry | Retry failed calls. | | timeout | Apply per-attempt timeout behavior. | | circuitBreaker | Stop calls while a dependency is unhealthy. | | bulkhead | Bound concurrency and queue depth. | | rateLimiter | Limit request rate in memory. | | fallback | Return an alternate Response on errors. | | classifier | Override failure classification. | | store | Override the state store service. | | clock | Override timers and time source. | | policies | Register custom policy factories. |

The fetch option is adapter-specific and is removed before configuration is passed to @resili/core.

Retry Example

import { createFetch } from "@resili/fetch";

const resilientFetch = createFetch({
  retry: {
    maxAttempts: 3,
    backoff: "exponential",
    baseDelayMs: 100,
    maxDelayMs: 1_000,
    jitter: "none",
  },
});

const response = await resilientFetch("https://api.example.com/orders");

Retry behavior is provided by @resili/core. Deterministic jitter: "none" is supported by the current retry policy.

Timeout Example

import { createFetch } from "@resili/fetch";

const resilientFetch = createFetch({
  timeout: { perAttemptMs: 750 },
});

const response = await resilientFetch("https://api.example.com/health");

The adapter shallow-copies RequestInit and sets init.signal to the Resili context signal for each execution. Resili's signal overrides a caller-provided init.signal.

Fallback Example

import { createFetch } from "@resili/fetch";

const resilientFetch = createFetch({
  timeout: { perAttemptMs: 500 },
  fallback: {
    handler() {
      return new Response("cached fallback", { status: 200 });
    },
  },
});

const response = await resilientFetch("https://api.example.com/status");

Fallback handlers may return a Response or a promise for one.

Custom Policies

import { definePolicy } from "@resili/core";
import { createFetch } from "@resili/fetch";

const headerPolicy = definePolicy({
  name: "headers-observer",
  order: { before: "timeout" },
  create() {
    return {
      name: "headers-observer",
      order: { before: "timeout" },
      execute(ctx, next) {
        console.log(ctx.requestId);
        return next(ctx);
      },
    };
  },
});

const resilientFetch = createFetch({
  policies: [{ factory: headerPolicy }],
});

Testing With an Injected Fetch

import { createFetch, type FetchImplementation } from "@resili/fetch";

const fakeFetch: FetchImplementation = async () => {
  return new Response("ok", { status: 200 });
};

const resilientFetch = createFetch({ fetch: fakeFetch });
const response = await resilientFetch("https://example.test");

Injected fetch implementations are useful for deterministic tests and for custom runtime environments.

Current Limitations

  • The adapter does not classify HTTP status codes.
  • The adapter does not transform response bodies.
  • The adapter does not retry based on Response.status by itself.
  • The adapter does not add headers or mutate caller-provided RequestInit.
  • The adapter does not provide OpenTelemetry or metrics exporters.
  • The adapter is intentionally a thin wrapper over @resili/core.

If you need status-code classification, provide a core classifier or custom policy that matches your application contract.

Documentation

License

MIT © Resili contributors.