@vielzeug/fetchit 1.0.3 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/fetchit.js CHANGED
@@ -1,186 +1,366 @@
1
- import { Logit as p } from "./logit/dist/logit.js";
2
- class y extends Error {
1
+ import "./toolkit/dist/logit/dist/logit.js";
2
+ import { retry as q } from "./toolkit/dist/async/retry.js";
3
+ const M = 0, Q = 5 * 6e4, W = 3e4, K = 3, x = !0, z = "application/json", G = "content-type";
4
+ class _ extends Error {
3
5
  url;
4
6
  method;
5
7
  status;
6
- originalError;
7
- constructor(e, r, n, o, a) {
8
- super(e), this.name = "HttpError", this.url = r, this.method = n, this.status = o, this.originalError = a;
8
+ original;
9
+ constructor(c, p, a, h, i) {
10
+ super(c), this.name = "HttpError", this.url = p, this.method = a, this.status = h, this.original = i;
9
11
  }
10
12
  }
11
- const C = 5e3, R = 12e4, j = {
12
- ABORTED: 499,
13
- BAD_REQUEST: 400,
14
- CONFLICT: 409,
15
- FORBIDDEN: 403,
16
- NOT_ALLOWED: 405,
17
- NOT_FOUND: 404,
18
- PRE_CONDITION: 412,
19
- TIMEOUT: 408,
20
- UNAUTHORIZED: 401
21
- }, u = {
22
- ERROR: "ERROR",
23
- PENDING: "PENDING",
24
- SUCCESS: "SUCCESS"
25
- }, i = /* @__PURE__ */ new Map();
26
- function T(t, e) {
27
- if (e.id) return e.id;
28
- const { method: r = "GET", body: n, headers: o } = e;
29
- return JSON.stringify({ body: n, headers: o, method: r, url: t });
13
+ function k(t) {
14
+ return t instanceof Error ? t : new Error(String(t));
30
15
  }
31
- function f(t, e, r, n, o) {
32
- const a = Date.now() - o, s = t.toLowerCase(), c = r.method?.toUpperCase() ?? "GET", l = O(e), h = t === "SUCCESS" ? "✓" : "✕";
33
- p[s](`HTTP::${c}(…/${l}) ${h} ${a}ms`, {
34
- req: r,
35
- res: n,
36
- url: e
37
- });
16
+ function X(t, c, p) {
17
+ const a = (t || "").replace(/\/+$/, ""), h = c.replace(/^\/+/, ""), i = a ? `${a}/${h}` : h;
18
+ if (!p) return i;
19
+ const y = Object.entries(p).filter(([, g]) => g !== void 0).map(([g, S]) => `${encodeURIComponent(g)}=${encodeURIComponent(String(S))}`).join("&");
20
+ return y ? `${i}${i.includes("?") ? "&" : "?"}${y}` : i;
38
21
  }
39
- function O(t) {
40
- return t.replace(/^https?:\/\/[^/]+\//, "");
22
+ function Z(t) {
23
+ return typeof FormData < "u" && t instanceof FormData || typeof Blob < "u" && t instanceof Blob || typeof URLSearchParams < "u" && t instanceof URLSearchParams || typeof t == "string" || t instanceof ArrayBuffer || t && typeof t == "object" && Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? !0 : !!ArrayBuffer.isView?.(t);
41
24
  }
42
- async function E(t, e, { id: r, retries: n = 2 }) {
43
- const o = Date.now(), a = e.method?.toUpperCase() ?? "GET";
25
+ function j(t) {
26
+ return t === null ? "null" : t === void 0 ? "undefined" : typeof t != "object" ? JSON.stringify(t) : Array.isArray(t) ? `[${t.map((a) => j(a)).join(",")}]` : `{${Object.keys(t).sort().map((a) => `${JSON.stringify(a)}:${j(t[a])}`).join(",")}}`;
27
+ }
28
+ function tt(t) {
29
+ if (t == null)
30
+ return "null";
31
+ if (typeof FormData < "u" && t instanceof FormData)
32
+ return "[FormData]";
33
+ if (typeof Blob < "u" && t instanceof Blob)
34
+ return `[Blob:${t.size}:${t.type}]`;
35
+ if (typeof URLSearchParams < "u" && t instanceof URLSearchParams)
36
+ return `[URLSearchParams:${t.toString()}]`;
37
+ if (t instanceof ArrayBuffer)
38
+ return `[ArrayBuffer:${t.byteLength}]`;
39
+ if (ArrayBuffer.isView?.(t))
40
+ return `[ArrayBufferView:${t.byteLength}]`;
41
+ if (typeof t == "string")
42
+ return t;
43
+ if (typeof t == "object")
44
+ try {
45
+ return j(t);
46
+ } catch {
47
+ return "[Object]";
48
+ }
44
49
  try {
45
- const s = await fetch(t, e), c = await S(s);
46
- return f("SUCCESS", t, e, c, o), d(r, u.SUCCESS), { data: c, ok: s.ok, status: s.status };
47
- } catch (s) {
48
- if (f("ERROR", t, e, s, o), d(r, u.ERROR), n > 0 && s instanceof TypeError)
49
- return E(t, e, { id: r, retries: n - 1 });
50
- throw new y(s instanceof Error ? s.message : "Request failed", t, a, void 0, s);
51
- } finally {
52
- r && e.method !== "GET" && i.delete(r);
50
+ return JSON.stringify(t);
51
+ } catch {
52
+ return "[Unknown]";
53
53
  }
54
54
  }
55
- async function S(t) {
56
- if (t.status === 204 || t.headers.get("content-length") === "0")
57
- return;
58
- const e = t.headers.get("content-type") ?? "";
59
- return e.includes("application/json") ? t.json() : e.includes("text") ? t.text() : t.blob();
60
- }
61
- function d(t, e) {
62
- const r = t ? i.get(t) : void 0;
63
- r && (r.status = e);
64
- }
65
- async function b(t, e, r) {
66
- const n = T(t, e);
67
- let o = i.get(n);
68
- if (o && m(e, o) && (o.controller.abort("Request aborted"), i.delete(n), o = void 0), o && U(o))
69
- return o.request;
70
- const a = new AbortController(), s = D(t, r), c = N(e, r, a), l = E(s, c, { id: n });
71
- return i.set(n, {
72
- controller: a,
73
- expiresIn: Date.now() + (r?.expiresIn ?? R),
74
- request: l,
75
- status: u.PENDING
76
- }), l;
77
- }
78
- function m(t, e) {
79
- return t.invalidate ? !0 : e ? t.cancelable && e.status === u.PENDING || e.status === u.ERROR : !1;
80
- }
81
- function U(t) {
82
- return Date.now() <= t.expiresIn;
83
- }
84
- function D(t, e) {
85
- if (!e?.url) return t;
86
- const r = e.url.replace(/\/+$/, ""), n = t.replace(/^\/+/, "");
87
- return `${r}/${n}`;
88
- }
89
- function I(t) {
90
- return t instanceof FormData || t instanceof Blob || t instanceof ArrayBuffer || t instanceof URLSearchParams || typeof t == "string";
91
- }
92
- function N(t, e, r) {
93
- const n = e?.timeout ?? C, o = AbortSignal.any([r.signal, AbortSignal.timeout(n)]);
94
- let a;
95
- const s = {};
96
- return t.body !== void 0 && (I(t.body) ? a = t.body : (a = JSON.stringify(t.body), s["Content-Type"] = "application/json")), {
97
- ...t,
98
- body: a,
99
- headers: w(e?.headers, t.headers, s),
100
- signal: o
55
+ function et(t, c) {
56
+ if (t === 0 || t === Number.POSITIVE_INFINITY) {
57
+ if (c)
58
+ return {
59
+ clear: () => {
60
+ },
61
+ signal: c
62
+ };
63
+ const i = new AbortController();
64
+ return {
65
+ clear: () => {
66
+ },
67
+ signal: i.signal
68
+ };
69
+ }
70
+ if (typeof AbortSignal < "u" && "timeout" in AbortSignal && !c) {
71
+ const i = AbortSignal.timeout(t);
72
+ return {
73
+ clear: () => {
74
+ },
75
+ // No cleanup needed for native timeout
76
+ signal: i
77
+ };
78
+ }
79
+ const p = new AbortController(), a = () => p.abort();
80
+ c && (c.aborted ? p.abort() : c.addEventListener("abort", a, { once: !0 }));
81
+ const h = setTimeout(() => p.abort(), t);
82
+ return {
83
+ clear: () => {
84
+ clearTimeout(h), c && c.removeEventListener("abort", a);
85
+ },
86
+ signal: p.signal
101
87
  };
102
88
  }
103
- function g(t) {
104
- const e = {};
105
- if (t instanceof Headers)
106
- t.forEach((r, n) => {
107
- e[n] = r;
108
- });
109
- else if (Array.isArray(t))
110
- for (const [r, n] of t)
111
- e[r] = n;
112
- else
113
- for (const [r, n] of Object.entries(t))
114
- e[r] = n;
115
- return e;
116
- }
117
- function w(t, e, r) {
118
- const n = {};
119
- if (t)
120
- for (const [o, a] of Object.entries(t))
121
- a !== void 0 && (n[o] = a);
122
- return e && Object.assign(n, g(e)), r && Object.assign(n, r), n;
123
- }
124
- function P(t, e) {
125
- if (!e || Object.keys(e).length === 0)
126
- return t;
127
- const r = new URL(t);
128
- for (const [n, o] of Object.entries(e))
129
- o !== void 0 && r.searchParams.append(n, String(o));
130
- return r.toString();
89
+ async function rt(t) {
90
+ if (t.status === 204)
91
+ return;
92
+ const c = t.headers.get(G) ?? "";
93
+ if (c.includes(z))
94
+ return await t.json();
95
+ if (c.startsWith("text/"))
96
+ return await t.text();
97
+ try {
98
+ return await t.blob();
99
+ } catch {
100
+ return await t.text();
101
+ }
131
102
  }
132
- function v(t = { url: "" }) {
133
- const e = (r) => (n, o = {}) => b(n, { ...o, method: r }, t);
103
+ function st(t = {}) {
104
+ const {
105
+ baseUrl: c = "",
106
+ headers: p = {},
107
+ timeout: a = W,
108
+ dedupe: h = x,
109
+ logger: i
110
+ } = t;
111
+ let y = { ...p };
112
+ const g = /* @__PURE__ */ new Map();
113
+ function S(f, d, C) {
114
+ i && i(f, d, C);
115
+ }
116
+ async function A(f, d, C = {}) {
117
+ const T = X(c, d, C.params), E = (f || "GET").toUpperCase(), { body: w, headers: F, dedupe: R, signal: B, ...N } = C, $ = R !== !1 && h, e = $ ? JSON.stringify({
118
+ body: tt(w),
119
+ full: T,
120
+ m: E
121
+ }) : "";
122
+ if ($ && g.has(e))
123
+ return g.get(e);
124
+ const { signal: n, clear: r } = et(a, B ?? null), s = {
125
+ method: E,
126
+ ...N,
127
+ headers: { ...y, ...F },
128
+ signal: n
129
+ };
130
+ w !== void 0 && !Z(w) ? (s.body = JSON.stringify(w), s.headers = { [G]: z, ...s.headers }) : w !== void 0 && (s.body = w);
131
+ const m = (async () => {
132
+ const l = Date.now();
133
+ try {
134
+ const u = await fetch(T, s), b = await rt(u);
135
+ if (S("info", `${E} ${T} - ${u.status} (${Date.now() - l}ms)`, { req: s, res: b }), !u.ok) throw new _("Non-OK response", T, E, u.status, b);
136
+ return b;
137
+ } catch (u) {
138
+ throw S("error", `${E} ${T} - ERROR`, u), u instanceof _ ? u : new _(k(u).message, T, E, void 0, u);
139
+ } finally {
140
+ r(), $ && g.delete(e);
141
+ }
142
+ })();
143
+ return $ && g.set(e, m), m;
144
+ }
134
145
  return {
135
- /**
136
- * Cleans up expired cache entries.
137
- * Returns the number of entries removed.
138
- */
139
- cleanupCache() {
140
- const r = Date.now(), n = Array.from(i.entries()).filter(([, o]) => r > o.expiresIn).map(([o]) => o);
141
- for (const o of n)
142
- i.delete(o);
143
- return n.length;
144
- },
145
- /**
146
- * Clears all cached requests.
147
- */
148
- clearCache() {
149
- i.clear();
150
- },
151
- delete: e("DELETE"),
152
- get: e("GET"),
153
- /**
154
- * Returns the number of cached requests.
155
- */
156
- getCacheSize() {
157
- return i.size;
158
- },
159
- /**
160
- * Invalidates a specific cache entry by id or URL.
161
- */
162
- invalidateCache(r) {
163
- return i.delete(r);
164
- },
165
- patch: e("PATCH"),
166
- post: e("POST"),
167
- put: e("PUT"),
168
- /**
169
- * Updates the service headers.
170
- * Headers with undefined values will be removed.
171
- */
172
- setHeaders(r) {
173
- t.headers = Object.fromEntries(
174
- Object.entries({ ...t.headers, ...r }).filter(([, n]) => n !== void 0)
146
+ delete: (f, d) => A("DELETE", f, d),
147
+ get: (f, d) => A("GET", f, d),
148
+ getHeaders: () => ({ ...y }),
149
+ patch: (f, d) => A("PATCH", f, d),
150
+ post: (f, d) => A("POST", f, d),
151
+ put: (f, d) => A("PUT", f, d),
152
+ request: A,
153
+ setHeaders(f) {
154
+ y = Object.fromEntries(
155
+ Object.entries({ ...y, ...f }).filter(([, d]) => d !== void 0)
175
156
  );
176
157
  }
177
158
  };
178
159
  }
160
+ function at(t) {
161
+ const c = t?.cache?.staleTime ?? t?.staleTime ?? M, p = t?.cache?.gcTime ?? t?.gcTime ?? Q, a = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map();
162
+ function i(e) {
163
+ return j(e);
164
+ }
165
+ function y(e) {
166
+ const n = i(e);
167
+ let r = a.get(n);
168
+ return r || (r = {
169
+ abortController: null,
170
+ data: void 0,
171
+ dataUpdatedAt: 0,
172
+ error: null,
173
+ errorUpdatedAt: 0,
174
+ fetchedAt: 0,
175
+ gcTimer: null,
176
+ observers: /* @__PURE__ */ new Set(),
177
+ promise: null,
178
+ status: "idle"
179
+ }, a.set(n, r), h.set(n, n)), r;
180
+ }
181
+ function g(e) {
182
+ const n = {
183
+ data: e.data,
184
+ dataUpdatedAt: e.dataUpdatedAt,
185
+ error: e.error,
186
+ errorUpdatedAt: e.errorUpdatedAt,
187
+ fetchedAt: e.fetchedAt,
188
+ isError: e.status === "error",
189
+ isIdle: e.status === "idle",
190
+ isLoading: e.status === "pending",
191
+ isSuccess: e.status === "success",
192
+ status: e.status
193
+ };
194
+ e.observers.forEach((r) => {
195
+ try {
196
+ r(n);
197
+ } catch {
198
+ }
199
+ });
200
+ }
201
+ function S(e, n, r) {
202
+ n.gcTimer && (clearTimeout(n.gcTimer), n.gcTimer = null), r > 0 && (n.gcTimer = setTimeout(() => {
203
+ a.delete(e), h.delete(e);
204
+ }, r));
205
+ }
206
+ function A(e) {
207
+ e.abortController?.abort(), e.gcTimer && (clearTimeout(e.gcTimer), e.gcTimer = null);
208
+ }
209
+ function f(e, n, r = K) {
210
+ const s = e === !1 ? 1 : (e ?? r) + 1;
211
+ let m, l;
212
+ return typeof n == "function" ? (m = void 0, l = (u) => n(u - 1)) : typeof n == "number" ? (m = n, l = void 0) : (m = 1e3, l = (u, b) => Math.min(b * 2, 3e4)), { backoff: l, delay: m, times: s };
213
+ }
214
+ async function d(e) {
215
+ const {
216
+ queryKey: n,
217
+ queryFn: r,
218
+ staleTime: s = c,
219
+ gcTime: m = p,
220
+ enabled: l = !0,
221
+ retry: u = K,
222
+ retryDelay: b,
223
+ onSuccess: L,
224
+ onError: P
225
+ } = e;
226
+ if (!l) throw new Error("Query disabled");
227
+ const I = i(n), o = y(n);
228
+ if (o.status === "success" && Date.now() - o.dataUpdatedAt < s)
229
+ return o.data;
230
+ if (o.promise) return o.promise;
231
+ const U = new AbortController();
232
+ o.abortController = U, o.status = "pending", g(o);
233
+ const { times: V, delay: Y, backoff: v } = f(u, b), H = (async () => {
234
+ try {
235
+ const O = await q(() => r(), { backoff: v, delay: Y, signal: U.signal, times: V }), D = Date.now();
236
+ o.data = O, o.status = "success", o.dataUpdatedAt = D, o.fetchedAt = D, o.error = null, o.promise = null, o.abortController = null, S(I, o, m);
237
+ try {
238
+ L?.(O);
239
+ } catch {
240
+ }
241
+ return g(o), O;
242
+ } catch (O) {
243
+ const D = k(O), J = U.signal.aborted || D.name === "AbortError";
244
+ J ? (o.status = "idle", o.error = null) : (o.status = "error", o.error = D, o.errorUpdatedAt = Date.now()), o.promise = null, o.abortController = null;
245
+ try {
246
+ J || P?.(D);
247
+ } catch {
248
+ }
249
+ throw g(o), D;
250
+ }
251
+ })();
252
+ return o.promise = H, H;
253
+ }
254
+ async function C(e) {
255
+ return d({ ...e, enabled: !0 }).catch(() => {
256
+ });
257
+ }
258
+ function T(e) {
259
+ const n = i(e), r = a.get(n);
260
+ if (r) {
261
+ A(r), a.delete(n), h.delete(n);
262
+ return;
263
+ }
264
+ const s = [], m = n.slice(0, -1);
265
+ for (const [l, u] of h.entries())
266
+ if (u === n || // Exact match
267
+ u.startsWith(`${m},`)) {
268
+ const L = a.get(l);
269
+ L && A(L), s.push(l);
270
+ }
271
+ for (const l of s)
272
+ a.delete(l), h.delete(l);
273
+ }
274
+ function E() {
275
+ a.forEach(A), a.clear(), h.clear();
276
+ }
277
+ function w(e, n) {
278
+ const r = i(e), s = y(e);
279
+ s.data = typeof n == "function" ? n(s.data) : n, s.dataUpdatedAt = Date.now(), s.fetchedAt = s.fetchedAt || Date.now(), s.status = "success", S(r, s, p), g(s);
280
+ }
281
+ function F(e) {
282
+ const n = i(e);
283
+ return a.get(n)?.data ?? void 0;
284
+ }
285
+ function R(e) {
286
+ const n = i(e), r = a.get(n);
287
+ return r ? {
288
+ data: r.data,
289
+ dataUpdatedAt: r.dataUpdatedAt,
290
+ error: r.error,
291
+ errorUpdatedAt: r.errorUpdatedAt,
292
+ fetchedAt: r.fetchedAt,
293
+ isError: r.status === "error",
294
+ isIdle: r.status === "idle",
295
+ isLoading: r.status === "pending",
296
+ isSuccess: r.status === "success",
297
+ status: r.status
298
+ } : null;
299
+ }
300
+ function B(e, n) {
301
+ const r = y(e);
302
+ r.observers.add(n);
303
+ const s = {
304
+ data: r.data,
305
+ dataUpdatedAt: r.dataUpdatedAt,
306
+ error: r.error,
307
+ errorUpdatedAt: r.errorUpdatedAt,
308
+ fetchedAt: r.fetchedAt,
309
+ isError: r.status === "error",
310
+ isIdle: r.status === "idle",
311
+ isLoading: r.status === "pending",
312
+ isSuccess: r.status === "success",
313
+ status: r.status
314
+ };
315
+ return n(s), () => r.observers.delete(n);
316
+ }
317
+ function N(e, n) {
318
+ const r = i(e), s = a.get(r);
319
+ s && s.observers.delete(n);
320
+ }
321
+ async function $(e, n) {
322
+ const { mutationFn: r, onSuccess: s, onError: m, onSettled: l, retry: u = !1, retryDelay: b } = e, { times: L, delay: P, backoff: I } = f(u, b, 0);
323
+ try {
324
+ const o = await q(() => r(n), { backoff: I, delay: P, times: L });
325
+ try {
326
+ s?.(o, n);
327
+ } catch {
328
+ }
329
+ try {
330
+ l?.(o, null, n);
331
+ } catch {
332
+ }
333
+ return o;
334
+ } catch (o) {
335
+ const U = k(o);
336
+ try {
337
+ m?.(U, n);
338
+ } catch {
339
+ }
340
+ try {
341
+ l?.(void 0, U, n);
342
+ } catch {
343
+ }
344
+ throw U;
345
+ }
346
+ }
347
+ return {
348
+ clearCache: E,
349
+ fetch: d,
350
+ getCacheSize: () => a.size,
351
+ getData: F,
352
+ getState: R,
353
+ invalidate: T,
354
+ mutate: $,
355
+ prefetch: C,
356
+ setData: w,
357
+ subscribe: B,
358
+ unsubscribe: N
359
+ };
360
+ }
179
361
  export {
180
- y as HttpError,
181
- j as RequestErrorType,
182
- u as RequestStatus,
183
- P as buildUrl,
184
- v as createHttpClient
362
+ _ as HttpError,
363
+ st as createHttpClient,
364
+ at as createQueryClient
185
365
  };
186
366
  //# sourceMappingURL=fetchit.js.map