UNPKG

@trifrost/core

Version:

Blazingly fast, runtime-agnostic server framework for modern edge and node environments

91 lines (90 loc) 4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Sym_TriFrostSkipCache = exports.Sym_TriFrostCached = void 0; exports.cache = cache; exports.cacheSkip = cacheSkip; exports.cacheSkipped = cacheSkipped; exports.cacheFn = cacheFn; const string_1 = require("@valkyriestudios/utils/string"); exports.Sym_TriFrostCached = Symbol('trifrost.cache.cached'); exports.Sym_TriFrostSkipCache = Symbol('trifrost.cache.skip'); function cache(key, opts) { return function (method) { /* Prevent re-decoration */ if (Reflect.get(method, exports.Sym_TriFrostCached)) return method; const wrapped = async function (...args) { const ctx = Array.isArray(args) && args.length ? args[0] : undefined; /* Get trifrost cache either from passed ctx, this.cache or this.ctx.cache */ const trifrost_cache = ctx?.cache ?? this?.cache ?? this?.ctx?.cache; /* No viable cache found */ if (typeof trifrost_cache?.get !== 'function' || typeof trifrost_cache?.set !== 'function') return method.call(this, ...args); /* Determine cache key */ const ckey = typeof key === 'function' ? key(...args.slice(0, key.length)) : (0, string_1.isNeString)(key) ? key : null; if (!ckey) return method.call(this, ...args); /* Retrieve from cache, if exists -> return */ const cached = await trifrost_cache.get(ckey); if (cached !== null && cached !== undefined) return cached; /* Run method */ const result = await method.call(this, ...args); if (Object.prototype.toString.call(result) === '[object Object]' && Reflect.get(result, exports.Sym_TriFrostSkipCache)) return result.value; /* Cache */ await trifrost_cache.set(ckey, result, opts); return result; }; /* Set to prevent re-decoration */ Reflect.set(wrapped, exports.Sym_TriFrostCached, true); return wrapped; }; } /** * Marks a value as "do not cache", will still return the value directly from the method. */ function cacheSkip(value) { const v = { value }; Reflect.set(v, exports.Sym_TriFrostSkipCache, true); return v; } /** * Returns whether or not a value is a cache skip value */ function cacheSkipped(v) { return (Object.prototype.toString.call(v) === '[object Object]' && Reflect.get(v, exports.Sym_TriFrostSkipCache) === true); } function cacheFn(key, opts) { return function (fn) { /* Prevent re-decoration */ if (Reflect.get(fn, exports.Sym_TriFrostCached)) return fn; const wrapped = async function (...args) { const ctx = Array.isArray(args) && args.length ? args[0] : undefined; const trifrost_cache = ctx?.cache ?? this?.cache ?? this?.ctx?.cache; /* No viable cache found */ if (typeof trifrost_cache?.get !== 'function' || typeof trifrost_cache?.set !== 'function') return fn.apply(this, args); /* Determine cache key */ const ckey = typeof key === 'function' ? key(...args.slice(0, key.length)) : (0, string_1.isNeString)(key) ? key : null; if (!ckey) return fn.apply(this, args); /* Retrieve from cache, if exists -> return */ const cached = await trifrost_cache.get(ckey); if (cached !== null && cached !== undefined) return cached; /* Run method */ const result = await fn.apply(this, args); if (cacheSkipped(result)) return result.value; /* Cache */ await trifrost_cache.set(ckey, result, opts); return result; }; /* Set to prevent re-decoration */ Reflect.set(wrapped, exports.Sym_TriFrostCached, true); return wrapped; }; }