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

@youneed/server-plugin-store

v0.1.0

Published

Distributed key-value contract (KV) + in-process MemoryKV. The backing store is chosen by adapter (redis/postgres/deno via @youneed/server-plugin-pubsub-*).

Readme

@youneed/server-plugin-store

The distributed key-value contract (KV) plus an in-process default (MemoryKV). The framework never hosts shared state — it defines the contract here and lets the deployment choose where data physically lives by plugging in an adapter. Consumers (session store, rate-limit, cache) take a KV and don't care which backend is behind it.

Values are strings — callers serialize (JSON, etc.). TTLs are in seconds.

import { MemoryKV, namespaced, type KV } from "@youneed/server-plugin-store";

const kv: KV = new MemoryKV();

await kv.set("user:1", JSON.stringify({ name: "Ada" }), { ttl: 60 });
await kv.get("user:1");          // → '{"name":"Ada"}'  (undefined once expired)
await kv.incr("hits", { ttl: 60 }); // → 1, atomic, expiry set only on creation
await kv.ttl("hits");            // → remaining seconds (-1 no expiry, -2 missing)

// Share one backend across consumers without key collisions:
const sessions = namespaced(kv, "sess");   // every key becomes "sess:<key>"
const rate = namespaced(kv, "rl");

The KV contract

interface KV {
  get(key: string): Promise<string | undefined>;
  set(key: string, value: string, opts?: SetOptions): Promise<void>;
  delete(key: string): Promise<void>;
  incr(key: string, opts?: IncrOptions): Promise<number>;
  expire(key: string, ttl: number): Promise<void>;
  ttl(key: string): Promise<number>;   // ≥0 live · -1 no expiry · -2 missing
  scan?(prefix: string): Promise<string[]>;   // optional — for invalidation
  close?(): Promise<void>;                     // optional — release sockets
}

Every op is async (adapters may do network I/O). scan/close are optional — callers must tolerate their absence.

  • SetOptions — { ttl? } (expiry seconds; omit for none).
  • IncrOptions — { by?, ttl? }. by is the amount (default 1); ttl sets expiry only when this call creates the key — applied atomically with the increment, so it's a race-free counter.

MemoryKV

In-process KV backed by a Map, with lazy + periodic TTL expiry. Correct for a single instance; not shared across processes.

new MemoryKV({ now: () => Date.now(), sweepMs: 30_000 });
  • now — clock in epoch ms (injectable for tests).
  • sweepMs — proactive sweep interval (default 30s; 0 disables the timer, entries still expire lazily on access).
  • .size — entries currently held (after expiry).

namespaced(kv, ns)

Wrap a KV so every key is transparently prefixed with ns + ":". Lets several consumers share one backend without colliding; scan is prefixed and the namespace is stripped from results.

Related