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

cachify-function

v0.1.0

Published

A simple

Readme

cachify-function

A modular, zero-dependency, type-safe utility for caching sync or async functions in both Node.js and the browser (ES modules or CommonJS). You keep full type information while choosing the caching strategy that fits each call site: cache, stale-while-revalidate, or always-fresh.


Features

  • Fully type-safe – function generics propagate the exact argument and return types through every helper.

  • Modular – one small file, no third-party packages; tree-shakable ES export per helper.

  • Multiple run modes

    • runCache – standard “return if fresh, otherwise compute”.
    • runStale – stale-while-revalidate with optional silent background errors.
    • runFresh – force new execution, replacing the cache.
    • runFreshCached – reuse an in-flight promise if one is already running.
  • Fine-grained invalidation – per-key (invalidate) or global (invalidateAll).

  • Perf-oriented – constant-time lookups, minimal timers, in-flight promise deduping.


Installation

npm i cachify-function

Quick start

import * as cf from 'cachify-function';

const delay = (ms: number) => new Promise<number>(res => setTimeout(() => res(ms), ms));

const delayCfc = cf.cachify(delay, {
    max_age: 5000, // fresh for 5 s
    max_age_auto_invalidate: 10000
});

(async () => {
    // First call → takes a full second.
    console.time('first');
    await cf.runCache(delayCfc, 1000);
    console.timeEnd('first'); // ≈1000 ms

    // Cached call → instant.
    console.time('cached');
    await cf.runCache(delayCfc, 1000);
    console.timeEnd('cached'); // <1 ms

    // Force a fresh run.
    console.time('fresh');
    await cf.runFresh(delayCfc, 1000);
    console.timeEnd('fresh'); // ≈1000 ms

    // Deduping in-flight promises.
    console.time('dedupe');
    const p1 = cf.runFreshCached(delayCfc, 2000); // starts work
    const p2 = cf.runFreshCached(delayCfc, 2000); // re-uses same promise
    console.log('same promise:', p1 === p2); // true
    await Promise.all([p1, p2]); // finishes once
    console.timeEnd('dedupe'); // ≈2000 ms total

    // After 6s the entry is stale but still present.
    await delay(6000);
    console.time('stale');
    await cf.runStale(delayCfc, 1000); // returns immediately,
    // then revalidates in background
    console.timeEnd('stale'); // <1 ms

    // Manual invalidation.
    cf.invalidate(delayCfc, 1000); // remove that key
    cf.invalidateAll(delayCfc); // or wipe everything
})();

Why is it type safe?

Because each helper is generic over the original function:

// Type of `user` is still { id: string; name: string }
const user = await runCache(userCfc, 'u_123');

No casts, no any, no surprise unknowns.


API surface (concise)

| Helper | Purpose | | ------------------------------------------------- | --------------------------------------------------------- | | cachify(fn, options)CachifyFunctionContext | Wrap once, configure cache. | | runCache(ctx, ...args) | Return cached value if fresh, else compute & cache. | | runStale(ctx, ...args) | Return cached value even if stale; refresh in background. | | runFresh(ctx, ...args) | Always compute; overwrites cache, dedupes any in-flight. | | runFreshCached(ctx, ...args) | Use current in-flight promise or compute fresh. | | invalidate(ctx, ...args) | Remove one cached entry. | | invalidateAll(ctx) | Clear every entry for that context. |

Options for cachify(fn, options):

| Name | Default | Notes | | ---------------------------------- | ----------------------- | ---------------------------------------------------------------------------- | | max_age | 0 | Fresh-until age (ms). 0 = never stale. | | max_age_auto_invalidate | 1.5 × max_age | Delete entry after this age (ms). 0/false disables. Must be ≥ max_age. | | suppress_stale_revalidate_errors | true | Don’t surface background-refresh errors. | | get_cache_key(...args) | serialize.generateKey | Custom key generator. (Recommended that you use this) |


Modular build usage

// ESM
import { runCache } from 'cachify-function/runCache.js';

// CommonJS
const { runCache } = require('cachify-function');

License

MIT © 2025 VastBlast