@net-vert/core
Version:
Dependency Inversion Network Library with Type-Safe Injection.
339 lines (338 loc) • 7.72 kB
JavaScript
import E from "localforage";
import { TaskQueue as j } from "id-queue";
const k = {
get: (t, e) => ({
url: t,
method: "get",
...e,
params: e == null ? void 0 : e.params
}),
post: (t, e, r) => ({
url: t,
method: "post",
data: e,
headers: { "Content-Type": "application/json", ...r == null ? void 0 : r.headers },
...r
}),
delete: (t, e) => ({
url: t,
method: "delete",
...e
}),
put: (t, e, r) => ({
url: t,
method: "put",
data: e,
headers: { "Content-Type": "application/json", ...r == null ? void 0 : r.headers },
...r
}),
request: (t) => t
};
function T(t) {
const e = {};
return Object.keys(k).forEach(
(r) => {
e[r] = (...o) => {
const n = k[r](...o);
return t(n);
};
}
), e;
}
const M = "default", z = () => `${Date.now()}_${Math.random().toString().slice(2, 8)}`, I = /* @__PURE__ */ new Map(), Z = (t, e = M) => {
I.set(e, T(t));
}, v = (t = M) => {
const e = I.get(t);
if (!e) throw new Error(`Requestor实例 ${t} 未注册`);
return e;
};
class O {
has(e) {
return !!this.get(e);
}
// 获取缓存
get(e) {
const r = localStorage.getItem(e);
if (r)
try {
return JSON.parse(r);
} catch (o) {
console.error("Error parsing cached data", o);
return;
}
}
// 设置缓存
set(e, r) {
try {
const o = JSON.stringify(r);
localStorage.setItem(e, o);
} catch (o) {
console.error("Error saving data to localStorage", o);
}
return r;
}
// 删除缓存
remove(e) {
localStorage.removeItem(e);
}
// 清空所有缓存
clear() {
localStorage.clear();
}
}
const H = new O(), U = ({ persist: t, name: e, sync: r }) => {
if (t && r)
return H;
if (t) {
const o = E.createInstance({
name: e
// driver: sync
// ?undefined
// :localforage.LOCALSTORAGE,
});
return {
has: (n) => o.keys().then((s) => s.includes(n)),
get: (n) => o.getItem(n),
set: (n, s) => o.setItem(n, s),
remove: (n) => o.removeItem(n),
clear: () => o.clear()
};
} else {
const o = /* @__PURE__ */ new Map();
return {
has: (n) => o.has(n),
get: (n) => o.get(n),
set: (n, s) => o.set(n, s),
remove: (n) => o.delete(n),
clear: () => o.clear()
};
}
}, _ = () => {
const t = /* @__PURE__ */ new Map();
return {
getPromise: (s) => t.get(s),
setPromise: (s, u) => {
t.set(s, u);
},
delPromise: (s) => {
t.delete(s);
},
clearCache: () => {
t.clear();
}
};
}, A = (t, e) => ({
value: t,
expiresAt: Date.now() + e
}), x = (t) => t.expiresAt > Date.now(), J = {
key: (t) => t.url,
persist: !1,
duration: 1 / 0,
sync: !1
}, S = (t) => {
const e = { ...J, ...t }, { name: r, persist: o, sync: n } = e, s = U({ persist: o, name: r, sync: n }), { getPromise: u, setPromise: P, delPromise: g } = _();
function l(a, h) {
const { isValid: i } = e, f = s.get(a);
let C = !1;
if (f && x(f)) {
try {
C = (i == null ? void 0 : i({
key: a,
config: h,
cachedData: f
})) ?? !0;
} catch (c) {
console.error(`校验异常 ${a}`, c);
}
!C && s.remove(a);
}
return { shouldUseCache: C, cachedData: f };
}
async function d(a, h) {
const { isValid: i } = e, f = await s.get(a);
let C = !1;
if (f && x(f)) {
try {
C = await (i == null ? void 0 : i({
key: a,
config: h,
cachedData: f
})) ?? !0;
} catch (c) {
console.error(`校验异常 ${a}`, c);
}
!C && s.remove(a);
}
return { shouldUseCache: C, cachedData: f };
}
const p = {
get(a, h) {
function i(c, y, ...m) {
const q = Reflect.apply(a[h], a, m).then(async (w) => {
const R = typeof e.duration == "number" ? e.duration : e.duration({
key: c,
config: y,
response: w
});
return s.set(c, A(w, R)), w;
}).finally(() => {
g(c);
});
return P(c, q), q;
}
return n ? (...c) => {
const y = k[h](...c), m = e.key(y), q = u(m);
if (q)
return q;
const { shouldUseCache: w, cachedData: R } = l(m, y);
return w ? R.value : i(m, y, ...c);
} : (...c) => {
const y = k[h](...c), m = e.key(y), q = u(m);
if (q)
return q;
const w = (async () => {
try {
const { shouldUseCache: R, cachedData: D } = await d(m, y);
return R ? D.value : await i(m, y, ...c);
} finally {
g(m);
}
})();
return P(m, w), w;
};
}
};
return {
requestor: new Proxy(v(), p),
store: s
};
}, N = (t) => {
const { method: e, url: r, params: o, data: n } = t;
return [e, r, JSON.stringify(o), JSON.stringify(n)].join("|");
}, b = {
key: N,
duration: 1e3
}, F = (t) => {
const e = { ...b, ...t }, {
requestor: r,
store: o
} = S({
...e,
persist: !1
});
return {
requestor: r,
store: o
};
}, L = {
retries: 3,
delay: 0,
retryCondition: () => !0
}, $ = (t) => {
const { retries: e, delay: r, retryCondition: o } = { ...L, ...t }, n = {
get(s, u) {
return (...g) => {
let l = 0;
const d = () => Reflect.apply(s[u], s, g).catch((p) => {
if (l < e && o(p)) {
l++;
const a = typeof r == "function" ? r(l) : r;
return new Promise((h) => {
setTimeout(() => h(d()), a);
});
}
return Promise.reject(p);
});
return d();
};
}
};
return {
requestor: new Proxy(v(), n)
};
};
class Q {
constructor(e = 4) {
this.parallelCount = e, this.tasks = new j(), this.runningCount = 0;
}
// 加入
add(e, r) {
return new Promise((o, n) => {
this.tasks.enqueue(e, {
task: r,
resolve: o,
reject: n
}), this._run();
});
}
// 删除
remove(e) {
this.tasks.remove(e);
}
execute(e) {
const { task: r, resolve: o, reject: n } = e;
return r().then(o).catch(n).finally(() => {
this.runningCount--, this._run();
});
}
_run() {
for (; this.runningCount < this.parallelCount && this.tasks.size > 0; ) {
const e = this.tasks.dequeue();
this.runningCount++, this.execute(e);
}
}
}
const W = {
parallelCount: 4,
retries: 0,
createId: () => z()
}, Y = (t) => {
const e = { ...W, ...t }, { parallelCount: r, createId: o, ...n } = e, s = new Q(r), { requestor: u = null } = n.retries > 0 ? $(n) : {}, P = {
get(g, l) {
return (...p) => {
const a = k[l](...p), h = o(a), i = () => u ? Reflect.apply(u[l], u, p) : Reflect.apply(g[l], g, p);
return s.add(h, i);
};
}
};
return {
requestor: new Proxy(v(), P),
concurrentPool: s
};
}, B = {
persist: !1,
sync: !0
}, G = (t) => {
const e = { ...B, ...t }, { ...r } = e, {
requestor: o,
store: n
} = S(r), s = {
get(u, P) {
return (...l) => {
try {
const d = Reflect.apply(u[P], u, l);
if (d instanceof Promise)
throw d;
return d;
} catch (d) {
throw d;
}
};
}
};
return {
requestor: new Proxy(o, s),
store: n
};
}, K = {
cacheRequestor: S,
idempotencyRequestor: F,
retryRequestor: $,
concurrentPoolRequestor: Y,
syncRequestor: G
};
export {
Z as inject,
K as requestExtender,
v as useRequestor
};