@trifrost/core
Version:
Blazingly fast, runtime-agnostic server framework for modern edge and node environments
91 lines (90 loc) • 2.94 kB
JavaScript
import { cacheSkip, cacheSkipped } from './util';
export class TriFrostCache {
#store;
constructor(opts) {
if (typeof opts?.store?.set === 'function' && typeof opts?.store?.get === 'function' && typeof opts?.store?.del === 'function') {
this.#store = opts.store;
}
else {
throw new Error('TriFrostCache: Expected a store');
}
}
get store() {
return this.#store;
}
/**
* Retrieves a cached value by key.
*
* @note If value doesn't exist will return null
* @param {string} key - Key of the value you wish to retrieve
*/
async get(key) {
const stored = (await this.#store.get(key));
return Object.prototype.toString.call(stored) === '[object Object]' && 'v' in stored ? stored.v : null;
}
/**
* Sets a value in cache
*
* @param {string} key - Key to set the value on in cache
* @param {TVal} value - Value to set
* @param {CacheOptions?} opts - Options for caching, eg: {ttl: 3600} means cache for 1 hour
*/
async set(key, value, opts) {
if (value === undefined)
throw new Error('TriFrostCache@set: Value can not be undefined');
await this.#store.set(key, { v: value }, opts);
}
/**
* Deletes a cached value by key or prefix
*
* @param {string|{prefix:string}} val - Value or group you wish to delete
*/
async del(val) {
await this.#store.del(val);
}
/**
* Wraps a get + set combined as a utility method.
*
* @param {string} key - Key the value is/will be cached on
* @param {Function} compute - Function to wrap which computes the value to cache
* @param {CacheOptions?} opts - Options for caching, eg: {ttl: 3600} means cache for 1 hour
*/
async wrap(key, compute, opts) {
/* Check if it exists in cache */
const existing = await this.get(key);
if (existing !== null)
return existing;
/* If not exists, compute the value and set */
const result = await compute();
if (result === undefined)
return result;
/* If cache was skipped from inside the method do not cache */
if (cacheSkipped(result))
return result.value;
await this.set(key, result, opts);
return result;
}
/**
* Instance alias for cacheSkip
*/
skip(value) {
return cacheSkip(value);
}
/**
* Stops the cache, for most storage adapters this is a no-op, but some storage adapters (eg: Memory) use
* this to kill internal timers and what not.
*/
async stop() {
await this.#store.stop();
}
/**
* Returns a context-scoped clone of this cache
*
* @note This is an internal method
*/
spawn(ctx) {
return new TriFrostCache({
store: this.#store.spawn(ctx),
});
}
}