@socketsecurity/lib
Version:
Core utilities and infrastructure for Socket.dev security tools
213 lines (212 loc) • 6.33 kB
JavaScript
;
/* Socket Lib - Built with esbuild */
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var memoization_exports = {};
__export(memoization_exports, {
Memoize: () => Memoize,
clearAllMemoizationCaches: () => clearAllMemoizationCaches,
memoize: () => memoize,
memoizeAsync: () => memoizeAsync,
memoizeDebounced: () => memoizeDebounced,
memoizeWeak: () => memoizeWeak,
once: () => once
});
module.exports = __toCommonJS(memoization_exports);
var import_debug = require("./debug");
function memoize(fn, options = {}) {
const {
keyGen = (...args) => JSON.stringify(args),
maxSize = Number.POSITIVE_INFINITY,
name = fn.name || "anonymous",
ttl = Number.POSITIVE_INFINITY
} = options;
const cache = /* @__PURE__ */ new Map();
const accessOrder = [];
function evictLRU() {
if (cache.size >= maxSize && accessOrder.length > 0) {
const oldest = accessOrder.shift();
if (oldest) {
cache.delete(oldest);
(0, import_debug.debugLog)(`[memoize:${name}] clear`, {
key: oldest,
reason: "LRU"
});
}
}
}
function isExpired(entry) {
if (ttl === Number.POSITIVE_INFINITY) {
return false;
}
return Date.now() - entry.timestamp > ttl;
}
return function memoized(...args) {
const key = keyGen(...args);
const cached = cache.get(key);
if (cached && !isExpired(cached)) {
cached.hits++;
const index = accessOrder.indexOf(key);
if (index !== -1) {
accessOrder.splice(index, 1);
}
accessOrder.push(key);
(0, import_debug.debugLog)(`[memoize:${name}] hit`, { key, hits: cached.hits });
return cached.value;
}
(0, import_debug.debugLog)(`[memoize:${name}] miss`, { key });
const value = fn(...args);
evictLRU();
cache.set(key, {
value,
timestamp: Date.now(),
hits: 0
});
accessOrder.push(key);
(0, import_debug.debugLog)(`[memoize:${name}] set`, { key, cacheSize: cache.size });
return value;
};
}
function memoizeAsync(fn, options = {}) {
const {
keyGen = (...args) => JSON.stringify(args),
maxSize = Number.POSITIVE_INFINITY,
name = fn.name || "anonymous",
ttl = Number.POSITIVE_INFINITY
} = options;
const cache = /* @__PURE__ */ new Map();
const accessOrder = [];
function evictLRU() {
if (cache.size >= maxSize && accessOrder.length > 0) {
const oldest = accessOrder.shift();
if (oldest) {
cache.delete(oldest);
(0, import_debug.debugLog)(`[memoizeAsync:${name}] clear`, {
key: oldest,
reason: "LRU"
});
}
}
}
function isExpired(entry) {
if (ttl === Number.POSITIVE_INFINITY) {
return false;
}
return Date.now() - entry.timestamp > ttl;
}
return async function memoized(...args) {
const key = keyGen(...args);
const cached = cache.get(key);
if (cached && !isExpired(cached)) {
cached.hits++;
const index = accessOrder.indexOf(key);
if (index !== -1) {
accessOrder.splice(index, 1);
}
accessOrder.push(key);
(0, import_debug.debugLog)(`[memoizeAsync:${name}] hit`, { key, hits: cached.hits });
return await cached.value;
}
(0, import_debug.debugLog)(`[memoizeAsync:${name}] miss`, { key });
const promise = fn(...args);
evictLRU();
cache.set(key, {
value: promise,
timestamp: Date.now(),
hits: 0
});
accessOrder.push(key);
(0, import_debug.debugLog)(`[memoizeAsync:${name}] set`, { key, cacheSize: cache.size });
try {
const result = await promise;
return result;
} catch (e) {
cache.delete(key);
const orderIndex = accessOrder.indexOf(key);
if (orderIndex !== -1) {
accessOrder.splice(orderIndex, 1);
}
(0, import_debug.debugLog)(`[memoizeAsync:${name}] clear`, { key, reason: "error" });
throw e;
}
};
}
function Memoize(options = {}) {
return (_target, propertyKey, descriptor) => {
const originalMethod = descriptor.value;
descriptor.value = memoize(originalMethod, {
...options,
name: options.name || propertyKey
});
return descriptor;
};
}
function clearAllMemoizationCaches() {
(0, import_debug.debugLog)("[memoize:all] clear", { action: "clear-all-caches" });
}
function memoizeWeak(fn) {
const cache = /* @__PURE__ */ new WeakMap();
return function memoized(key) {
const cached = cache.get(key);
if (cached !== void 0) {
(0, import_debug.debugLog)(`[memoizeWeak:${fn.name}] hit`);
return cached;
}
(0, import_debug.debugLog)(`[memoizeWeak:${fn.name}] miss`);
const result = fn(key);
cache.set(key, result);
return result;
};
}
function once(fn) {
let called = false;
let result;
return function memoized() {
if (!called) {
result = fn();
called = true;
(0, import_debug.debugLog)(`[once:${fn.name}] set`);
} else {
(0, import_debug.debugLog)(`[once:${fn.name}] hit`);
}
return result;
};
}
function memoizeDebounced(fn, wait, options = {}) {
const memoized = memoize(fn, options);
let timeoutId;
return function debounced(...args) {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
memoized(...args);
}, wait);
return memoized(...args);
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Memoize,
clearAllMemoizationCaches,
memoize,
memoizeAsync,
memoizeDebounced,
memoizeWeak,
once
});