@beignet/core
Version:
Core framework primitives for Beignet
82 lines • 2.59 kB
JavaScript
/**
* Resolve and validate the optional TTL shared by cache adapters.
*
* @param options - Cache write options.
* @returns The positive TTL, or `undefined` for a persistent value.
*/
export function resolveCacheTtlSeconds(options) {
const ttlSeconds = options?.ttlSeconds;
if (ttlSeconds === undefined) {
return undefined;
}
if (!Number.isSafeInteger(ttlSeconds) || ttlSeconds <= 0) {
throw new RangeError("Cache ttlSeconds must be a positive safe integer when provided.");
}
return ttlSeconds;
}
function resolveExpiresAt(options) {
const ttlSeconds = resolveCacheTtlSeconds(options);
if (ttlSeconds === undefined) {
return null;
}
return Math.min(Number.MAX_SAFE_INTEGER, Date.now() + ttlSeconds * 1000);
}
function isExpired(entry) {
return entry.expiresAt != null && entry.expiresAt <= Date.now();
}
/**
* Create an in-memory cache for tests, examples, and single-process
* development.
*
* This adapter is not durable or distributed. Values are lost when the process
* exits and are not shared across workers, regions, or serverless invocations.
*
* @param initialValues - Optional initial string values without TTL.
* @returns A cache port backed by a local `Map`.
*/
export function createMemoryCache(initialValues = {}) {
const values = new Map(Object.entries(initialValues).map(([key, value]) => [
key,
{ value, expiresAt: null },
]));
async function getFreshEntry(key) {
const entry = values.get(key);
if (!entry) {
return null;
}
if (isExpired(entry)) {
values.delete(key);
return null;
}
return entry;
}
const cache = {
async get(key) {
return (await getFreshEntry(key))?.value ?? null;
},
async set(key, value, options) {
values.set(key, {
value,
expiresAt: resolveExpiresAt(options),
});
},
async delete(key) {
return values.delete(key);
},
async has(key) {
return (await getFreshEntry(key)) != null;
},
async remember(key, factory, options) {
resolveCacheTtlSeconds(options);
const cached = await cache.get(key);
if (cached != null) {
return cached;
}
const value = await factory();
await cache.set(key, value, options);
return value;
},
};
return cache;
}
//# sourceMappingURL=cache.js.map