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 🙏

© 2024 – Pkg Stats / Ryan Hefner

limited-cache

v2.2.0

Published

A minimal JS cache: like using an object, except it won't grow forever

Downloads

289

Readme

Limited-Cache

A minimal JS cache. Like using an object to store keys and values, except it won't grow forever

npm version build status test coverage dependencies status gzip size

Motivation

A plain Javascript object is often good enough for simple key-value caching.

The problem is that a plain object cache can grow forever -- especially if you persist it in local storage. This library adds a size limit, plus maxCacheTime and smarter removal of old items.

Usage

The plain API provides a standard cache interface:

const recentResults = LimitedCache({
  maxCacheSize: 100,
});
recentResults.set('abc', thingToSave);
recentResults.get('abc');
recentResults.has('abc');
recentResults.getAll();
recentResults.reset();

Use LimitedCacheObject for a nicer developer experience, using Proxy:

const recentResults = LimitedCacheObject();
recentResults['abc'] = thingToSave;

Low-level functions using plain objects, if you need to stay serializable or want to store offline:

const reduxState = {
  childIdsByParentId: {},
  cacheMeta: limitedCacheUtil.init(),
};

// cacheMeta is a plain, serializable object that contains the cache's internal state
cacheMeta = limitedCacheUtil.set(cacheMeta, 'abc', thingToSave);

return {
  ...reduxState,
  childIdsByParentId: limitedCacheUtil.getAll(cacheMeta),
  cacheMeta,
};

Typescript generics, to define a type for items in the cache:

const stringCache = LimitedCache<string>();
const myClassCache = LimitedCacheObject<SomeClass>();
const offlineCacheMeta = lowLevelInit<SomeObjectShape>();

Note: The React hooks were removed in v1.0 The code for useLimitedCache and useLimitedCacheObject is here if you want to implement them yourself. For most cases, a useMemo(() => LimitedCache(), [])) should be enough.

Install and Import

npm install limited-cache or yarn add limited-cache

import { LimitedCache, LimitedCacheObject, limitedCacheUtil } from 'limited-cache';

Options

maxCacheSize (number, default: 100)

Number of key/value pairs to keep in the cache. A falsy value will make it limitless.

maxCacheTime (milliseconds, default: 1 day, max: 1 year)

Time after which an item is removed. A falsy value will make it the 1-year maximum.

warnIfItemPurgedBeforeTime (milliseconds, default: 5000, development only)

If an item rotates out of the cache before this time passes, emits a warning to suggest you increase the cache size. Use a falsy value to disable.

Low-level functions

Under the hood, everything is tracked inside a single, serializable object (cacheMeta) which can be persisted to storage or kept in Redux or any other state.

You can retrieve this object from a LimitedCache or LimitedCacheObject, or create it directly via lowLevelInit:

myLimitedCache.getCacheMeta();
getCacheMetaFromObject(myLimitedCacheObject);

Do not manipulate cacheMeta directly: a set of low-level functions is available for that. Every action available on the higher-level LimitedCache and LimitedCacheObject is available as a low-level function.

  • lowLevelInit(options)
  • lowLevelGetOne(cacheMeta, cacheKey)
  • lowLevelGetAll(cacheMeta) - returns the entire cache, excluding expired items
  • lowLevelHas(cacheMeta, cacheKey)
  • lowLevelSet(cacheMeta, cacheKey, value)
  • lowLevelRemove(cacheMeta, cacheKey)
  • lowLevelReset(cacheMeta)
  • lowLevelSetOptions(cacheMeta, options) - you can update options anytime

These functions are also grouped together as limitedCacheUtil -- but minimization and tree-shaking will be slightly better if you import each individually.

FAQ

Immutable?

The cache itself is, but the low-level cacheMeta is persistent/mutated.

API for bulk operations?

Only reset and getAll. The other actions aren't as optimizable, so they're omitted to keep this small.

When are old items removed?

When new items are added, or if you try to get an item that has expired.

Is this a least-recently-used cache?

Not by default: For performance it only tracks by set time.

You can turn it into a least-recently-used cache by calling set each time you get an item, though: items will then expire based on when they were last accessed. This case has been optimized so performance won't suffer.