UNPKG

@net-vert/core

Version:

Dependency Inversion Network Library with Type-Safe Injection.

339 lines (338 loc) 7.72 kB
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 };