create-request 1.6.0 → 2.0.0-next.0

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 ADDED
@@ -0,0 +1,717 @@
1
+ //#region src/error.ts
2
+ var RequestError = class extends Error {
3
+ name = "RequestError";
4
+ constructor(message, options) {
5
+ super(message, options);
6
+ Object.assign(this, options);
7
+ }
8
+ get data() {
9
+ if (this._data === void 0 && this.body) try {
10
+ this._data = JSON.parse(this.body);
11
+ } catch {}
12
+ return this._data;
13
+ }
14
+ get isTimeout() {
15
+ return this.code === "TIMEOUT";
16
+ }
17
+ get isAborted() {
18
+ return this.code === "ABORTED";
19
+ }
20
+ };
21
+ const isRequestError = (error) => error instanceof RequestError;
22
+ const messageOf = (error) => error instanceof Error ? error.message : String(error);
23
+
24
+ //#endregion
25
+ //#region src/schema.ts
26
+ const isSchema = (value) => !!value && (typeof value === "object" || typeof value === "function") && "~standard" in value;
27
+
28
+ //#endregion
29
+ //#region src/utils.ts
30
+ const anySignal = (signals) => {
31
+ const list = signals.filter((signal) => !!signal);
32
+ if (list.length < 2) return list[0];
33
+ if (AbortSignal.any) return AbortSignal.any(list);
34
+ const controller = new AbortController();
35
+ for (const signal of list) {
36
+ if (signal.aborted) {
37
+ controller.abort(signal.reason);
38
+ break;
39
+ }
40
+ signal.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
41
+ }
42
+ return controller.signal;
43
+ };
44
+ const abortError = (signal, deadline) => {
45
+ if (deadline?.controller.signal.aborted) return ["TIMEOUT", `Request timed out after ${deadline.ms}ms`];
46
+ if (!signal?.aborted) return void 0;
47
+ return signal.reason?.name === "TimeoutError" ? ["TIMEOUT", "Request timed out"] : ["ABORTED", "Request aborted"];
48
+ };
49
+ const MAX_DELAY = 2 ** 31 - 1;
50
+ const sleep = (ms, signal) => new Promise((resolve) => {
51
+ if (signal?.aborted) return resolve();
52
+ const done = () => {
53
+ clearTimeout(timer);
54
+ signal?.removeEventListener("abort", done);
55
+ resolve();
56
+ };
57
+ const timer = setTimeout(done, Math.min(ms, MAX_DELAY));
58
+ signal?.addEventListener("abort", done);
59
+ });
60
+ const release = (body) => void body?.cancel().catch(() => void 0);
61
+ const readCapped = async (body, max) => {
62
+ const decoder = new TextDecoder();
63
+ let text = "";
64
+ let size = 0;
65
+ try {
66
+ for (const reader = body?.getReader(); reader;) {
67
+ const { done, value } = await reader.read();
68
+ if (done) break;
69
+ if ((size += value.length) > max) return void reader.cancel().catch(() => void 0);
70
+ text += decoder.decode(value, { stream: true });
71
+ }
72
+ return text + decoder.decode();
73
+ } catch {
74
+ return;
75
+ }
76
+ };
77
+ const validUrl = (url) => {
78
+ try {
79
+ return !!url.trim() && !!new URL(url, "http://_");
80
+ } catch {
81
+ return false;
82
+ }
83
+ };
84
+ const sameOrigin = (url) => {
85
+ if (typeof location === "undefined") return true;
86
+ try {
87
+ return new URL(url, typeof document !== "undefined" && document.baseURI || location.href).origin === location.origin;
88
+ } catch {
89
+ return false;
90
+ }
91
+ };
92
+ const readCookie = (name) => {
93
+ if (typeof document === "undefined") return void 0;
94
+ for (const part of document.cookie.split(";")) {
95
+ const at = part.indexOf("=");
96
+ if (at > 0 && part.slice(0, at).trim() === name) {
97
+ const value = part.slice(at + 1).trim();
98
+ try {
99
+ return decodeURIComponent(value);
100
+ } catch {
101
+ return value;
102
+ }
103
+ }
104
+ }
105
+ };
106
+ const retryAfter = (response) => {
107
+ const header = response?.headers.get("retry-after");
108
+ if (!header) return void 0;
109
+ const ms = /^\d+(\.\d+)?$/.test(header) ? +header * 1e3 : Date.parse(header) - Date.now();
110
+ return ms >= 0 ? ms : ms < 0 ? 0 : void 0;
111
+ };
112
+
113
+ //#endregion
114
+ //#region src/response.ts
115
+ var ResponseWrapper = class {
116
+ raw;
117
+ url;
118
+ method;
119
+ constructor(raw, url = "", method = "GET") {
120
+ this.raw = raw;
121
+ this.url = url;
122
+ this.method = method;
123
+ }
124
+ get status() {
125
+ return this.raw.status;
126
+ }
127
+ get statusText() {
128
+ return this.raw.statusText;
129
+ }
130
+ get ok() {
131
+ return this.raw.ok;
132
+ }
133
+ get headers() {
134
+ return this.raw.headers;
135
+ }
136
+ _err(message, code, extra) {
137
+ return new RequestError(message, {
138
+ code,
139
+ url: this.url,
140
+ method: this.method,
141
+ status: this.raw.status,
142
+ response: this.raw,
143
+ ...extra
144
+ });
145
+ }
146
+ _unreadable(fallback, extra) {
147
+ clearTimeout(this._timeout?.timer);
148
+ const aborted = abortError(this._signal, this._timeout);
149
+ return this._err(aborted?.[1] ?? fallback, aborted?.[0] ?? "PARSE", extra);
150
+ }
151
+ _buffer() {
152
+ if (!this._bin) {
153
+ if (this.raw.bodyUsed) return Promise.reject(this._unreadable("Response body already consumed"));
154
+ this._bin = this.raw.arrayBuffer().then((buffer) => {
155
+ clearTimeout(this._timeout?.timer);
156
+ return buffer;
157
+ }, (e) => {
158
+ throw this._unreadable(`Failed to read response body: ${messageOf(e)}`, { cause: e });
159
+ });
160
+ }
161
+ return this._bin;
162
+ }
163
+ async _validate(schema, data) {
164
+ let result;
165
+ try {
166
+ result = await schema["~standard"].validate(data);
167
+ } catch (e) {
168
+ throw this._err(`Schema validation threw: ${messageOf(e)}`, "VALIDATION", { cause: e });
169
+ }
170
+ if (result.issues) {
171
+ const [issue] = result.issues;
172
+ const path = issue?.path?.map((p) => String(typeof p === "object" ? p.key : p)).join(".");
173
+ throw this._err(`Response validation failed: ${issue?.message}${path ? ` at ${path}` : ""}`, "VALIDATION", {
174
+ body: await this.getText(),
175
+ issues: result.issues
176
+ });
177
+ }
178
+ return result.value;
179
+ }
180
+ getArrayBuffer() {
181
+ return this._buffer();
182
+ }
183
+ async getBlob() {
184
+ return new Blob([await this._buffer()], { type: this.raw.headers.get("content-type") ?? "" });
185
+ }
186
+ getText() {
187
+ return this._text ??= this._buffer().then((buffer) => new TextDecoder().decode(buffer));
188
+ }
189
+ async getFormData() {
190
+ const buffer = await this._buffer();
191
+ try {
192
+ return await new Response(buffer, { headers: this.raw.headers }).formData();
193
+ } catch (e) {
194
+ throw this._err(`Failed to parse form data: ${messageOf(e)}`, "PARSE", { cause: e });
195
+ }
196
+ }
197
+ getBody() {
198
+ if (this.raw.bodyUsed) throw this._unreadable("Response body already consumed");
199
+ clearTimeout(this._timeout?.timer);
200
+ return this.raw.body;
201
+ }
202
+ getJson(schema) {
203
+ this._json ??= this.getText().then((text) => {
204
+ if (!text.trim()) return null;
205
+ let data;
206
+ try {
207
+ data = JSON.parse(text);
208
+ } catch (e) {
209
+ throw this._err(`Invalid JSON response: ${messageOf(e)}`, "PARSE", {
210
+ body: text,
211
+ cause: e
212
+ });
213
+ }
214
+ const errors = this._gqlThrow ? data?.errors : void 0;
215
+ if (Array.isArray(errors) && errors.length) {
216
+ const messages = errors.map((e) => {
217
+ const message = e?.message ?? e;
218
+ return typeof message === "string" ? message : JSON.stringify(message);
219
+ });
220
+ throw this._err(`GraphQL error: ${messages.join("; ")}`, "GRAPHQL", { body: text });
221
+ }
222
+ return data;
223
+ });
224
+ return schema ? this._json.then((data) => this._validate(schema, data)) : this._json;
225
+ }
226
+ async getData(schemaOrSelector, selector) {
227
+ const schema = isSchema(schemaOrSelector) ? schemaOrSelector : void 0;
228
+ const select = schema ? selector : schemaOrSelector;
229
+ const data = await this.getJson(schema);
230
+ if (!select) return data;
231
+ try {
232
+ return select(data);
233
+ } catch (e) {
234
+ throw this._err(`Selector failed: ${messageOf(e)}`, "PARSE", { cause: e });
235
+ }
236
+ }
237
+ };
238
+
239
+ //#endregion
240
+ //#region src/request.ts
241
+ const RETRY_STATUSES = [
242
+ 408,
243
+ 425,
244
+ 429,
245
+ 500,
246
+ 502,
247
+ 503,
248
+ 504
249
+ ];
250
+ var HttpRequest = class HttpRequest {
251
+ method;
252
+ _o = {
253
+ init: {},
254
+ headers: {},
255
+ query: new URLSearchParams(),
256
+ signals: [],
257
+ req: [],
258
+ res: [],
259
+ err: []
260
+ };
261
+ _url;
262
+ constructor(method, url) {
263
+ this.method = method;
264
+ this._url = url;
265
+ }
266
+ get url() {
267
+ const query = this._o.query.toString();
268
+ if (!query) return this._url;
269
+ const hashAt = this._url.indexOf("#");
270
+ const base = hashAt < 0 ? this._url : this._url.slice(0, hashAt);
271
+ return `${base}${base.includes("?") ? "&" : "?"}${query}${hashAt < 0 ? "" : this._url.slice(hashAt)}`;
272
+ }
273
+ _fail(message, code, extra) {
274
+ return new RequestError(message, {
275
+ url: this.url,
276
+ method: this.method,
277
+ ...extra,
278
+ code
279
+ });
280
+ }
281
+ _set(key, value) {
282
+ this._o.init[key] = value;
283
+ return this;
284
+ }
285
+ withHeaders(headers) {
286
+ for (const [name, value] of Object.entries(headers)) {
287
+ const key = name.toLowerCase();
288
+ if (value == null) delete this._o.headers[key];
289
+ else this._o.headers[key] = String(value);
290
+ }
291
+ return this;
292
+ }
293
+ withHeader(name, value) {
294
+ return this.withHeaders({ [name]: value });
295
+ }
296
+ withContentType(contentType) {
297
+ return this.withHeader("content-type", contentType);
298
+ }
299
+ withAuthorization(value) {
300
+ return this.withHeader("authorization", value);
301
+ }
302
+ withBearerToken(token) {
303
+ return this.withAuthorization(`Bearer ${token}`);
304
+ }
305
+ withBasicAuth(username, password) {
306
+ return this.withAuthorization(`Basic ${btoa(String.fromCharCode(...new TextEncoder().encode(`${username}:${password}`)))}`);
307
+ }
308
+ withCookies(cookies) {
309
+ for (const [name, value] of Object.entries(cookies)) {
310
+ const previous = this._o.headers["cookie"];
311
+ this.withHeader("cookie", `${previous ? `${previous}; ` : ""}${name}=${value}`);
312
+ }
313
+ return this;
314
+ }
315
+ withCookie(name, value) {
316
+ return this.withCookies({ [name]: value });
317
+ }
318
+ withCsrf(options = {}) {
319
+ this._o.csrf = options;
320
+ return this;
321
+ }
322
+ withCsrfToken(token, header = "X-CSRF-Token") {
323
+ return this.withHeader(header, token);
324
+ }
325
+ withQueryParams(params) {
326
+ const entries = params instanceof URLSearchParams ? [...params] : Object.entries(params);
327
+ for (const [key] of entries) this._o.query.delete(key);
328
+ for (const [key, value] of entries) for (const item of Array.isArray(value) ? value : [value]) if (item != null) this._o.query.append(key, item instanceof Date ? item.toISOString() : String(item));
329
+ return this;
330
+ }
331
+ withQueryParam(key, value) {
332
+ return this.withQueryParams({ [key]: value });
333
+ }
334
+ withTimeout(ms) {
335
+ if (!(ms >= 0)) throw this._fail(`Invalid timeout: ${ms}`, "VALIDATION");
336
+ this._o.timeout = ms > 0 && ms <= MAX_DELAY ? ms : void 0;
337
+ return this;
338
+ }
339
+ withRetries(retries) {
340
+ const config = typeof retries === "number" ? { attempts: retries } : retries;
341
+ if (!(Number.isInteger(config.attempts) && config.attempts >= 0)) throw this._fail(`Invalid retry attempts: ${config.attempts}`, "VALIDATION");
342
+ this._o.retry = {
343
+ ...this._o.retry,
344
+ ...config
345
+ };
346
+ return this;
347
+ }
348
+ onRetry(callback) {
349
+ this._o.retry = {
350
+ attempts: 0,
351
+ ...this._o.retry,
352
+ onRetry: callback
353
+ };
354
+ return this;
355
+ }
356
+ withSignal(signal) {
357
+ this._o.signals.push(signal);
358
+ return this;
359
+ }
360
+ withAbortController(controller) {
361
+ return this.withSignal(controller.signal);
362
+ }
363
+ withFetch(fetchFn) {
364
+ this._o.fetch = fetchFn;
365
+ return this;
366
+ }
367
+ withCredentials(credentials) {
368
+ return this._set("credentials", credentials);
369
+ }
370
+ withMode(mode) {
371
+ return this._set("mode", mode);
372
+ }
373
+ withRedirect(redirect) {
374
+ return this._set("redirect", redirect);
375
+ }
376
+ withReferrer(referrer) {
377
+ return this._set("referrer", referrer);
378
+ }
379
+ withReferrerPolicy(policy) {
380
+ return this._set("referrerPolicy", policy);
381
+ }
382
+ withPriority(priority) {
383
+ return this._set("priority", priority);
384
+ }
385
+ withKeepAlive(keepalive = true) {
386
+ return this._set("keepalive", keepalive);
387
+ }
388
+ withIntegrity(integrity) {
389
+ return this._set("integrity", integrity);
390
+ }
391
+ withCache(cache) {
392
+ return this._set("cache", cache);
393
+ }
394
+ withRequestInterceptor(interceptor) {
395
+ this._o.req.push(interceptor);
396
+ return this;
397
+ }
398
+ withResponseInterceptor(interceptor) {
399
+ this._o.res.push(interceptor);
400
+ return this;
401
+ }
402
+ withErrorInterceptor(interceptor) {
403
+ this._o.err.push(interceptor);
404
+ return this;
405
+ }
406
+ withBody(body) {
407
+ const o = this._o;
408
+ const tag = Object.prototype.toString.call(body).slice(8, -1);
409
+ const raw = ArrayBuffer.isView(body) || /^(String|Blob|File|FormData|URLSearchParams|ArrayBuffer|ReadableStream)$/.test(tag);
410
+ o.stream = tag === "ReadableStream";
411
+ if (raw) o.body = body;
412
+ else try {
413
+ o.body = JSON.stringify(body);
414
+ } catch (e) {
415
+ throw this._fail(`Body is not JSON-serializable: ${messageOf(e)}`, "VALIDATION", { cause: e });
416
+ }
417
+ if (tag === "FormData") delete o.headers["content-type"];
418
+ else if (!("content-type" in o.headers) && (!raw || tag === "String")) this.withContentType(raw ? "text/plain" : "application/json");
419
+ return this;
420
+ }
421
+ withGraphQL(query, variables, options) {
422
+ this._o.gqlThrow = options?.throwOnError;
423
+ return this.withBody({
424
+ query,
425
+ variables
426
+ });
427
+ }
428
+ clone() {
429
+ const o = this._o;
430
+ const copy = new HttpRequest(this.method, this._url);
431
+ copy._o = {
432
+ ...o,
433
+ init: { ...o.init },
434
+ headers: { ...o.headers },
435
+ query: new URLSearchParams(o.query),
436
+ signals: [...o.signals],
437
+ req: [...o.req],
438
+ res: [...o.res],
439
+ err: [...o.err]
440
+ };
441
+ return copy;
442
+ }
443
+ async getResponse() {
444
+ const o = this._o;
445
+ const retry = o.retry;
446
+ let error;
447
+ for (let attempt = 0;; attempt++) try {
448
+ return await this._attempt();
449
+ } catch (e) {
450
+ error = e instanceof RequestError ? e : this._fail(`Unexpected error: ${messageOf(e)}`, "NETWORK", { cause: e });
451
+ const context = {
452
+ attempt: attempt + 1,
453
+ error
454
+ };
455
+ if (attempt >= (retry?.attempts ?? 0)) break;
456
+ try {
457
+ if (!await this._retriable(context)) break;
458
+ const maxDelay = retry.maxDelay ?? 3e4;
459
+ const serverDelay = retry.delay === void 0 ? retryAfter(error.response) : void 0;
460
+ if (serverDelay > maxDelay) break;
461
+ const delay = serverDelay ?? (typeof retry.delay === "function" ? retry.delay(context) : retry.delay ?? Math.min(300 * 2 ** attempt + Math.random() * 100, maxDelay));
462
+ await retry.onRetry?.({
463
+ ...context,
464
+ delay
465
+ });
466
+ release(error.response?.body);
467
+ await sleep(delay, anySignal(o.signals));
468
+ } catch (e) {
469
+ error = this._fail(`Retry callback failed: ${messageOf(e)}`, "INTERCEPTOR", {
470
+ ...error,
471
+ cause: e
472
+ });
473
+ break;
474
+ }
475
+ }
476
+ for (const interceptor of o.err) try {
477
+ const result = await interceptor(error, this);
478
+ if (result instanceof ResponseWrapper) return result;
479
+ if (result) error = result;
480
+ } catch (e) {
481
+ error = e instanceof RequestError ? e : this._fail(`Error interceptor failed: ${messageOf(e)}`, "INTERCEPTOR", {
482
+ ...error,
483
+ cause: e
484
+ });
485
+ }
486
+ throw error;
487
+ }
488
+ async _retriable(context) {
489
+ const o = this._o;
490
+ const retry = o.retry;
491
+ const { code, status } = context.error;
492
+ if (code === "ABORTED" || o.stream || o.signals.some((signal) => signal.aborted)) return false;
493
+ if (retry.shouldRetry) return retry.shouldRetry(context);
494
+ if (retry.methods && !retry.methods.includes(this.method)) return false;
495
+ return code === "NETWORK" || code === "TIMEOUT" || code === "HTTP" && (retry.statuses ?? RETRY_STATUSES).includes(status);
496
+ }
497
+ async _attempt() {
498
+ const o = this._o;
499
+ const method = this.method;
500
+ let config = {
501
+ ...o.init,
502
+ url: this.url,
503
+ method,
504
+ headers: { ...o.headers },
505
+ body: o.body,
506
+ signal: anySignal(o.signals)
507
+ };
508
+ if (o.stream) config.duplex = "half";
509
+ const fail = (message, code, extra) => new RequestError(message, {
510
+ code,
511
+ url: config.url,
512
+ method,
513
+ ...extra
514
+ });
515
+ const early = abortError(config.signal, void 0);
516
+ if (early) throw fail(early[1], early[0], { cause: config.signal.reason });
517
+ let response;
518
+ for (const interceptor of o.req) {
519
+ let result;
520
+ try {
521
+ result = await interceptor(config);
522
+ } catch (e) {
523
+ throw fail(`Request interceptor failed: ${messageOf(e)}`, "INTERCEPTOR", { cause: e });
524
+ }
525
+ if (result instanceof Response) {
526
+ response = result;
527
+ break;
528
+ }
529
+ if (result) config = result;
530
+ }
531
+ let deadline;
532
+ let signal = config.signal;
533
+ if (!response) {
534
+ if (!validUrl(config.url)) throw fail(`Invalid URL: "${config.url}"`, "VALIDATION");
535
+ try {
536
+ this._csrf(config);
537
+ } catch (e) {
538
+ throw fail(`CSRF token callback failed: ${messageOf(e)}`, "INTERCEPTOR", { cause: e });
539
+ }
540
+ try {
541
+ new Headers(config.headers);
542
+ } catch (e) {
543
+ throw fail(`Invalid header: ${messageOf(e)}`, "VALIDATION", { cause: e });
544
+ }
545
+ if (o.timeout) {
546
+ const controller = new AbortController();
547
+ deadline = {
548
+ ms: o.timeout,
549
+ controller,
550
+ timer: setTimeout(() => controller.abort(), o.timeout)
551
+ };
552
+ }
553
+ const { url, ...init } = config;
554
+ init.signal = signal = anySignal([config.signal, deadline?.controller.signal]);
555
+ try {
556
+ response = await (o.fetch ?? fetch)(url, init);
557
+ } catch (e) {
558
+ clearTimeout(deadline?.timer);
559
+ const aborted = abortError(signal, deadline);
560
+ if (aborted) throw fail(aborted[1], aborted[0], { cause: e });
561
+ const cause = e?.cause;
562
+ const detail = cause && (messageOf(cause) || cause.code);
563
+ throw fail(`Network error: ${messageOf(e)}${detail ? ` (${detail})` : ""}`, "NETWORK", { cause: e });
564
+ }
565
+ }
566
+ const manualRedirect = config.redirect === "manual" && response.status >= 300 && response.status < 400;
567
+ if (!response.ok && !manualRedirect && response.type !== "opaque" && response.type !== "opaqueredirect") {
568
+ const body = response.bodyUsed || +response.headers.get("content-length") > 1e6 ? void 0 : await readCapped(response.body, 1e6);
569
+ clearTimeout(deadline?.timer);
570
+ throw fail(`HTTP ${response.status} ${response.statusText}`.trim(), "HTTP", {
571
+ status: response.status,
572
+ response,
573
+ body
574
+ });
575
+ }
576
+ if (!response.body) clearTimeout(deadline?.timer);
577
+ const arm = (wrapper) => {
578
+ wrapper._timeout ??= deadline;
579
+ wrapper._signal ??= signal;
580
+ wrapper._gqlThrow ??= o.gqlThrow;
581
+ return wrapper;
582
+ };
583
+ let wrapped = arm(new ResponseWrapper(response, config.url, method));
584
+ for (const interceptor of o.res) try {
585
+ const result = await interceptor(wrapped, this);
586
+ if (result && result.raw !== response) {
587
+ clearTimeout(deadline?.timer);
588
+ release(response.body);
589
+ }
590
+ wrapped = arm(result ?? wrapped);
591
+ } catch (e) {
592
+ clearTimeout(deadline?.timer);
593
+ throw fail(`Response interceptor failed: ${messageOf(e)}`, "INTERCEPTOR", {
594
+ status: wrapped.status,
595
+ response: wrapped.raw,
596
+ cause: e
597
+ });
598
+ }
599
+ return wrapped;
600
+ }
601
+ _csrf(config) {
602
+ const csrf = this._o.csrf;
603
+ if (!csrf || !(csrf.crossOrigin || sameOrigin(config.url))) return;
604
+ const fromToken = csrf.token !== void 0;
605
+ const token = fromToken ? typeof csrf.token === "function" ? csrf.token() : csrf.token : readCookie(csrf.cookie ?? "XSRF-TOKEN");
606
+ const header = (csrf.header ?? (fromToken ? "X-CSRF-Token" : "X-XSRF-TOKEN")).toLowerCase();
607
+ if (token && !(header in config.headers)) config.headers[header] = token;
608
+ }
609
+ getJson(schema) {
610
+ return this.getResponse().then((response) => response.getJson(schema));
611
+ }
612
+ getText() {
613
+ return this.getResponse().then((response) => response.getText());
614
+ }
615
+ getBlob() {
616
+ return this.getResponse().then((response) => response.getBlob());
617
+ }
618
+ getArrayBuffer() {
619
+ return this.getResponse().then((response) => response.getArrayBuffer());
620
+ }
621
+ getFormData() {
622
+ return this.getResponse().then((response) => response.getFormData());
623
+ }
624
+ getBody() {
625
+ return this.getResponse().then((response) => response.getBody());
626
+ }
627
+ getData(schemaOrSelector, selector) {
628
+ return this.getResponse().then((response) => response.getData(schemaOrSelector, selector));
629
+ }
630
+ async getResult(schema) {
631
+ try {
632
+ return {
633
+ data: await this.getJson(schema),
634
+ error: null
635
+ };
636
+ } catch (error) {
637
+ return {
638
+ data: null,
639
+ error
640
+ };
641
+ }
642
+ }
643
+ };
644
+
645
+ //#endregion
646
+ //#region src/api.ts
647
+ const ABSOLUTE = /^([a-z][a-z0-9+.-]*:)?\/\//i;
648
+ var Api = class Api {
649
+ _base;
650
+ _defaults;
651
+ constructor(_base = "", _defaults = []) {
652
+ this._base = _base;
653
+ this._defaults = _defaults;
654
+ }
655
+ _with(fn) {
656
+ fn(new HttpRequest("GET", ""));
657
+ return new Api(this._base, [...this._defaults, fn]);
658
+ }
659
+ withBaseURL(baseURL) {
660
+ return new Api(baseURL, this._defaults);
661
+ }
662
+ _make(method, path = "") {
663
+ const base = this._base;
664
+ const url = !base ? path : !path ? base : ABSOLUTE.test(path) ? path : `${base.replace(/\/+$/, "")}/${path.replace(/^\.?\/+/, "")}`;
665
+ const request = new HttpRequest(method, url);
666
+ for (const apply of this._defaults) apply(request);
667
+ return request;
668
+ }
669
+ };
670
+ const METHODS = [
671
+ "GET",
672
+ "HEAD",
673
+ "OPTIONS",
674
+ "POST",
675
+ "PUT",
676
+ "PATCH",
677
+ "DELETE"
678
+ ];
679
+ let installed = false;
680
+ function createApi() {
681
+ if (!installed) {
682
+ installed = true;
683
+ const proto = Api.prototype;
684
+ for (const method of METHODS) proto[method.toLowerCase()] = function(path) {
685
+ return this._make(method, path);
686
+ };
687
+ proto["del"] = proto["delete"];
688
+ for (const key of Object.getOwnPropertyNames(HttpRequest.prototype)) if (/^(with|onRetry)/.test(key) && !/^with(Body|GraphQL|Signal|AbortController)$/.test(key)) proto[key] = function(...args) {
689
+ return this._with((request) => void request[key](...args));
690
+ };
691
+ }
692
+ return new Api();
693
+ }
694
+
695
+ //#endregion
696
+ //#region src/index.ts
697
+ const createGet = (url) => new HttpRequest("GET", url);
698
+ const createHead = (url) => new HttpRequest("HEAD", url);
699
+ const createOptions = (url) => new HttpRequest("OPTIONS", url);
700
+ const createPost = (url) => new HttpRequest("POST", url);
701
+ const createPut = (url) => new HttpRequest("PUT", url);
702
+ const createPatch = (url) => new HttpRequest("PATCH", url);
703
+ const createDelete = (url) => new HttpRequest("DELETE", url);
704
+ const create = {
705
+ get: createGet,
706
+ head: createHead,
707
+ options: createOptions,
708
+ post: createPost,
709
+ put: createPut,
710
+ patch: createPatch,
711
+ delete: createDelete,
712
+ del: createDelete,
713
+ api: createApi
714
+ };
715
+
716
+ //#endregion
717
+ export { HttpRequest, RequestError, ResponseWrapper, createApi, createDelete, createGet, createHead, createOptions, createPatch, createPost, createPut, create as default, isRequestError };