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.
71 lines (70 loc) • 2.95 kB
JavaScript
/*! idmp v4.1.0 | (c) github/haozi | MIT */
//#region src/index.ts
var e = /* @__PURE__ */ function(e) {
return e[e.UNSENT = 0] = "UNSENT", e[e.OPENING = 1] = "OPENING", e[e.ABORTED = 2] = "ABORTED", e[e.REJECTED = 3] = "REJECTED", e[e.RESOLVED = 4] = "RESOLVED", e;
}(e || {}), t = /* @__PURE__ */ function(e) {
return e[e.retryCount = 0] = "retryCount", e[e.status = 1] = "status", e[e.pendingList = 2] = "pendingList", e[e.resolvedData = 3] = "resolvedData", e[e.rejectionError = 4] = "rejectionError", e[e.cachedPromiseFunc = 5] = "cachedPromiseFunc", e[e.timerId = 6] = "timerId", e[e._originalErrorStack = 7] = "_originalErrorStack", e;
}(t || {}), n = 3e3, r = 6048e5, i = () => {}, a = void 0, o = setTimeout, s = clearTimeout, c = (e, t) => e > t ? e : t, l = (e, t) => e < t ? e : t, u = (e) => e < 0 ? 0 : e > r ? r : e, d = {}, f = (e) => {
let { maxRetry: t = 30, maxAge: r = n, minRetryDelay: a = 50, maxRetryDelay: o = 5e3, onBeforeRetry: s = i, signal: c } = e || {};
return {
maxRetry: t,
maxAge: u(r),
minRetryDelay: a,
maxRetryDelay: o,
onBeforeRetry: s,
f: r === Infinity,
signal: c
};
}, p = (e) => {
if (!e) return;
let n = d[e];
n && (n[t.timerId] && s(n[t.timerId]), d[e] = a);
}, m = () => {
for (let e of Object.keys(d)) p(e);
d = {};
}, h = (n, r, i) => {
if (!n) return r();
let { maxRetry: s, minRetryDelay: u, maxRetryDelay: m, maxAge: h, onBeforeRetry: g, f: _, signal: v } = f(i);
d[n] = d[n] || [
0,
e.UNSENT,
[]
];
let y = d[n], b = () => {
y[t.status] = e.UNSENT, y[t.resolvedData] = y[t.rejectionError] = a;
}, x = () => {
let e = y[t.pendingList].length;
for (let n = 0; n < e; ++n) y[t.pendingList][n][0](y[t.resolvedData]);
y[t.pendingList] = [], _ || (y[t.timerId] = o(() => {
p(n);
}, h));
}, S = () => {
let e = y[t.pendingList].length, r;
r = e - s, (r < 0 || !isFinite(e)) && (r = c(1, y[t.pendingList].length - 3));
for (let e = 0; e < r; ++e) y[t.pendingList][e][1](y[t.rejectionError]);
p(n);
}, C = () => new Promise((i, a) => {
if (!y[t.cachedPromiseFunc] && (y[t.cachedPromiseFunc] = r), y[t.status] === e.RESOLVED) {
i(y[t.resolvedData]);
return;
}
if (v) {
if (v.aborted) return;
v.addEventListener("abort", () => {
b(), y[t.rejectionError] = new DOMException(v.reason, "AbortError"), S();
});
}
y[t.status] === e.UNSENT ? (y[t.status] = e.OPENING, y[t.pendingList].push([i, a]), y[t.cachedPromiseFunc]().then((n) => {
y[t.resolvedData] = n, x(), y[t.status] = e.RESOLVED;
}).catch((r) => {
y[t.status] = e.REJECTED, y[t.rejectionError] = r, ++y[t.retryCount], y[t.retryCount] > s ? S() : (g(r, {
globalKey: n,
retryCount: y[t.retryCount]
}), b(), o(C, l(m, u * Math.pow(2, y[t.retryCount] - 1))));
})) : y[t.status] === e.OPENING && y[t.pendingList].push([i, a]);
});
return C();
};
h.flush = p, h.flushAll = m, h._s = a;
//#endregion
export { h as default, h as idmp, f as getOptions };