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

yes

v0.2.7

Published

The ultimate primitive for async TypeScript: retries, caching, rate limits and validation as fast, typed options on async functions

Readme

yes adds retries, caching, deduplication, timeouts, rate limits and validation, as typed options, to the async function you, or your agent, already wrote, with its exact type kept. Where an agent would hand-roll a retry loop and a Map cache, a little differently in every file, it writes one option whose behavior is documented and tested once, and you review one line.

It is built to disappear. An operation is plain TypeScript: awaited, it returns what your function returns and throws what it throws. A string-key cache hit takes under a microsecond, a cached query ships about 5 KB gzipped on a server and under 6 KB in a browser, with no dependencies, every call path is benchmarked against a raw async call with a budget pnpm bench enforces, and an area you never use ships nothing.

Built inside Pullfrog to keep its GitHub API calls reliable when GitHub says no, and running there in production. Schemas and tools build on the same primitive today, and MCP, REST and RPC are coming. Start with one function: declare a read with yes.query and a write with yes.mutation.

import * as yes from "yes";

const getUser = yes.query({
  run: async (id: string) => db.users.findUnique({ where: { id } }),
  ttl: 60_000,
  retry: [100, 500],
});

await getUser("abc"); // executes
await getUser("abc"); // cache hit

const addCredits = yes.mutation({
  run: async (input: { userId: string; amount: number }) => db.credits.add(input),
});

await Promise.all([addCredits({ userId: "abc", amount: 1 }), addCredits({ userId: "abc", amount: 1 })]); // both run
npm install yes

yes runs on Node 22 or later, Bun and Deno, and bundles for browsers and edge runtimes, Cloudflare Workers and Next.js edge routes included, with no Node built-in to polyfill. Its types need TypeScript 5.4 or later and check clean on TypeScript 7.

To teach Claude Code, Codex or Cursor to reach for yes instead of hand-rolling a retry loop, install its Agent Skill:

npx skills add colinhacks/yes

Ask it anything

| Ask it | The answer | Read more | | --- | --- | --- | | Retry when it throws? | yes, with retry: [100, 500] | Retries | | Cache the result? | yes, with ttl: 60_000 | Caching | | Share concurrent calls? | yes, always, for a read | Reads and writes | | Keep my function's type? | yes, exactly typeof run | Types | | Validate what goes in and out? | yes, with any Standard Schema | Validation | | Stop when I abort? | yes, with ctx.signal | Cancellation | | Survive a 529 from a model API? | yes, with retry, timeout and a shared rateLimit | Model APIs | | Give up on a slow attempt? | yes, with timeout: 5_000 | Timeouts and limits | | Stay under an API's rate limit? | yes, with rateLimit or concurrency | Timeouts and limits | | Share a cache across servers? | yes, with yes.redisCache | Stores | | Let a model call it? | yes, as a Standard Tool | Tools | | Share or cache a write? | no: a mutation always runs | Reads and writes |

Coming soon

Every layer planned for yes is an operation underneath, so a retry or a ttl will mean the same thing on each. This is direction, not commitment, and the sketches can change:

  • MCP servers: tools served to any MCP client with yes.mcp, on the official SDK.
  • REST: type-safe, OpenAPI-first routes and routers with yes.rest.
  • RPC and a typed client: named procedures documented in OpenAPI, and a client typed from the router.

Docs

Every page is in docs/content/docs/, starting with the quick start. pnpm run docs serves the site at http://localhost:4000.

Develop

The repo runs on Node 24, which executes TypeScript files directly. A script that imports yes's source runs with --conditions=yes-src, so package.json's #hash import resolves to ops/ rather than to a built dist/:

pnpm install
pnpm test                         # tsc, then vitest with type assertions
node --conditions=yes-src play.ts # a runnable tour of the API
pnpm run docs                     # the docs site at http://localhost:4000
pnpm --filter yes-docs examples   # type-check every example in the docs