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

@serve-tools/signal-storage

v0.1.3

Published

Typed Web Storage change subscriptions and signal-backed watches

Downloads

654

Readme

@serve-tools/signal-storage

The @serve-tools/signal-storage package adds signal-backed watches to the typed, observable Web Storage client from @serve-tools/client-storage.

import { SignalStorage } from "@serve-tools/signal-storage";

const storage = new SignalStorage<{ theme: "dark" | "light" }>();
const theme = storage.watch("theme");

storage.set("theme", "dark");

console.log(theme.get()); // "dark"

Install

npm install @serve-tools/signal @serve-tools/signal-storage

Typed storage

Describe the keys and their string values once. The schema exists only in TypeScript and adds nothing at runtime.

import { SignalStorage } from "@serve-tools/signal-storage";

interface AppStorage {
	theme: "dark" | "light";
	token: string;
}

const storage = new SignalStorage<AppStorage>();

storage.set("theme", "dark");
storage.get("theme"); // "dark" | "light" | null
storage.has("theme"); // true
storage.delete("theme"); // true

Pass session to use sessionStorage instead, or a separate window to handle different browsing contexts.

const session = new SignalStorage<AppStorage>("session", window.top);

Change subscriptions

subscribe synchronously delivers every change occurrence for one key. It receives writes made through the wrapper in the current document and native storage events from other documents using the same storage area.

const unsubscribe = storage.subscribe("theme", (change) => {
	switch (change.kind) {
		case "added":
		case "updated":
			console.log(change.value);
	}
});

storage.set("theme", "light");

unsubscribe();

Changes are discriminated as added, updated, removed, or invalidated. An invalidation means the current value should be read again. Unchanged writes do not notify subscribers. Subscriptions are removed explicitly with the returned function or automatically with an AbortSignal.

Each occurrence uses a registration-order snapshot. A subscriber added during delivery waits until the next occurrence; a subscriber removed before its turn is skipped. If callbacks fail, every later active subscriber still runs. After delivery, one error is rethrown unchanged, while multiple errors are reported in delivery order in an AggregateError. Writes made through set or delete are committed before callback errors surface.

const controller = new AbortController();

storage.subscribe("token", updateAuthentication, { signal: controller.signal });
controller.abort();

The package listens for the global storage event only while at least one subscription or watch is active and filters events by storage area. Native clear events do not identify individual keys, so they invalidate every actively observed key.

Reactive watches

watch returns a read-only computed signal containing the current value. Known changes apply their exact deltas without rereading storage. Invalidations and explicit refresh() calls reread storage synchronously. Signal consumers may coalesce intermediate changes and observe only the latest value; use subscribe when every occurrence matters.

const theme = storage.watch("theme");

theme.get(); // "dark" | "light" | null

storage.set("theme", "light");

theme.get(); // "light"

storage.source.setItem("theme", "dark");

theme.get(); // still "light"

theme.refresh();

theme.get(); // "dark"

theme.dispose();

Direct same-document writes through source do not emit a storage event in that document, so call refresh() to make them visible to an active watch. Call dispose() or Symbol.dispose to stop following storage changes. Disposal is idempotent; a disposed signal retains its last observed value, and later refreshes are no-ops.

Public API

  • SignalStorage extends @serve-tools/client-storage with watch() while preserving size, get, has, set, delete, clear, subscribe, source, and target.
  • StorageSignal<Value> is a read-only computed signal with synchronous refresh() and terminal dispose() methods.
  • SignalStorage.Schema is the unrestricted string-keyed schema.
  • StorageChange, StorageSubscriber, StorageSubscribeOptions, StorageKey, and StorageValue are re-exported from @serve-tools/client-storage.

Compatibility

The package is an ES module for browser windows with Web Storage and a compatible @serve-tools/signal installation. Storage availability, persistence, quota, and privacy behavior remain controlled by the browser. Explicit resource management requires Symbol.dispose support or a compatible polyfill; dispose() is always available.

Agent Skill

This package includes skills/serve-tools-signal-storage/SKILL.md with version-aligned usage guidance for compatible coding agents. Activation is explicit; installing the package does not automatically trust or enable it.

Development

The default test command runs native Web Storage tests in Chromium, Firefox, and WebKit.

npx playwright install chromium firefox webkit
npm test --workspace @serve-tools/signal-storage

Run the opt-in Chromium benchmarks for watch lifecycle, change fanout, sparse updates, and refresh with:

npm run benchmark --workspace @serve-tools/signal-storage

License

MIT-0