Skip to content

wrap virtually everything that can store by key to act as cache with ttl/max-age, stale-while-validate, parallel fetch protection and type-safety support

License

Notifications You must be signed in to change notification settings

davidhoga/cachified

 
 

Repository files navigation

cachified

🚀 Publish codecov semantic-release: angular Love and Peace no dependencies npm

🧙 One API to cache them all

wrap virtually everything that can store by key to act as cache with ttl/max-age, stale-while-validate, parallel fetch protection and type-safety support

🤔 Idea and 💻 initial implementation by @kentcdodds 👏💜

Install

npm install cachified
# yarn add cachified

Usage

import type { CacheEntry } from 'cachified';
import LRUCache from 'lru-cache';
import { cachified } from 'cachified';

// lru cache is not part of this package but a simple non-persistent cache
const lru = new LRUCache<string, CacheEntry<string>>({ max: 1000 });

const value = await cachified({
  cache: lru,
  key: 'cache-key-for-this-value',
  async getFreshValue() {
    return /* call to really complex stuff here */ 'pi';
  },
  /* Other options */
});

Options

export interface CachifiedOptions<Value> {
  /**
   * The key this value is cached by
   * @type {string}
   */
  key: string;
  /**
   * Cache implementation to use
   *
   * Must conform with signature
   *  - set(key: string, value: object): void
   *  - get(key: string): object
   *  - delete(key: string): void
   *
   * @type {Cache}
   */
  cache: Cache<Value>;
  /**
   * This is called when no valid value is in cache for given key.
   * Basically what we would do if we wouldn't use a cache.
   *
   * Can be async and must return fresh value or throw.
   *
   * @type {function(): Promise | Value}
   */
  getFreshValue: GetFreshValue<Value>;
  /**
   * Time To Live; often also referred to as max age.
   *
   * Amount of milliseconds the value should stay in cache
   * before we get a fresh one
   *
   * @type {number} Must be positive, can be infinite
   * @defaultValue {Infinity}
   */
  ttl?: number;
  /**
   * Amount of milliseconds that a value with exceeded ttl is still returned
   * while a fresh value is refreshed in the background
   *
   * @type {number} Must be positive, can be infinite
   * @defaultValue {0}
   */
  staleWhileRevalidate?: number;
  /**
   * Called for each fresh or cached value to check if it matches the
   * typescript type.
   *
   * Must return true when value is valid.
   *
   * May return false or the reason (string) why the value is invalid
   *
   * @type {function(): boolean | string}
   * @defaultValue {() => true} each value is considered valid by default
   */
  checkValue?: (value: unknown) => boolean | string;
  /**
   * Set true to not even try reading the currently cached value
   *
   * Will write new value to cache even when cached value is
   * still valid.
   *
   * @type {boolean}
   * @defaultValue {false}
   */
  forceFresh?: boolean;
  /**
   * Weather of not to fall back to cache when getting a forced fresh value
   * fails.
   *
   * Can also be the maximum age in milliseconds that a fallback value might
   * have
   *
   * @type {boolean | number} Number must be positive, can be infinite
   * @defaultValue {Infinity}
   */
  fallbackToCache?: boolean | number;
  /**
   * Amount of time in milliseconds before revalidation of a stale
   * cache entry is started
   *
   * @type {number} must be positive and finite
   * @defaultValue {0}
   */
  staleRefreshTimeout?: number;
  /**
   * A reporter receives events during the runtime of
   * cachified and can be used for debugging and monitoring
   *
   * @type {(context) => (event) => void}
   * @defaultValue {noop}
   */
  reporter?: CreateReporter<Value>;
}

About

wrap virtually everything that can store by key to act as cache with ttl/max-age, stale-while-validate, parallel fetch protection and type-safety support

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 99.6%
  • JavaScript 0.4%