UNPKG

idmp

Version:

A lightweight TypeScript library for deduplicating and caching async function calls with automatic retries, designed for idempotent network requests in React and Node.js.

88 lines (87 loc) 2.88 kB
/*! idmp v4.1.0 | (c) github/haozi | MIT */ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); let crypto = require("crypto"); let idmp = require("idmp"); let json_web3 = require("json-web3"); let redis = require("redis"); //#region src/index.ts var __filename$1 = (0, require("url").fileURLToPath)({}.url); var md5 = (data) => (0, crypto.createHash)("md5").update(data).digest("hex"); var cachePrefix = `/idmp/v4/${md5(__filename$1)}`; var udf = void 0; var encode = encodeURIComponent; var getCachePath = (globalKey) => `${cachePrefix}/${encode(globalKey)}`; var redisIdmpWrap = (_idmp, namespace, options) => { const client = (0, redis.createClient)({ url: options.url }); client.once("error", (err) => { console.error("Redis Client Error", err); process.exit(err.code === "ECONNREFUSED" ? 1 : 0); }); const setData = async (key, data, maxAge) => { if (!key) return; if (!client.isOpen) await client.connect(); const cachePath = getCachePath(key); await client.set(cachePath, (0, json_web3.stringify_UNSAFE)(data), { expiration: { type: "EX", value: Math.floor(maxAge / 1e3) } }); }; const getData = async (key) => { if (!key) return udf; if (!client.isOpen) await client.connect(); const cachePath = getCachePath(key); let redisLocalData; try { const rawData = await client.get(cachePath); if (!rawData) return udf; redisLocalData = (0, json_web3.parse_UNSAFE)(rawData); } catch {} if (redisLocalData === udf) return udf; return redisLocalData; }; const deleteKeysByPrefix = async (prefix) => { const client = (0, redis.createClient)({ url: options.url }); await client.connect(); let cursor = "0"; const pattern = `${prefix}*`; do { const { cursor: nextCursor, keys } = await client.scan(cursor, { MATCH: pattern, COUNT: 100 }); cursor = nextCursor; if (keys.length > 0) await client.del(keys); } while (cursor !== "0"); await client.quit(); }; const newIdmp = (globalKey, promiseFunc, options) => { globalKey = `${namespace}_${globalKey}`; const finalOptions = (0, idmp.getOptions)(options); return _idmp(globalKey, async () => { const localData = await getData(globalKey); if (localData !== udf) return localData; const memoryData = await promiseFunc(); if (memoryData !== udf) setData(globalKey, memoryData, finalOptions.maxAge); return memoryData; }, { maxAge: 0 }); }; newIdmp.flush = async (globalKey) => { _idmp.flush(globalKey); await client?.del(getCachePath(globalKey)); }; newIdmp.flushAll = async () => { _idmp.flushAll(); await deleteKeysByPrefix(cachePrefix); }; newIdmp.quit = async () => { if (client.isOpen) await client.quit(); }; return newIdmp; }; //#endregion exports.cachePrefix = cachePrefix; exports.default = redisIdmpWrap; exports.getCachePath = getCachePath;