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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@boredland/node-ts-cache

v4.0.0

Published

Simple and extensible caching module with Stale-While-Revalidate (SWR) strategy support.

Readme

@boredland/node-ts-cache

Simple and extensible caching module with Stale-While-Revalidate (SWR) strategy support.

CI The MIT License

Install

npm i @boredland/node-ts-cache

Usage

Wrap your function calls with withCacheFactory

Function wrapper factory for arbitrary async functions. The cache key is calculated based on the parameters passed to the function.

import {
  withCacheFactory,
  CacheContainer,
  LRUStorage,
} from "@boredland/node-ts-cache";

const cache = new CacheContainer(new LRUStorage());

const someFn = (input: { a: string; b: number }) => Promise.resolve("result");

const wrappedFn = withCacheFactory(cache)(someFn, {
  prefix: "my-function",
  cacheTimeMs: 60000,
  staleTimeMs: 120000,
});

const result = await wrappedFn({ a: "hello", b: 123 });

Caching Strategy: Stale-While-Revalidate (SWR)

The withCache wrapper implements the Stale-While-Revalidate (SWR) caching strategy:

  • Fresh content (within cacheTimeMs): returned immediately without revalidation
  • Stale content (within staleTimeMs after expiration): returned immediately while revalidating in the background
  • Expired content (beyond staleTimeMs): waits for fresh revalidation
  • No caching (when cacheTimeMs=0 and staleTimeMs=0): function executes every time

This strategy is ideal for scenarios where:

  • You want fast response times even with slightly outdated data
  • Background revalidation is acceptable
  • You want to minimize the number of cache misses

Options

const wrappedFn = withCacheFactory(cacheContainer)(someFn, {
  // Cache key prefix for namespacing
  prefix?: string;

  // Time in milliseconds after which cached content is considered "expired"
  // During this period, cached content is returned immediately without revalidation
  // Default: 0 (no caching)
  cacheTimeMs?: number;

  // Time in milliseconds after which cached content is considered "stale"
  // Used for Stale-While-Revalidate: stale content is returned immediately while revalidation happens in the background
  // Must be greater than cacheTimeMs to be effective
  // Default: 0 (no stale caching)
  staleTimeMs?: number;

  // Custom cache key calculation function
  // Default: hash-based on parameters
  calculateKey?: (params: Parameters) => string;

  // Conditional caching predicate
  // Return true to cache the result, false to skip caching
  shouldStore?: (result: Awaited<Result>) => boolean;

  // Concurrency limit for background revalidation tasks
  // Default: 1
  revalidationConcurrency?: number;
});

Example: Different Cache Configurations

No Caching (Pass-through)

const wrappedFn = withCacheFactory(cache)(someFn, {
  cacheTimeMs: 0,
  staleTimeMs: 0,
});

Fresh-only Caching (60 seconds)

const wrappedFn = withCacheFactory(cache)(someFn, {
  cacheTimeMs: 60000,
  staleTimeMs: 0,
});

Stale-While-Revalidate (Fresh for 60s, stale for 120s)

const wrappedFn = withCacheFactory(cache)(someFn, {
  cacheTimeMs: 60000,
  staleTimeMs: 120000,
  revalidationConcurrency: 5,
});

Using getItem and setItem directly

import { CacheContainer, LRUStorage } from "@boredland/node-ts-cache";

const myCache = new CacheContainer(new LRUStorage({ max: 1000 }));

class MyService {
  public async getUsers(): Promise<string[]> {
    const cachedUsers = await myCache.getItem<string[]>("users");

    if (cachedUsers?.content) {
      return cachedUsers.content;
    }

    const newUsers = ["Alice", "Bob"];

    await myCache.setItem("users", newUsers, {
      ttl: 60000, // Content expires after 60 seconds
      staleTtl: 120000, // Content is stale after 120 seconds
    });

    return newUsers;
  }
}

Storage Adapters

LRUStorage

In-memory LRU (Least Recently Used) cache with automatic eviction:

import { LRUStorage } from "@boredland/node-ts-cache";

const storage = new LRUStorage({ max: 10000 });
const container = new CacheContainer(storage);

Features:

  • In-memory caching with automatic eviction
  • LRU eviction policy when capacity is reached
  • Configurable maximum size
  • Perfect for testing and single-process applications

FallbackStorage

Cascading storage that tries multiple storages in order:

import {
  FallbackStorage,
  LRUStorage,
  RedisStorage,
} from "@boredland/node-ts-cache";

// Try Redis first, fall back to LRU if Redis is unavailable
const storage = new FallbackStorage([
  new RedisStorage(),
  new LRUStorage({ max: 5000 }),
]);

const container = new CacheContainer(storage);

Behavior:

  • On getItem: tries each storage in order until finding a hit
  • If found in a lower-priority storage: writes it back to all higher-priority storages
  • On setItem: always writes to the primary storage, attempts to write to others in the background
  • Ensures data consistency across multiple storage layers

Logging

This project uses debug to log useful information. Set environment variable DEBUG=node-ts-cache to enable logging.

Running Tests

npm test

Development & Testing

Setup

cd node-ts-cache
npm i
npm run build
npm test
npm run lint

Commands

  • npm test - Run test suite with Vitest
  • npm run lint - Run TypeScript and Biome linting
  • npm run build - Build the project

LICENSE

Distributed under the MIT License. See LICENSE.md for more information.

Credits

As this is a fork of the original node-ts-cache, all credit goes to the upstream project by havsar.

Structural changes have been made by boredland in order to align more with their use-case.

Project Link: https://github.com/boredland/node-ts-cache