UNPKG

@socketsecurity/lib

Version:

Core utilities and infrastructure for Socket.dev security tools

229 lines (228 loc) 7 kB
"use strict"; /* Socket Lib - Built with esbuild */ var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var cache_with_ttl_exports = {}; __export(cache_with_ttl_exports, { createTtlCache: () => createTtlCache }); module.exports = __toCommonJS(cache_with_ttl_exports); var cacache = __toESM(require("./cacache")); const DEFAULT_TTL_MS = 5 * 60 * 1e3; const DEFAULT_PREFIX = "ttl-cache"; function createTtlCache(options) { const opts = { __proto__: null, memoize: true, prefix: DEFAULT_PREFIX, ttl: DEFAULT_TTL_MS, ...options }; if (opts.prefix?.includes("*")) { throw new TypeError( 'Cache prefix cannot contain wildcards (*). Use clear({ prefix: "pattern*" }) for wildcard matching.' ); } const memoCache = /* @__PURE__ */ new Map(); const ttl = opts.ttl ?? DEFAULT_TTL_MS; function buildKey(key) { return `${opts.prefix}:${key}`; } function isExpired(entry) { return Date.now() > entry.expiresAt; } function createMatcher(pattern) { const fullPattern = buildKey(pattern); const hasWildcard = pattern.includes("*"); if (!hasWildcard) { return (key) => key.startsWith(fullPattern); } const escaped = fullPattern.replaceAll(/[.+?^${}()|[\]\\]/g, "\\$&"); const regexPattern = escaped.replaceAll("*", ".*"); const regex = new RegExp(`^${regexPattern}`); return (key) => regex.test(key); } async function get(key) { if (key.includes("*")) { throw new TypeError( "Cache key cannot contain wildcards (*). Use getAll(pattern) to retrieve multiple entries." ); } const fullKey = buildKey(key); if (opts.memoize) { const memoEntry = memoCache.get(fullKey); if (memoEntry && !isExpired(memoEntry)) { return memoEntry.data; } if (memoEntry) { memoCache.delete(fullKey); } } const cacheEntry = await cacache.safeGet(fullKey); if (cacheEntry) { const entry = JSON.parse( cacheEntry.data.toString("utf8") ); if (!isExpired(entry)) { if (opts.memoize) { memoCache.set(fullKey, entry); } return entry.data; } await cacache.remove(fullKey); } return void 0; } async function getAll(pattern) { const results = /* @__PURE__ */ new Map(); const matches = createMatcher(pattern); if (opts.memoize) { for (const [key, entry] of memoCache.entries()) { if (!matches(key)) { continue; } if (isExpired(entry)) { memoCache.delete(key); continue; } const originalKey = key.slice((opts.prefix?.length ?? 0) + 1); results.set(originalKey, entry.data); } } const cacheDir = (await import("./paths")).getSocketCacacheDir(); const cacacheModule = await import("./cacache"); const stream = cacacheModule.getCacache().ls.stream(cacheDir); for await (const cacheEntry of stream) { if (!cacheEntry.key.startsWith(`${opts.prefix}:`)) { continue; } if (!matches(cacheEntry.key)) { continue; } const originalKey = cacheEntry.key.slice((opts.prefix?.length ?? 0) + 1); if (results.has(originalKey)) { continue; } try { const entry = await cacache.safeGet(cacheEntry.key); if (!entry) { continue; } const parsed = JSON.parse( entry.data.toString("utf8") ); if (isExpired(parsed)) { await cacache.remove(cacheEntry.key); continue; } results.set(originalKey, parsed.data); if (opts.memoize) { memoCache.set(cacheEntry.key, parsed); } } catch { } } return results; } async function set(key, data) { if (key.includes("*")) { throw new TypeError( 'Cache key cannot contain wildcards (*). Wildcards are only supported in clear({ prefix: "pattern*" }).' ); } const fullKey = buildKey(key); const entry = { data, expiresAt: Date.now() + ttl }; if (opts.memoize) { memoCache.set(fullKey, entry); } try { await cacache.put(fullKey, JSON.stringify(entry), { metadata: { expiresAt: entry.expiresAt } }); } catch { } } async function getOrFetch(key, fetcher) { const cached = await get(key); if (cached !== void 0) { return cached; } const data = await fetcher(); await set(key, data); return data; } async function deleteEntry(key) { if (key.includes("*")) { throw new TypeError( "Cache key cannot contain wildcards (*). Use deleteAll(pattern) to remove multiple entries." ); } const fullKey = buildKey(key); memoCache.delete(fullKey); await cacache.remove(fullKey); } async function deleteAll(pattern) { const fullPrefix = pattern ? `${opts.prefix}:${pattern}` : opts.prefix; if (!pattern) { memoCache.clear(); } else { const matches = createMatcher(pattern); for (const key of memoCache.keys()) { if (matches(key)) { memoCache.delete(key); } } } const removed = await cacache.clear({ prefix: fullPrefix }); return removed ?? 0; } async function clear(options2) { const opts2 = { __proto__: null, ...options2 }; memoCache.clear(); if (opts2.memoOnly) { return; } await deleteAll(); } return { clear, delete: deleteEntry, deleteAll, get, getAll, getOrFetch, set }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createTtlCache });