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
JavaScript
/*! 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;