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

request-refresher

v1.0.0

Published

A small service worker helper for 401 responses, coordinated refresh fetch, and retry

Readme

request-refresher

A small service worker helper that wraps fetch so 401 responses trigger a single coordinated refresh fetch, then one retry of the original request.

Features

  • Transparent to the call site — application code keeps using ordinary fetch; you wire the wrapper once in the service worker, and callers do not need refresh-specific logic or extra handling
  • 401-only — reacts when response.status === 401
  • Single-flight refresh — concurrent 401s share one in-flight refresh fetch
  • Optional callbackson_refresh_succeeded / on_refresh_failed for follow-up or cleanup (each runs at most once per coordinated refresh; see Configuration)
  • No runtime dependencies
  • ES modules — intended for module service workers

Installation

CDN (pinned)

// sw.js
import { build_fetch_with_refresh } from "https://cdn.jsdelivr.net/npm/[email protected]/src/index.js";

npm

npm install request-refresher
import { build_fetch_with_refresh } from "request-refresher";

Quick start

1. Register a module service worker

try {
	await navigator.serviceWorker.register("/sw.js", { type: "module" });
} catch (error) {
	console.error("Error registering module service worker:", error);
}

2. Use the wrapper in sw.js

import { build_fetch_with_refresh } from "https://cdn.jsdelivr.net/npm/[email protected]/src/index.js";

const fetch_with_refresh = build_fetch_with_refresh({
	refresh_request: new Request("/api/auth/refresh", { method: "POST" })
});

self.addEventListener("fetch", (event) => {
	const url = new URL(event.request.url);
	if (url.pathname.startsWith("/api/")) {
		event.respondWith(fetch_with_refresh(event.request));
	}
});

You must pass a refresh_request Request (at minimum a URL and method; add headers, body, or other Request options only if your API needs them). The wrapper fetches the incoming RequestInfo as usual. If the server responds with 401, the library performs that refresh fetch (each attempt uses a clone of refresh_request), then issues one more fetch on the original RequestInfo. Backends typically return 401 when the session is invalid; no special headers or service-worker-specific signals are required.

Backend refresh endpoint

A typical refresh route is a POST (or whatever your API uses) that validates a refresh credential and responds by setting two cookies:

  • Session cookie — scoped to Path=/ so it is sent on normal app requests (for example /api/...). The encoded session token is usually short-lived (for example about 1 hour).
  • Refresh cookie — scoped narrowly to the refresh URL only, for example Path=/api/auth/refresh in the snippets above, so the browser only sends it when calling that endpoint. The refresh token and cookie usually last longer (for example about 1 week).

Both are commonly HttpOnly and Secure (and SameSite as your threat model requires). The service worker does not read these cookies; the browser attaches them automatically on the refresh fetch and on the retried request. Your backend decides names, encoding, and exact lifetimes—this library only needs the refresh URL to succeed when a new session should be issued.

Configuration

refresh_request is required. Optional fields: customFetch (swap in your own fetch for mocks or composition), loggingEnabled, on_refresh_succeeded, on_refresh_failed.

Each of on_refresh_succeeded and on_refresh_failed runs at most once per refresh attempt, and concurrent 401s share one in-flight refresh—so each callback fires at most once for that shared refresh. Thrown errors in these callbacks are logged and do not alter which Response the wrapper returns.

const fetch_with_refresh = build_fetch_with_refresh({
	refresh_request: new Request("https://api.example.com/session/refresh", {
		method: "POST"
	}),
	loggingEnabled: false,
	on_refresh_succeeded: async () => {
		// e.g. update locally cached auth state — runs when the refresh response is OK
	},
	on_refresh_failed: async () => {
		// e.g. clear app cache — runs when refresh response is not OK
	}
});

Limitations

  • Only 401 triggers refresh (not other status codes).
  • At most one refresh attempt per 401 branch; no loop until success. If the retry still returns 401, that response is returned.
  • Refresh is always a fetch of refresh_request — there is no arbitrary async callback instead of fetch.

Example site

From the package root:

npm install
npm run example

Open the URL printed by serve (see package.json — default port 4173). Use the buttons to call a mocked /api/profile flow and reset demo state.

Development

npm test

Runs unit tests, Node e2e-style tests, and Playwright against example/.

License

MIT

Links