@vielzeug/courier 3.0.0 → 26.10.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/index.js CHANGED
@@ -1,670 +1,2 @@
1
- import { cache as e } from "@vielzeug/arsenal/cache";
2
- import { hash as t } from "@vielzeug/arsenal/object";
3
- import { abortError as n } from "@vielzeug/arsenal";
4
- //#region src/errors.ts
5
- var r = class extends Error {
6
- static errorName = "CourierError";
7
- constructor(e, t) {
8
- super(e, t), this.name = new.target.errorName, Object.setPrototypeOf(this, new.target.prototype);
9
- }
10
- }, i = class e extends r {
11
- static errorName = "CourierHttpError";
12
- url;
13
- method;
14
- status;
15
- data;
16
- headers;
17
- constructor(e) {
18
- super(e.message), this.url = e.url, this.method = e.method, this.status = e.status, this.data = e.data, this.headers = e.headers;
19
- }
20
- static fromResponse(t, n, r, i) {
21
- return new e({
22
- data: n,
23
- headers: t.headers,
24
- message: t.statusText || `HTTP ${t.status}`,
25
- method: r,
26
- status: t.status,
27
- url: i
28
- });
29
- }
30
- static is(t, n) {
31
- return t instanceof e && (n === void 0 || t.status === n);
32
- }
33
- }, a = class extends r {
34
- static errorName = "CourierNetworkError";
35
- url;
36
- method;
37
- constructor(e) {
38
- super(e.message, { cause: e.cause }), this.url = e.url, this.method = e.method;
39
- }
40
- }, o = class extends r {
41
- static errorName = "CourierTimeoutError";
42
- url;
43
- method;
44
- constructor(e) {
45
- super(e.message, { cause: e.cause }), this.url = e.url, this.method = e.method;
46
- }
47
- }, s = class extends r {
48
- static errorName = "CourierAbortError";
49
- url;
50
- method;
51
- constructor(e) {
52
- super(e.message, { cause: e.cause }), this.url = e.url, this.method = e.method;
53
- }
54
- }, c = class extends r {
55
- static errorName = "CourierSchemaValidationError";
56
- data;
57
- constructor(e, t) {
58
- super(e instanceof Error ? e.message : String(e), { cause: e }), this.data = t;
59
- }
60
- }, l = class extends r {
61
- static errorName = "CourierDisposedError";
62
- constructor(e) {
63
- super(`${e} disposed`);
64
- }
65
- }, u = class extends r {
66
- static errorName = "CourierParseError";
67
- };
68
- function d(e) {
69
- try {
70
- return typeof e == "object" && e && typeof e.name == "string" ? e.name : void 0;
71
- } catch {
72
- return;
73
- }
74
- }
75
- function f(e) {
76
- try {
77
- return typeof e == "object" && e && typeof e.message == "string" ? e.message : String(e);
78
- } catch {
79
- return "Request failed";
80
- }
81
- }
82
- function p(e, t, n, r) {
83
- let i = f(e), c = d(r?.reason), l = d(e);
84
- return c === "TimeoutError" || l === "TimeoutError" ? new o({
85
- cause: e,
86
- message: i,
87
- method: t,
88
- url: n
89
- }) : c === "AbortError" || l === "AbortError" || r?.aborted ? new s({
90
- cause: e,
91
- message: i,
92
- method: t,
93
- url: n
94
- }) : new a({
95
- cause: e,
96
- message: i,
97
- method: t,
98
- url: n
99
- });
100
- }
101
- //#endregion
102
- //#region src/transport.ts
103
- function m(e, t, n) {
104
- let r = Object.freeze({ ...t }), i = Object.freeze({ ...n });
105
- return Object.freeze({
106
- headers: r,
107
- init: i,
108
- url: e,
109
- withHeaders(t) {
110
- let n = { ...r };
111
- for (let [e, r] of Object.entries(t)) {
112
- let t = e.toLowerCase();
113
- r === void 0 ? delete n[t] : n[t] = r;
114
- }
115
- return m(e, n, i);
116
- },
117
- withInit(t) {
118
- return m(e, r, {
119
- ...i,
120
- ...t
121
- });
122
- }
123
- });
124
- }
125
- function h(...e) {
126
- let t = e.filter((e) => e != null);
127
- if (t.length !== 0) return t.length === 1 ? t[0] : AbortSignal.any(t);
128
- }
129
- var g = 3e4, _ = 2147483647;
130
- function v(e) {
131
- if (e !== Infinity && (!Number.isInteger(e) || e <= 0 || e > _)) throw new r(`[courier] timeout must be an integer from 1 to ${_}, or Infinity`);
132
- }
133
- function y(e, t) {
134
- return e === Infinity ? t ?? void 0 : h(AbortSignal.timeout(e), t);
135
- }
136
- function b(e = {}) {
137
- let { baseUrl: t = "", fetch: n = globalThis.fetch, headers: r = {}, middleware: i = [], timeout: a = g } = e;
138
- v(a);
139
- let o = Object.fromEntries(new Headers(r).entries()), s = /* @__PURE__ */ new Set(), c = new AbortController(), l = !1, u = async (e) => {
140
- try {
141
- return await n(e.url, {
142
- ...e.init,
143
- headers: e.headers
144
- });
145
- } catch (t) {
146
- throw p(t, (e.init.method ?? "GET").toUpperCase(), e.url, e.init.signal);
147
- }
148
- }, d = i.length === 0 ? u : i.reduceRight((e, t) => (n) => t(n, e), u);
149
- function f(e) {
150
- let t = e ? Object.fromEntries(new Headers(e).entries()) : void 0;
151
- return {
152
- ...o,
153
- ...t
154
- };
155
- }
156
- function h(e) {
157
- return s.add(e), () => s.delete(e);
158
- }
159
- function _(e) {
160
- return d(m(e.url, e.headers, e.init));
161
- }
162
- function y() {
163
- for (let e of [...s]) e.abort();
164
- s.clear();
165
- }
166
- function b() {
167
- if (!l) {
168
- l = !0, c.abort();
169
- for (let e of s) e.abort();
170
- s.clear();
171
- }
172
- }
173
- return {
174
- baseUrl: t,
175
- cancelAll: y,
176
- dispatch: _,
177
- get disposalSignal() {
178
- return c.signal;
179
- },
180
- dispose: b,
181
- get disposed() {
182
- return l;
183
- },
184
- mergeHeaders: f,
185
- timeout: a,
186
- track: h
187
- };
188
- }
189
- //#endregion
190
- //#region src/_cache.ts
191
- var x = 100, S = 3e4;
192
- function C(e, t) {
193
- if (e !== Infinity && (!Number.isFinite(e) || e < 0)) throw new r(`${t} must be a non-negative finite number or Infinity`);
194
- return e;
195
- }
196
- function w(e) {
197
- if (e !== Infinity && (!Number.isInteger(e) || e < 1)) throw new r("cache.capacity must be a positive integer or Infinity");
198
- return e;
199
- }
200
- function T(e) {
201
- if (!Array.isArray(e) || e.length === 0) throw new r("cache.key must be a non-empty array");
202
- for (let t of e) {
203
- if (t !== null && ![
204
- "boolean",
205
- "number",
206
- "string"
207
- ].includes(typeof t)) throw new r("cache.key atoms must be strings, finite numbers, booleans, or null");
208
- if (typeof t == "number" && !Number.isFinite(t)) throw new r("cache.key numbers must be finite");
209
- }
210
- return t(e);
211
- }
212
- function E(e, t) {
213
- return t.length <= e.length && t.every((t, n) => t === e[n]);
214
- }
215
- function D(e, t, n) {
216
- return t ? t.aborted ? Promise.reject(p(t.reason, "GET", n, t)) : new Promise((r, i) => {
217
- let a = () => i(p(t.reason, "GET", n, t));
218
- t.addEventListener("abort", a, { once: !0 }), e.then((e) => {
219
- t.removeEventListener("abort", a), r(e);
220
- }, (e) => {
221
- t.removeEventListener("abort", a), i(e);
222
- });
223
- }) : e;
224
- }
225
- function O(t) {
226
- let n = C(t?.ttlMs ?? S, "cache.ttlMs"), r = e({ capacity: w(t?.capacity ?? x) }), i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = (e) => ({
227
- id: T(e.key),
228
- key: Object.freeze([...e.key]),
229
- ttlMs: C(e.ttlMs ?? n, "cache.ttlMs")
230
- }), s = (e, t) => {
231
- let n = r.get(e);
232
- if (n) {
233
- if (t !== Infinity && Date.now() - n.cachedAt >= t) {
234
- r.delete(e);
235
- return;
236
- }
237
- return n;
238
- }
239
- }, c = (e, t) => {
240
- t === "prefetch" ? e.owners-- : e.waiters--, !(e.settled || e.owners > 0 || e.waiters > 0) && (e.cacheable = !1, i.get(e.id) === e && i.delete(e.id), e.controller.abort());
241
- }, l = (e, t, n, o) => {
242
- let s = new AbortController(), c = {
243
- cacheable: !0,
244
- controller: s,
245
- id: e,
246
- key: t,
247
- owners: 0,
248
- promise: void 0,
249
- settled: !1,
250
- ttlMs: n,
251
- waiters: 0
252
- }, l;
253
- try {
254
- l = Promise.resolve(o(s.signal));
255
- } catch (e) {
256
- l = Promise.reject(e);
257
- }
258
- return c.promise = l.then((n) => (c.cacheable && !s.signal.aborted && r.set(e, {
259
- cachedAt: Date.now(),
260
- data: n,
261
- key: t
262
- }, { ttlMs: c.ttlMs }), n)).finally(() => {
263
- c.settled = !0, a.delete(c), i.get(e) === c && i.delete(e);
264
- }), i.set(e, c), a.add(c), c;
265
- }, u = (e, t) => {
266
- let n = o(e), r = s(n.id, n.ttlMs);
267
- if (r) return {
268
- ...n,
269
- stored: r
270
- };
271
- let a = i.get(n.id) ?? l(n.id, n.key, n.ttlMs, t);
272
- return a.ttlMs = Math.min(a.ttlMs, n.ttlMs), {
273
- ...n,
274
- entry: a
275
- };
276
- };
277
- return {
278
- cancelAll() {
279
- for (let e of a) e.cacheable = !1, e.controller.abort();
280
- i.clear();
281
- },
282
- clear() {
283
- r.clear();
284
- for (let e of a) e.cacheable = !1;
285
- i.clear();
286
- },
287
- dispose() {
288
- r.clear();
289
- for (let e of a) e.cacheable = !1, e.controller.abort();
290
- i.clear(), a.clear();
291
- },
292
- invalidate(e) {
293
- T(e);
294
- for (let [t, n] of r.entries()) E(n.key, e) && r.delete(t);
295
- for (let t of a) E(t.key, e) && (t.cacheable = !1, i.get(t.id) === t && i.delete(t.id));
296
- },
297
- prefetch({ cache: e, load: t }) {
298
- let n = u(e, t);
299
- return "stored" in n ? Promise.resolve() : (n.entry.owners++, n.entry.promise.then(() => void 0, () => void 0).finally(() => c(n.entry, "prefetch")));
300
- },
301
- read({ cache: e, load: t, signal: n, timeout: r, url: i }) {
302
- v(r);
303
- let a = y(r, n);
304
- if (a?.aborted) return Promise.reject(p(a.reason, "GET", i, a));
305
- let o = u(e, t);
306
- return "stored" in o ? Promise.resolve(o.stored.data) : (o.entry.waiters++, D(o.entry.promise, a, i).finally(() => c(o.entry, "waiter")));
307
- }
308
- };
309
- }
310
- //#endregion
311
- //#region src/response.ts
312
- async function k(e) {
313
- let t = (await e.text()).trim();
314
- return t ? JSON.parse(t) : void 0;
315
- }
316
- function A(e, t, r) {
317
- if (!e.body) return r(), e;
318
- if (e.body.locked) throw new u("Raw response body is already locked");
319
- let i = e.body.getReader(), a = !1, o, s = () => {
320
- a || (a = !0, t?.removeEventListener("abort", c), r());
321
- }, c = () => {
322
- let e = n(t, "The operation was aborted.");
323
- try {
324
- o?.error(e);
325
- } catch {}
326
- s(), i.cancel(e).catch(() => void 0);
327
- }, l = new ReadableStream({
328
- cancel: async (e) => {
329
- try {
330
- await i.cancel(e);
331
- } finally {
332
- s();
333
- }
334
- },
335
- pull: async (e) => {
336
- try {
337
- let t = await i.read();
338
- if (a) return;
339
- t.done ? (e.close(), s()) : e.enqueue(t.value);
340
- } catch (t) {
341
- a || e.error(t), s();
342
- }
343
- },
344
- start: (e) => {
345
- o = e, t?.aborted ? c() : t?.addEventListener("abort", c, { once: !0 });
346
- }
347
- });
348
- return j(new Response(l, {
349
- headers: e.headers,
350
- status: e.status,
351
- statusText: e.statusText
352
- }), e);
353
- }
354
- function j(e, t) {
355
- let n = e.clone.bind(e);
356
- return Object.defineProperties(e, {
357
- clone: { value: () => j(n(), t) },
358
- redirected: { value: t.redirected },
359
- type: { value: t.type },
360
- url: { value: t.url }
361
- }), e;
362
- }
363
- async function M(e, t = "auto") {
364
- if (t === "raw") return e;
365
- if (e.status === 204 || e.status === 205) return;
366
- if (t === "json") return k(e);
367
- if (t === "text") return e.text();
368
- if (t === "blob") return e.blob();
369
- if (t === "arrayBuffer") return e.arrayBuffer();
370
- let n = e.headers.get("content-type") ?? "";
371
- return n.includes("application/json") || n.includes("+json") ? k(e) : n.startsWith("text/") ? e.text() : n.startsWith("image/") || n.startsWith("audio/") || n.startsWith("video/") ? e.blob() : e.text();
372
- }
373
- //#endregion
374
- //#region src/serialize.ts
375
- function N(e, t, n, r, i) {
376
- if (n !== void 0 && !I(n)) {
377
- let a = JSON.stringify(n);
378
- if (a === void 0) throw TypeError("request body is not JSON-serializable");
379
- return {
380
- ...i,
381
- body: a,
382
- headers: {
383
- "content-type": "application/json",
384
- ...t
385
- },
386
- method: e.toUpperCase(),
387
- signal: r
388
- };
389
- }
390
- return {
391
- ...i,
392
- ...n !== void 0 && { body: n },
393
- ...F(n) && { duplex: "half" },
394
- headers: t,
395
- method: e.toUpperCase(),
396
- signal: r
397
- };
398
- }
399
- function P(e) {
400
- try {
401
- return Object.prototype.toString.call(e);
402
- } catch {
403
- return "";
404
- }
405
- }
406
- function F(e) {
407
- return P(e) === "[object ReadableStream]" && typeof e.getReader == "function";
408
- }
409
- function I(e) {
410
- return typeof e == "string" || ArrayBuffer.isView(e) ? !0 : [
411
- "[object ArrayBuffer]",
412
- "[object Blob]",
413
- "[object FormData]",
414
- "[object URLSearchParams]",
415
- "[object ReadableStream]"
416
- ].includes(P(e));
417
- }
418
- //#endregion
419
- //#region src/url.ts
420
- function L(e, t, n, r) {
421
- let i = e.replace(/\/+$/, ""), a = i ? t.replace(/^\/+/, "") : t;
422
- a = a.replace(/\{([^}]+)\}/g, (e, r) => {
423
- let i = n?.[r];
424
- if (i == null) throw new u(`unresolved path param {${r}} in '${t}'`);
425
- return encodeURIComponent(String(i));
426
- });
427
- let o = i && a ? `${i}/${a}` : i || a;
428
- if (!r) return o;
429
- let s = new URLSearchParams();
430
- for (let [e, t] of Object.entries(r)) if (t !== void 0) {
431
- if (Array.isArray(t)) {
432
- for (let n of t) n !== void 0 && s.append(e, n === null ? "" : String(n));
433
- continue;
434
- }
435
- s.append(e, t === null ? "" : String(t));
436
- }
437
- let c = s.toString();
438
- if (!c) return o;
439
- let l = o.indexOf("#"), d = l === -1 ? o : o.slice(0, l), f = l === -1 ? "" : o.slice(l);
440
- return `${d}${d.includes("?") ? "&" : "?"}${c}${f}`;
441
- }
442
- //#endregion
443
- //#region src/courier.ts
444
- function R(e = {}) {
445
- let { cache: t, ...n } = e, a = b(n), o = O(t), s = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set();
446
- function f(e) {
447
- if (d.size === 0) return;
448
- let t = Object.freeze(e);
449
- for (let e of [...d]) try {
450
- e(t);
451
- } catch {}
452
- }
453
- function m(e, t) {
454
- if (a.disposed || t?.signal?.aborted) return () => {};
455
- d.add(e);
456
- let n = () => {
457
- d.delete(e), s.delete(n), t?.signal?.removeEventListener("abort", n);
458
- };
459
- return t?.signal && (s.add(n), t.signal.addEventListener("abort", n, { once: !0 })), n;
460
- }
461
- async function g(e, t, n, o, s, l) {
462
- let d = t.signal, f = await a.dispatch({
463
- headers: e,
464
- init: t,
465
- url: n
466
- });
467
- if (!f.ok) {
468
- let e = f.headers.get("content-type")?.includes("json") ?? !1, t;
469
- try {
470
- t = await f.text();
471
- } catch (e) {
472
- throw d?.aborted ? p(e, o, n, d) : new u(e instanceof Error ? e.message : String(e), { cause: e });
473
- }
474
- let r = t;
475
- if (t && e) try {
476
- r = JSON.parse(t);
477
- } catch {}
478
- throw i.fromResponse(f, r, o, n);
479
- }
480
- let m;
481
- try {
482
- m = await M(f, s ?? "auto");
483
- } catch (e) {
484
- throw d?.aborted ? p(e, o, n, d) : e instanceof r ? e : new u(e instanceof Error ? e.message : String(e), { cause: e });
485
- }
486
- if (l) try {
487
- return {
488
- result: l.parse(m),
489
- status: f.status
490
- };
491
- } catch (e) {
492
- throw new c(e, m);
493
- }
494
- return {
495
- result: m,
496
- status: f.status
497
- };
498
- }
499
- function _(e, t) {
500
- try {
501
- return L(a.baseUrl, e, t.params, t.query);
502
- } catch (e) {
503
- throw e instanceof r ? e : new u(e instanceof Error ? e.message : String(e), { cause: e });
504
- }
505
- }
506
- async function x(e, t = {}) {
507
- if (a.disposed) throw new l("Courier");
508
- let n = (t.method ?? "GET").toUpperCase(), r = _(e, t), { body: i, fetchInit: o, headers: s, responseType: c, schema: d, signal: p, timeout: m } = t;
509
- if ((n === "GET" || n === "HEAD") && i !== void 0) throw new u(`${n} requests cannot include a body`);
510
- if (c === "raw" && d !== void 0) throw new u("Raw responses cannot use a schema");
511
- m !== void 0 && v(m);
512
- let b = new AbortController(), x = a.track(b), S = y(m ?? a.timeout, h(p, b.signal)), C = performance.now(), w = !1;
513
- f({
514
- method: n,
515
- type: "request-start",
516
- url: r
517
- });
518
- try {
519
- let e;
520
- try {
521
- e = N(n, a.mergeHeaders(s), i, S, o ?? {});
522
- } catch (e) {
523
- throw new u(e instanceof Error ? e.message : String(e), { cause: e });
524
- }
525
- let { headers: t, ...l } = e, { result: p, status: m } = await g(t, l, r, n, c, d);
526
- if (c === "raw" && p instanceof Response) {
527
- let e = A(p, S, x);
528
- return w = !0, f({
529
- duration: performance.now() - C,
530
- method: n,
531
- status: m,
532
- type: "request-success",
533
- url: r
534
- }), e;
535
- }
536
- return f({
537
- duration: performance.now() - C,
538
- method: n,
539
- status: m,
540
- type: "request-success",
541
- url: r
542
- }), p;
543
- } catch (e) {
544
- throw f({
545
- error: e,
546
- method: n,
547
- type: "request-error",
548
- url: r
549
- }), e;
550
- } finally {
551
- w || x();
552
- }
553
- }
554
- let S = (e, t, n) => x(t, {
555
- ...n,
556
- method: e
557
- });
558
- function C(e, t) {
559
- try {
560
- let n = t ?? {}, { cache: r, signal: i, timeout: s, ...c } = n;
561
- if (!r) return S("GET", e, {
562
- ...c,
563
- signal: i,
564
- timeout: s
565
- });
566
- let l = _(e, n);
567
- return o.read({
568
- cache: r,
569
- load: (t) => S("GET", e, {
570
- ...c,
571
- signal: t
572
- }),
573
- signal: i,
574
- timeout: s ?? a.timeout,
575
- url: l
576
- });
577
- } catch (e) {
578
- return Promise.reject(e);
579
- }
580
- }
581
- function w(e, t) {
582
- if (a.disposed) throw new l("Courier");
583
- let { cache: n, ...r } = t;
584
- return _(e, t), o.prefetch({
585
- cache: n,
586
- load: (t) => S("GET", e, {
587
- ...r,
588
- signal: t
589
- })
590
- });
591
- }
592
- return {
593
- cancelAll() {
594
- o.cancelAll(), a.cancelAll();
595
- },
596
- clearCache() {
597
- o.clear();
598
- },
599
- delete: (e, t) => S("DELETE", e, t),
600
- get disposalSignal() {
601
- return a.disposalSignal;
602
- },
603
- dispose() {
604
- if (!a.disposed) {
605
- f({ type: "dispose" });
606
- for (let e of [...s]) e();
607
- d.clear(), o.dispose(), a.dispose();
608
- }
609
- },
610
- get disposed() {
611
- return a.disposed;
612
- },
613
- get: C,
614
- invalidateCache(e) {
615
- o.invalidate(e);
616
- },
617
- patch: (e, t) => S("PATCH", e, t),
618
- post: (e, t) => S("POST", e, t),
619
- prefetch: w,
620
- put: (e, t) => S("PUT", e, t),
621
- request: x,
622
- tap: m,
623
- [Symbol.dispose]() {
624
- this.dispose();
625
- }
626
- };
627
- }
628
- //#endregion
629
- //#region src/interceptors.ts
630
- function z(e) {
631
- return async (t, n) => {
632
- let r = typeof e == "function" ? await e() : e;
633
- return n(t.withHeaders({ authorization: r ? `Bearer ${r}` : void 0 }));
634
- };
635
- }
636
- function B(e) {
637
- let t = e?.header ?? "x-request-id", n = e?.generate ?? (() => crypto.randomUUID());
638
- return (e, r) => r(e.withHeaders({ [t]: n() }));
639
- }
640
- function V(e) {
641
- let t = e.logger, n = (e, n) => {
642
- try {
643
- t(e, n);
644
- } catch {}
645
- };
646
- return async (e, t) => {
647
- let r = performance.now(), i = (e.init.method ?? "GET").toUpperCase();
648
- try {
649
- let a = await t(e), o = Math.round(performance.now() - r);
650
- return n(`${i} ${e.url} ${a.status} (${o}ms)`, {
651
- duration: o,
652
- method: i,
653
- status: a.status,
654
- url: e.url
655
- }), a;
656
- } catch (t) {
657
- let a = Math.round(performance.now() - r);
658
- throw n(`${i} ${e.url} ERR (${a}ms)`, {
659
- duration: a,
660
- method: i,
661
- status: 0,
662
- url: e.url
663
- }), t;
664
- }
665
- };
666
- }
667
- //#endregion
668
- export { s as CourierAbortError, l as CourierDisposedError, r as CourierError, i as CourierHttpError, a as CourierNetworkError, u as CourierParseError, c as CourierSchemaValidationError, o as CourierTimeoutError, R as createCourier, z as withBearerAuth, V as withLogging, B as withRequestId };
669
-
1
+ import{abortError as e,tapper as t}from"@vielzeug/arsenal";import{cache as n}from"@vielzeug/arsenal/cache";import{hash as r}from"@vielzeug/arsenal/object";var CourierError=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},i=class CourierHttpError extends CourierError{url;method;status;data;headers;constructor(e){super(e.message),this.url=e.url,this.method=e.method,this.status=e.status,this.data=e.data,this.headers=e.headers}static fromResponse(e,t,n,r){return new CourierHttpError({data:t,headers:e.headers,message:e.statusText||`HTTP ${e.status}`,method:n,status:e.status,url:r})}static is(e,t){return e instanceof CourierHttpError&&(t===void 0||e.status===t)}},CourierNetworkError=class extends CourierError{url;method;constructor(e){super(e.message,{cause:e.cause}),this.url=e.url,this.method=e.method}},CourierTimeoutError=class extends CourierError{url;method;constructor(e){super(e.message,{cause:e.cause}),this.url=e.url,this.method=e.method}},CourierAbortError=class extends CourierError{url;method;constructor(e){super(e.message,{cause:e.cause}),this.url=e.url,this.method=e.method}},CourierSchemaValidationError=class extends CourierError{data;constructor(e,t){super(e instanceof Error?e.message:String(e),{cause:e}),this.data=t}},CourierDisposedError=class extends CourierError{constructor(e){super(`${e} disposed`)}},CourierParseError=class extends CourierError{},CourierConfigError=class extends CourierError{};function errorName(e){try{return typeof e==`object`&&e&&typeof e.name==`string`?e.name:void 0}catch{return}}function errorMessage(e){try{return typeof e==`object`&&e&&typeof e.message==`string`?e.message:String(e)}catch{return`Request failed`}}function classifyRequestError(e,t,n,r){let i=errorMessage(e),a=errorName(r?.reason),o=errorName(e);return a===`TimeoutError`||o===`TimeoutError`?new CourierTimeoutError({cause:e,message:i,method:t,url:n}):a===`AbortError`||o===`AbortError`||r?.aborted?new CourierAbortError({cause:e,message:i,method:t,url:n}):new CourierNetworkError({cause:e,message:i,method:t,url:n})}function makeFetchContext(e,t,n){let r=Object.freeze({...t}),i=Object.freeze({...n});return Object.freeze({headers:r,init:i,url:e,withHeaders(t){let n={...r};for(let[e,r]of Object.entries(t)){let t=e.toLowerCase();r===void 0?delete n[t]:n[t]=r}return makeFetchContext(e,n,i)},withInit(t){return makeFetchContext(e,r,{...i,...t})}})}function anySignal(...e){let t=e.filter(e=>e!=null);if(t.length!==0)return t.length===1?t[0]:AbortSignal.any(t)}var a=3e4,o=2147483647;function validateTimeout(e){if(e!==1/0&&(!Number.isInteger(e)||e<=0||e>o))throw new CourierError(`[courier] timeout must be an integer from 1 to ${o}, or Infinity`)}function buildTimeoutSignal(e,t){return e===1/0?t??void 0:anySignal(AbortSignal.timeout(e),t)}function createTransportCore(e={}){let{baseUrl:t=``,fetch:n=globalThis.fetch,headers:r={},middleware:i=[],timeout:o=a}=e;validateTimeout(o);let s=Object.fromEntries(new Headers(r).entries()),c=new Set,l=new AbortController,u=!1,base=async e=>{try{return await n(e.url,{...e.init,headers:e.headers})}catch(t){throw classifyRequestError(t,(e.init.method??`GET`).toUpperCase(),e.url,e.init.signal)}},d=i.length===0?base:i.reduceRight((e,t)=>n=>t(n,e),base);function mergeHeaders(e){let t=e?Object.fromEntries(new Headers(e).entries()):void 0;return{...s,...t}}function track(e){return c.add(e),()=>c.delete(e)}function dispatch(e){return d(makeFetchContext(e.url,e.headers,e.init))}function cancelAll(){for(let e of[...c])e.abort();c.clear()}function dispose(){if(!u){u=!0,l.abort();for(let e of c)e.abort();c.clear()}}return{baseUrl:t,cancelAll,dispatch,get disposalSignal(){return l.signal},dispose,get disposed(){return u},mergeHeaders,timeout:o,track}}var s=100,c=3e4;function duration(e,t){if(e!==1/0&&(!Number.isFinite(e)||e<0))throw new CourierError(`${t} must be a non-negative finite number or Infinity`);return e}function capacity(e){if(e!==1/0&&(!Number.isInteger(e)||e<1))throw new CourierError(`cache.capacity must be a positive integer or Infinity`);return e}function keyId(e){if(!Array.isArray(e)||e.length===0)throw new CourierError(`cache.key must be a non-empty array`);for(let t of e){if(t!==null&&![`boolean`,`number`,`string`].includes(typeof t))throw new CourierError(`cache.key atoms must be strings, finite numbers, booleans, or null`);if(typeof t==`number`&&!Number.isFinite(t))throw new CourierError(`cache.key numbers must be finite`)}return r(e)}function matches(e,t){return t.length<=e.length&&t.every((t,n)=>t===e[n])}function waitFor(e,t,n){return t?t.aborted?Promise.reject(classifyRequestError(t.reason,`GET`,n,t)):new Promise((r,i)=>{let abort=()=>i(classifyRequestError(t.reason,`GET`,n,t));t.addEventListener(`abort`,abort,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,abort),r(e)},e=>{t.removeEventListener(`abort`,abort),i(e)})}):e}function createReadCache(e){let t=duration(e?.ttlMs??c,`cache.ttlMs`),r=n({capacity:capacity(e?.capacity??s)}),i=new Map,a=new Set,resolveCache=e=>({id:keyId(e.key),key:Object.freeze([...e.key]),ttlMs:duration(e.ttlMs??t,`cache.ttlMs`)}),readStored=(e,t)=>{let n=r.get(e);if(n){if(t!==1/0&&Date.now()-n.cachedAt>=t){r.delete(e);return}return n}},release=(e,t)=>{t===`prefetch`?e.owners--:e.waiters--,!(e.settled||e.owners>0||e.waiters>0)&&(e.cacheable=!1,i.get(e.id)===e&&i.delete(e.id),e.controller.abort())},start=(e,t,n,o)=>{let s=new AbortController,c={cacheable:!0,controller:s,id:e,key:t,owners:0,promise:void 0,settled:!1,ttlMs:n,waiters:0},l;try{l=Promise.resolve(o(s.signal))}catch(e){l=Promise.reject(e)}return c.promise=l.then(n=>(c.cacheable&&!s.signal.aborted&&r.set(e,{cachedAt:Date.now(),data:n,key:t},{ttlMs:c.ttlMs}),n)).finally(()=>{c.settled=!0,a.delete(c),i.get(e)===c&&i.delete(e)}),i.set(e,c),a.add(c),c},obtain=(e,t)=>{let n=resolveCache(e),r=readStored(n.id,n.ttlMs);if(r)return{...n,stored:r};let a=i.get(n.id)??start(n.id,n.key,n.ttlMs,t);return a.ttlMs=Math.min(a.ttlMs,n.ttlMs),{...n,entry:a}};return{cancelAll(){for(let e of a)e.cacheable=!1,e.controller.abort();i.clear()},clear(){r.clear();for(let e of a)e.cacheable=!1;i.clear()},dispose(){r.clear();for(let e of a)e.cacheable=!1,e.controller.abort();i.clear(),a.clear()},invalidate(e){keyId(e);for(let[t,n]of r.entries())matches(n.key,e)&&r.delete(t);for(let t of a)matches(t.key,e)&&(t.cacheable=!1,i.get(t.id)===t&&i.delete(t.id))},prefetch({cache:e,load:t}){let n=obtain(e,t);return`stored`in n?Promise.resolve():(n.entry.owners++,n.entry.promise.then(()=>void 0,()=>void 0).finally(()=>release(n.entry,`prefetch`)))},read({cache:e,load:t,signal:n,timeout:r,url:i}){validateTimeout(r);let a=buildTimeoutSignal(r,n);if(a?.aborted)return Promise.reject(classifyRequestError(a.reason,`GET`,i,a));let o=obtain(e,t);return`stored`in o?Promise.resolve(o.stored.data):(o.entry.waiters++,waitFor(o.entry.promise,a,i).finally(()=>release(o.entry,`waiter`)))}}}async function parseJson(e){let t=(await e.text()).trim();return t?JSON.parse(t):void 0}function trackRawResponse(t,n,r){if(!t.body)return r(),t;if(t.body.locked)throw new CourierParseError(`Raw response body is already locked`);let i=t.body.getReader(),a=!1,o,finish=()=>{a||(a=!0,n?.removeEventListener(`abort`,abort),r())},abort=()=>{let t=e(n,`The operation was aborted.`);try{o?.error(t)}catch{}finish(),i.cancel(t).catch(()=>void 0)},s=new ReadableStream({cancel:async e=>{try{await i.cancel(e)}finally{finish()}},pull:async e=>{try{let t=await i.read();if(a)return;t.done?(e.close(),finish()):e.enqueue(t.value)}catch(t){a||e.error(t),finish()}},start:e=>{o=e,n?.aborted?abort():n?.addEventListener(`abort`,abort,{once:!0})}});return preserveMetadata(new Response(s,{headers:t.headers,status:t.status,statusText:t.statusText}),t)}function preserveMetadata(e,t){let n=e.clone.bind(e);return Object.defineProperties(e,{clone:{value:()=>preserveMetadata(n(),t)},redirected:{value:t.redirected},type:{value:t.type},url:{value:t.url}}),e}async function parseResponse(e,t=`auto`){if(t===`raw`)return e;if(e.status===204||e.status===205)return;if(t===`json`)return parseJson(e);if(t===`text`)return e.text();if(t===`blob`)return e.blob();if(t===`arrayBuffer`)return e.arrayBuffer();let n=e.headers.get(`content-type`)??``;return n.includes(`application/json`)||n.includes(`+json`)?parseJson(e):n.startsWith(`text/`)?e.text():n.startsWith(`image/`)||n.startsWith(`audio/`)||n.startsWith(`video/`)?e.blob():e.text()}function buildRequestInit(e,t,n,r,i){if(n!==void 0&&!isBodyInit(n)){let a=JSON.stringify(n);if(a===void 0)throw TypeError(`request body is not JSON-serializable`);return{...i,body:a,headers:{"content-type":`application/json`,...t},method:e.toUpperCase(),signal:r}}return{...i,...n!==void 0&&{body:n},...isReadableStream(n)&&{duplex:`half`},headers:t,method:e.toUpperCase(),signal:r}}function objectTag(e){try{return Object.prototype.toString.call(e)}catch{return``}}function isReadableStream(e){return objectTag(e)===`[object ReadableStream]`&&typeof e.getReader==`function`}function isBodyInit(e){return typeof e==`string`||ArrayBuffer.isView(e)?!0:[`[object ArrayBuffer]`,`[object Blob]`,`[object FormData]`,`[object URLSearchParams]`,`[object ReadableStream]`].includes(objectTag(e))}function buildUrl(e,t,n,r){let i=e.replace(/\/+$/,``),a=i?t.replace(/^\/+/,``):t;a=a.replace(/\{([^}]+)\}/g,(e,r)=>{let i=n?.[r];if(i==null)throw new CourierParseError(`unresolved path param {${r}} in '${t}'`);return encodeURIComponent(String(i))});let o=i&&a?`${i}/${a}`:i||a;if(!r)return o;let s=new URLSearchParams;for(let[e,t]of Object.entries(r))if(t!==void 0){if(Array.isArray(t)){for(let n of t)n!==void 0&&s.append(e,n===null?``:String(n));continue}s.append(e,t===null?``:String(t))}let c=s.toString();if(!c)return o;let l=o.indexOf(`#`),u=l===-1?o:o.slice(0,l),d=l===-1?``:o.slice(l);return`${u}${u.includes(`?`)?`&`:`?`}${c}${d}`}function createCourier(e={}){let{cache:n,...r}=e,a=createTransportCore(r),o=createReadCache(n),s=t();function emit(e){s.size!==0&&s.emit(Object.freeze(e))}function tap(e,t){return a.disposed?()=>{}:s.tap(e,t)}async function execute(e,t,n,r,o,s){let c=t.signal,l=await a.dispatch({headers:e,init:t,url:n});if(!l.ok){let e=l.headers.get(`content-type`)?.includes(`json`)??!1,t;try{t=await l.text()}catch(e){throw c?.aborted?classifyRequestError(e,r,n,c):new CourierParseError(e instanceof Error?e.message:String(e),{cause:e})}let a=t;if(t&&e)try{a=JSON.parse(t)}catch{}throw i.fromResponse(l,a,r,n)}let u;try{u=await parseResponse(l,o??`auto`)}catch(e){throw c?.aborted?classifyRequestError(e,r,n,c):e instanceof CourierError?e:new CourierParseError(e instanceof Error?e.message:String(e),{cause:e})}if(s)try{return{result:s.parse(u),status:l.status}}catch(e){throw new CourierSchemaValidationError(e,u)}return{result:u,status:l.status}}function resolveUrl(e,t){try{return buildUrl(a.baseUrl,e,t.params,t.query)}catch(e){throw e instanceof CourierError?e:new CourierParseError(e instanceof Error?e.message:String(e),{cause:e})}}async function request(e,t={}){if(a.disposed)throw new CourierDisposedError(`Courier`);let n=(t.method??`GET`).toUpperCase(),r=resolveUrl(e,t),{body:i,fetchInit:o,headers:s,responseType:c,schema:l,signal:u,timeout:d}=t;if((n===`GET`||n===`HEAD`)&&i!==void 0)throw new CourierConfigError(`${n} requests cannot include a body`);if(c===`raw`&&l!==void 0)throw new CourierConfigError(`Raw responses cannot use a schema`);d!==void 0&&validateTimeout(d);let f=new AbortController,p=a.track(f),m=buildTimeoutSignal(d??a.timeout,anySignal(u,f.signal)),h=performance.now(),g=!1;emit({method:n,type:`request-start`,url:r});try{let e;try{e=buildRequestInit(n,a.mergeHeaders(s),i,m,o??{})}catch(e){throw new CourierParseError(e instanceof Error?e.message:String(e),{cause:e})}let{headers:t,...u}=e,{result:d,status:f}=await execute(t,u,r,n,c,l);if(c===`raw`&&d instanceof Response){let e=trackRawResponse(d,m,p);return g=!0,emit({duration:performance.now()-h,method:n,status:f,type:`request-success`,url:r}),e}return emit({duration:performance.now()-h,method:n,status:f,type:`request-success`,url:r}),d}catch(e){throw emit({error:e,method:n,type:`request-error`,url:r}),e}finally{g||p()}}let requestWithMethod=(e,t,n)=>request(t,{...n,method:e});function get(e,t){try{let n=t??{},{cache:r,signal:i,timeout:s,...c}=n;if(!r)return requestWithMethod(`GET`,e,{...c,signal:i,timeout:s});let l=resolveUrl(e,n);return o.read({cache:r,load:t=>requestWithMethod(`GET`,e,{...c,signal:t}),signal:i,timeout:s??a.timeout,url:l})}catch(e){return Promise.reject(e)}}function prefetch(e,t){if(a.disposed)throw new CourierDisposedError(`Courier`);let{cache:n,...r}=t;return resolveUrl(e,t),o.prefetch({cache:n,load:t=>requestWithMethod(`GET`,e,{...r,signal:t})})}return{cancelAll(){o.cancelAll(),a.cancelAll()},clearCache(){o.clear()},delete:(e,t)=>requestWithMethod(`DELETE`,e,t),get disposalSignal(){return a.disposalSignal},dispose(){a.disposed||(emit({type:`dispose`}),s.clear(),o.dispose(),a.dispose())},get disposed(){return a.disposed},get,invalidateCache(e){o.invalidate(e)},patch:(e,t)=>requestWithMethod(`PATCH`,e,t),post:(e,t)=>requestWithMethod(`POST`,e,t),prefetch,put:(e,t)=>requestWithMethod(`PUT`,e,t),request,tap,[Symbol.dispose](){this.dispose()}}}function withBearerAuth(e){return async(t,n)=>{let r=typeof e==`function`?await e():e;return n(t.withHeaders({authorization:r?`Bearer ${r}`:void 0}))}}function withRequestId(e){let t=e?.header??`x-request-id`,n=e?.generate??(()=>crypto.randomUUID());return(e,r)=>r(e.withHeaders({[t]:n()}))}function withLogging(e){let t=e.logger,write=(e,n)=>{try{t(e,n)}catch{}};return async(e,t)=>{let n=performance.now(),r=(e.init.method??`GET`).toUpperCase();try{let i=await t(e),a=Math.round(performance.now()-n);return write(`${r} ${e.url} ${i.status} (${a}ms)`,{duration:a,method:r,status:i.status,url:e.url}),i}catch(t){let i=Math.round(performance.now()-n);throw write(`${r} ${e.url} ERR (${i}ms)`,{duration:i,method:r,status:0,url:e.url}),t}}}export{CourierAbortError,CourierConfigError,CourierDisposedError,CourierError,i as CourierHttpError,CourierNetworkError,CourierParseError,CourierSchemaValidationError,CourierTimeoutError,createCourier,withBearerAuth,withLogging,withRequestId};
670
2
  //# sourceMappingURL=index.js.map