create-request 1.6.0 → 1.6.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.
@@ -3,98 +3,99 @@
3
3
  /**
4
4
  * Enum for HTTP methods
5
5
  */
6
- exports.HttpMethod = void 0;
7
- (function (HttpMethod) {
8
- HttpMethod["GET"] = "GET";
9
- HttpMethod["PUT"] = "PUT";
10
- HttpMethod["POST"] = "POST";
11
- HttpMethod["HEAD"] = "HEAD";
12
- HttpMethod["PATCH"] = "PATCH";
13
- HttpMethod["DELETE"] = "DELETE";
14
- HttpMethod["OPTIONS"] = "OPTIONS";
15
- })(exports.HttpMethod || (exports.HttpMethod = {}));
6
+ const HttpMethod = {
7
+ GET: "GET",
8
+ PUT: "PUT",
9
+ POST: "POST",
10
+ HEAD: "HEAD",
11
+ PATCH: "PATCH",
12
+ DELETE: "DELETE",
13
+ OPTIONS: "OPTIONS",
14
+ };
16
15
  /**
17
16
  * Enum for request priorities
18
17
  */
19
- exports.RequestPriority = void 0;
20
- (function (RequestPriority) {
21
- RequestPriority["LOW"] = "low";
22
- RequestPriority["HIGH"] = "high";
23
- RequestPriority["AUTO"] = "auto";
24
- })(exports.RequestPriority || (exports.RequestPriority = {}));
18
+ const RequestPriority = {
19
+ LOW: "low",
20
+ HIGH: "high",
21
+ AUTO: "auto",
22
+ };
25
23
  /**
26
24
  * Enum for credentials policies
27
25
  */
28
- exports.CredentialsPolicy = void 0;
29
- (function (CredentialsPolicy) {
30
- CredentialsPolicy["OMIT"] = "omit";
31
- CredentialsPolicy["INCLUDE"] = "include";
32
- CredentialsPolicy["SAME_ORIGIN"] = "same-origin";
33
- })(exports.CredentialsPolicy || (exports.CredentialsPolicy = {}));
26
+ const CredentialsPolicy = {
27
+ OMIT: "omit",
28
+ INCLUDE: "include",
29
+ SAME_ORIGIN: "same-origin",
30
+ };
34
31
  /**
35
32
  * Enum for request modes
36
33
  */
37
- exports.RequestMode = void 0;
38
- (function (RequestMode) {
39
- RequestMode["CORS"] = "cors";
40
- RequestMode["NO_CORS"] = "no-cors";
41
- RequestMode["SAME_ORIGIN"] = "same-origin";
42
- RequestMode["NAVIGATE"] = "navigate";
43
- })(exports.RequestMode || (exports.RequestMode = {}));
34
+ const RequestMode = {
35
+ CORS: "cors",
36
+ NO_CORS: "no-cors",
37
+ SAME_ORIGIN: "same-origin",
38
+ NAVIGATE: "navigate",
39
+ };
44
40
  /**
45
41
  * Enum for redirect modes
46
42
  */
47
- exports.RedirectMode = void 0;
48
- (function (RedirectMode) {
49
- RedirectMode["ERROR"] = "error";
50
- RedirectMode["FOLLOW"] = "follow";
51
- RedirectMode["MANUAL"] = "manual";
52
- })(exports.RedirectMode || (exports.RedirectMode = {}));
43
+ const RedirectMode = {
44
+ ERROR: "error",
45
+ FOLLOW: "follow",
46
+ MANUAL: "manual",
47
+ };
53
48
  /**
54
49
  * Enum for cookie SameSite policies
55
50
  */
56
- exports.SameSitePolicy = void 0;
57
- (function (SameSitePolicy) {
58
- SameSitePolicy["LAX"] = "Lax";
59
- SameSitePolicy["NONE"] = "None";
60
- SameSitePolicy["STRICT"] = "Strict";
61
- })(exports.SameSitePolicy || (exports.SameSitePolicy = {}));
51
+ const SameSitePolicy = {
52
+ LAX: "Lax",
53
+ NONE: "None",
54
+ STRICT: "Strict",
55
+ };
62
56
  /**
63
57
  * Enum for body types
64
58
  */
65
- var BodyType;
66
- (function (BodyType) {
67
- BodyType["JSON"] = "json";
68
- BodyType["STRING"] = "string";
69
- BodyType["BINARY"] = "binary";
70
- })(BodyType || (BodyType = {}));
59
+ const BodyType = {
60
+ JSON: "json",
61
+ STRING: "string",
62
+ BINARY: "binary",
63
+ };
71
64
  /**
72
65
  * Referrer policies for fetch requests
73
66
  */
74
- exports.ReferrerPolicy = void 0;
75
- (function (ReferrerPolicy) {
76
- ReferrerPolicy["ORIGIN"] = "origin";
77
- ReferrerPolicy["UNSAFE_URL"] = "unsafe-url";
78
- ReferrerPolicy["SAME_ORIGIN"] = "same-origin";
79
- ReferrerPolicy["NO_REFERRER"] = "no-referrer";
80
- ReferrerPolicy["STRICT_ORIGIN"] = "strict-origin";
81
- ReferrerPolicy["ORIGIN_WHEN_CROSS_ORIGIN"] = "origin-when-cross-origin";
82
- ReferrerPolicy["NO_REFERRER_WHEN_DOWNGRADE"] = "no-referrer-when-downgrade";
83
- ReferrerPolicy["STRICT_ORIGIN_WHEN_CROSS_ORIGIN"] = "strict-origin-when-cross-origin";
84
- })(exports.ReferrerPolicy || (exports.ReferrerPolicy = {}));
67
+ const ReferrerPolicy = {
68
+ ORIGIN: "origin",
69
+ UNSAFE_URL: "unsafe-url",
70
+ SAME_ORIGIN: "same-origin",
71
+ NO_REFERRER: "no-referrer",
72
+ STRICT_ORIGIN: "strict-origin",
73
+ ORIGIN_WHEN_CROSS_ORIGIN: "origin-when-cross-origin",
74
+ NO_REFERRER_WHEN_DOWNGRADE: "no-referrer-when-downgrade",
75
+ STRICT_ORIGIN_WHEN_CROSS_ORIGIN: "strict-origin-when-cross-origin",
76
+ };
85
77
  /**
86
78
  * Cache modes for fetch requests
87
79
  */
88
- exports.CacheMode = void 0;
89
- (function (CacheMode) {
90
- CacheMode["RELOAD"] = "reload";
91
- CacheMode["DEFAULT"] = "default";
92
- CacheMode["NO_CACHE"] = "no-cache";
93
- CacheMode["NO_STORE"] = "no-store";
94
- CacheMode["FORCE_CACHE"] = "force-cache";
95
- CacheMode["ONLY_IF_CACHED"] = "only-if-cached";
96
- })(exports.CacheMode || (exports.CacheMode = {}));
80
+ const CacheMode = {
81
+ RELOAD: "reload",
82
+ DEFAULT: "default",
83
+ NO_CACHE: "no-cache",
84
+ NO_STORE: "no-store",
85
+ FORCE_CACHE: "force-cache",
86
+ ONLY_IF_CACHED: "only-if-cached",
87
+ };
97
88
 
89
+ /**
90
+ * Extract a message from an unknown thrown value
91
+ * @internal
92
+ */
93
+ const errorMessage = (e) => (e instanceof Error ? e.message : String(e));
94
+ /**
95
+ * Coerce an unknown thrown value to an Error
96
+ * @internal
97
+ */
98
+ const toError = (e) => (e instanceof Error ? e : new Error(String(e)));
98
99
  /**
99
100
  * Error class for HTTP request failures.
100
101
  * Extends the standard Error class with additional context about the failed request.
@@ -135,7 +136,7 @@ class RequestError extends Error {
135
136
  /** Whether the request was aborted (cancelled) */
136
137
  isAborted;
137
138
  /** Cached result of parsing `body` as JSON (lazily populated by getJson) */
138
- parsedBody;
139
+ _parsed;
139
140
  /**
140
141
  * Creates a new RequestError instance.
141
142
  *
@@ -188,15 +189,15 @@ class RequestError extends Error {
188
189
  * ```
189
190
  */
190
191
  getJson() {
191
- if (this.parsedBody === undefined && this.body) {
192
+ if (this._parsed === undefined && this.body) {
192
193
  try {
193
- this.parsedBody = JSON.parse(this.body);
194
+ this._parsed = JSON.parse(this.body);
194
195
  }
195
196
  catch {
196
197
  // Body is not valid JSON - leave parsedBody undefined
197
198
  }
198
199
  }
199
- return this.parsedBody;
200
+ return this._parsed;
200
201
  }
201
202
  /**
202
203
  * Safely reads the body of a Response as text without consuming it.
@@ -292,55 +293,29 @@ class RequestError extends Error {
292
293
  let message = originalError.message;
293
294
  // Check for Node.js error codes (e.g., from undici/dns errors)
294
295
  const errorCode = originalError.code;
295
- const errorName = originalError.name;
296
296
  const stack = originalError.stack || "";
297
- const errorMessageLower = message.toLowerCase();
298
297
  // Check for timeout errors (Node.js/undici TimeoutError)
299
298
  // Note: While explicit timeouts set via withTimeout() are handled in BaseRequest,
300
- // this detection serves as a safety net for:
301
- // 1. Timeout errors from external AbortControllers (e.g., AbortSignal.timeout())
302
- // 2. Different runtime implementations that may throw timeout errors differently
303
- // 3. Network-level timeouts (ETIMEDOUT)
304
- const isTimeoutError = errorName === "TimeoutError" ||
305
- errorMessageLower.includes("timeout") ||
306
- errorMessageLower.includes("aborted due to timeout") ||
299
+ // this detection serves as a safety net for timeout errors from external
300
+ // AbortControllers, other runtimes, and network-level timeouts (ETIMEDOUT).
301
+ const isTimeoutError = originalError.name === "TimeoutError" ||
302
+ message.toLowerCase().includes("timeout") ||
307
303
  errorCode === "ETIMEDOUT" ||
308
304
  stack.includes("TimeoutError") ||
309
305
  stack.includes("timeout");
310
306
  // If the error message is generic "fetch failed", provide more context
311
307
  if (message === "fetch failed" || message === "Failed to fetch") {
312
308
  // Check for DNS resolution errors
313
- const isDnsError = errorCode === "ENOTFOUND" ||
314
- errorCode === "EAI_AGAIN" ||
315
- errorCode === "EAI_NODATA" ||
316
- stack.includes("getaddrinfo") ||
317
- stack.includes("ENOTFOUND") ||
318
- stack.includes("EAI_AGAIN");
309
+ const isDnsError = errorCode === "ENOTFOUND" || errorCode === "EAI_AGAIN" || errorCode === "EAI_NODATA" || /getaddrinfo|ENOTFOUND|EAI_AGAIN/.test(stack);
319
310
  // Check for connection errors (but not timeout errors)
320
311
  const isConnectionError = !isTimeoutError && (errorCode === "ECONNREFUSED" || errorCode === "ECONNRESET" || stack.includes("ECONNREFUSED") || stack.includes("connect"));
321
- if (isTimeoutError) {
322
- message = `Timeout:${url}`;
323
- }
324
- else if (isDnsError) {
325
- message = `DNS:${url}`;
326
- }
327
- else if (isConnectionError) {
328
- message = `Conn:${url}`;
329
- }
330
- else {
331
- message = `Net:${url}`;
332
- }
312
+ message = (isTimeoutError ? "Timeout:" : isDnsError ? "DNS:" : isConnectionError ? "Conn:" : "Net:") + url;
333
313
  }
334
- const error = new RequestError(message, url, method, {
335
- ...(isTimeoutError ? { isTimeout: true } : {}),
336
- });
337
- // Create a proper RequestError stack trace, but append the original stack for debugging
338
- // This way Node.js will show "RequestError: ..." instead of "TypeError: ..."
314
+ const error = new RequestError(message, url, method, isTimeoutError ? { isTimeout: true } : {});
315
+ // Create a proper RequestError stack trace, but append the original stack for
316
+ // debugging context, so Node.js shows "RequestError: ..." instead of "TypeError: ..."
339
317
  if (originalError.stack) {
340
- // Get the current stack (which will start with RequestError)
341
- const currentStack = error.stack || "";
342
- // Append the original error's stack as "Caused by:" for debugging context
343
- error.stack = `${currentStack}\n\nCaused by: ${originalError.stack}`;
318
+ error.stack = `${error.stack || ""}\n\nCaused by: ${originalError.stack}`;
344
319
  }
345
320
  return error;
346
321
  }
@@ -384,19 +359,19 @@ class ResponseWrapper {
384
359
  url;
385
360
  /** The HTTP method that was used (if available) */
386
361
  method;
387
- response;
388
- graphQLOptions;
362
+ _res;
363
+ _gqlOpts;
389
364
  // Cache the body as the last used method
390
- cachedBlob;
391
- cachedText;
392
- cachedJson;
393
- cachedArrayBuffer;
365
+ _blob;
366
+ _text;
367
+ _json;
368
+ _buf;
394
369
  constructor(response, url, method, graphQLOptions) {
395
- this.response = response;
370
+ this._res = response;
396
371
  this.url = url;
397
372
  this.method = method;
398
373
  if (graphQLOptions) {
399
- this.graphQLOptions = {
374
+ this._gqlOpts = {
400
375
  throwOnError: graphQLOptions.throwOnError,
401
376
  };
402
377
  }
@@ -405,43 +380,65 @@ class ResponseWrapper {
405
380
  * HTTP status code (e.g., 200, 404, 500)
406
381
  */
407
382
  get status() {
408
- return this.response.status;
383
+ return this._res.status;
409
384
  }
410
385
  /**
411
386
  * HTTP status text (e.g., "OK", "Not Found", "Internal Server Error")
412
387
  */
413
388
  get statusText() {
414
- return this.response.statusText;
389
+ return this._res.statusText;
415
390
  }
416
391
  /**
417
392
  * Response headers as a Headers object
418
393
  */
419
394
  get headers() {
420
- return this.response.headers;
395
+ return this._res.headers;
421
396
  }
422
397
  /**
423
398
  * Whether the response status is in the 200-299 range (successful)
424
399
  */
425
400
  get ok() {
426
- return this.response.ok;
401
+ return this._res.ok;
427
402
  }
428
403
  /**
429
404
  * The raw Response object from the fetch API.
430
405
  * Use this if you need direct access to the underlying Response.
431
406
  */
432
407
  get raw() {
433
- return this.response;
408
+ return this._res;
409
+ }
410
+ /**
411
+ * Create a RequestError carrying this response's context
412
+ * @param message - The error message
413
+ * @param withBody - Whether to attach the cached body text to the error
414
+ */
415
+ _err(message, withBody) {
416
+ return new RequestError(message, this.url || "", this.method || "", {
417
+ status: this._res.status,
418
+ response: this._res,
419
+ body: withBody ? this._text : undefined,
420
+ });
421
+ }
422
+ /**
423
+ * Read the response body via the given reader, wrapping failures in a RequestError
424
+ * @throws RequestError if the body has already been consumed or reading fails
425
+ */
426
+ async _read(reader) {
427
+ this._checkUsed();
428
+ try {
429
+ return await reader();
430
+ }
431
+ catch (e) {
432
+ throw this._err(`Read: ${errorMessage(e)}`);
433
+ }
434
434
  }
435
435
  /**
436
436
  * Check if the response body has already been consumed and throw an error if so
437
437
  * @throws RequestError if the body has already been consumed
438
438
  */
439
- checkBodyNotConsumed() {
440
- if (this.response.bodyUsed) {
441
- throw new RequestError("Body used", this.url || "", this.method || "", {
442
- status: this.response.status,
443
- response: this.response,
444
- });
439
+ _checkUsed() {
440
+ if (this._res.bodyUsed) {
441
+ throw this._err("Body used");
445
442
  }
446
443
  }
447
444
  /**
@@ -449,8 +446,8 @@ class ResponseWrapper {
449
446
  * @param data - The parsed JSON data
450
447
  * @throws RequestError if GraphQL response contains errors and throwOnError is enabled
451
448
  */
452
- checkGraphQLErrors(data) {
453
- if (!this.graphQLOptions?.throwOnError || typeof data !== "object" || data === null)
449
+ _checkGql(data) {
450
+ if (!this._gqlOpts?.throwOnError || typeof data !== "object" || data === null)
454
451
  return;
455
452
  const responseData = data;
456
453
  if (!Array.isArray(responseData.errors) || responseData.errors.length === 0)
@@ -479,12 +476,7 @@ class ResponseWrapper {
479
476
  }
480
477
  return String(x);
481
478
  });
482
- const errorMessage = errorMessages.join(", ");
483
- throw new RequestError(`GQL: ${errorMessage}`, this.url || "", this.method || "", {
484
- status: this.response.status,
485
- response: this.response,
486
- body: this.cachedText,
487
- });
479
+ throw this._err(`GQL: ${errorMessages.join(", ")}`, true);
488
480
  }
489
481
  /**
490
482
  * Parse the response body as JSON
@@ -513,39 +505,35 @@ class ResponseWrapper {
513
505
  * }
514
506
  */
515
507
  async getJson() {
516
- if (this.cachedJson !== undefined)
517
- return this.cachedJson;
508
+ if (this._json !== undefined)
509
+ return this._json;
518
510
  // Handle empty responses: 204 No Content or content-length: 0
519
- const contentLength = this.response.headers.get("content-length");
520
- if (this.response.status === 204 || contentLength === "0") {
521
- this.cachedJson = null;
511
+ const contentLength = this._res.headers.get("content-length");
512
+ if (this._res.status === 204 || contentLength === "0") {
513
+ this._json = null;
522
514
  return null;
523
515
  }
524
- this.checkBodyNotConsumed();
516
+ this._checkUsed();
525
517
  try {
526
518
  // Read as text first to handle empty bodies and cache for getText()
527
- const text = await this.response.text();
528
- this.cachedText = text;
519
+ const text = await this._res.text();
520
+ this._text = text;
529
521
  // Handle empty or whitespace-only responses
530
522
  if (!text || text.trim() === "") {
531
- this.cachedJson = null;
523
+ this._json = null;
532
524
  return null;
533
525
  }
534
526
  // Parse the text as JSON
535
527
  const parsed = JSON.parse(text);
536
- this.cachedJson = parsed;
537
- this.checkGraphQLErrors(parsed);
528
+ this._json = parsed;
529
+ this._checkGql(parsed);
538
530
  return parsed;
539
531
  }
540
532
  catch (error) {
541
533
  if (error instanceof RequestError) {
542
534
  throw error;
543
535
  }
544
- throw new RequestError(`Bad JSON: ${error instanceof Error ? error.message : String(error)}`, this.url || "", this.method || "", {
545
- status: this.response.status,
546
- response: this.response,
547
- body: this.cachedText,
548
- });
536
+ throw this._err(`Bad JSON: ${errorMessage(error)}`, true);
549
537
  }
550
538
  }
551
539
  /**
@@ -562,20 +550,9 @@ class ResponseWrapper {
562
550
  * ```
563
551
  */
564
552
  async getText() {
565
- if (this.cachedText !== undefined)
566
- return this.cachedText;
567
- this.checkBodyNotConsumed();
568
- try {
569
- const text = await this.response.text();
570
- this.cachedText = text;
571
- return text;
572
- }
573
- catch (e) {
574
- throw new RequestError(`Read: ${e instanceof Error ? e.message : String(e)}`, this.url || "", this.method || "", {
575
- status: this.response.status,
576
- response: this.response,
577
- });
578
- }
553
+ if (this._text !== undefined)
554
+ return this._text;
555
+ return (this._text = await this._read(() => this._res.text()));
579
556
  }
580
557
  /**
581
558
  * Get the response body as a Blob.
@@ -593,20 +570,9 @@ class ResponseWrapper {
593
570
  * ```
594
571
  */
595
572
  async getBlob() {
596
- if (this.cachedBlob !== undefined)
597
- return this.cachedBlob;
598
- this.checkBodyNotConsumed();
599
- try {
600
- const blob = await this.response.blob();
601
- this.cachedBlob = blob;
602
- return blob;
603
- }
604
- catch (e) {
605
- throw new RequestError(`Read: ${e instanceof Error ? e.message : String(e)}`, this.url || "", this.method || "", {
606
- status: this.response.status,
607
- response: this.response,
608
- });
609
- }
573
+ if (this._blob !== undefined)
574
+ return this._blob;
575
+ return (this._blob = await this._read(() => this._res.blob()));
610
576
  }
611
577
  /**
612
578
  * Get the response body as an ArrayBuffer.
@@ -624,21 +590,10 @@ class ResponseWrapper {
624
590
  * ```
625
591
  */
626
592
  async getArrayBuffer() {
627
- if (this.cachedArrayBuffer !== undefined) {
628
- return this.cachedArrayBuffer;
629
- }
630
- this.checkBodyNotConsumed();
631
- try {
632
- const arrayBuffer = await this.response.arrayBuffer();
633
- this.cachedArrayBuffer = arrayBuffer;
634
- return arrayBuffer;
635
- }
636
- catch (e) {
637
- throw new RequestError(`Read: ${e instanceof Error ? e.message : String(e)}`, this.url || "", this.method || "", {
638
- status: this.response.status,
639
- response: this.response,
640
- });
593
+ if (this._buf !== undefined) {
594
+ return this._buf;
641
595
  }
596
+ return (this._buf = await this._read(() => this._res.arrayBuffer()));
642
597
  }
643
598
  /**
644
599
  * Get the raw response body as a ReadableStream
@@ -656,8 +611,8 @@ class ResponseWrapper {
656
611
  * }
657
612
  */
658
613
  getBody() {
659
- this.checkBodyNotConsumed();
660
- return this.response.body;
614
+ this._checkUsed();
615
+ return this._res.body;
661
616
  }
662
617
  /**
663
618
  * Extract specific data using a selector function
@@ -707,16 +662,11 @@ class ResponseWrapper {
707
662
  }
708
663
  // Enhance selector errors with context
709
664
  if (selector) {
710
- throw new RequestError(`Selector: ${error instanceof Error ? error.message : String(error)}`, this.url || "", this.method || "", {
711
- status: this.response.status,
712
- response: this.response,
713
- body: this.cachedText,
714
- });
665
+ throw this._err(`Selector: ${errorMessage(error)}`, true);
715
666
  }
716
667
  // If we get here and it's not a RequestError, wrap it
717
668
  // This should rarely happen as getJson() should throw RequestError
718
- const errorObj = error instanceof Error ? error : new Error(String(error));
719
- throw RequestError.networkError(this.url || "", this.method || "", errorObj);
669
+ throw RequestError.networkError(this.url || "", this.method || "", toError(error));
720
670
  }
721
671
  }
722
672
  }
@@ -728,20 +678,9 @@ class CookieUtils {
728
678
  * @returns Formatted cookie string for the Cookie header
729
679
  */
730
680
  static formatRequestCookies(cookies) {
731
- const cookiePairs = [];
732
- Object.entries(cookies).forEach(([name, valueOrOptions]) => {
733
- let value;
734
- if (typeof valueOrOptions === "string") {
735
- value = valueOrOptions;
736
- }
737
- else {
738
- // Extract value from options object without validation
739
- value = valueOrOptions.value;
740
- }
741
- // Add the cookie to the request
742
- cookiePairs.push(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`);
743
- });
744
- return cookiePairs.join("; ");
681
+ return Object.entries(cookies)
682
+ .map(([name, valueOrOptions]) => `${encodeURIComponent(name)}=${encodeURIComponent(typeof valueOrOptions === "string" ? valueOrOptions : valueOrOptions.value)}`)
683
+ .join("; ");
745
684
  }
746
685
  }
747
686
 
@@ -795,17 +734,11 @@ class CsrfUtils {
795
734
  // If token is longer than 10 chars, perform additional security checks
796
735
  if (token.length > 10) {
797
736
  // Check for valid character set (alphanumeric & common token symbols)
798
- const validTokenRegex = /^[A-Za-z0-9\-_=+/.]+$/;
799
- if (!validTokenRegex.test(token)) {
737
+ if (!/^[A-Za-z0-9\-_=+/.]+$/.test(token)) {
800
738
  return false;
801
739
  }
802
740
  // For longer tokens, check for sufficient entropy (at least 2 character types)
803
- const hasUpperCase = /[A-Z]/.test(token);
804
- const hasLowerCase = /[a-z]/.test(token);
805
- const hasNumbers = /[0-9]/.test(token);
806
- const hasSpecials = /[-_=+/.]/.test(token);
807
- const characterTypesCount = [hasUpperCase, hasLowerCase, hasNumbers, hasSpecials].filter(Boolean).length;
808
- return characterTypesCount >= 2;
741
+ return [/[A-Z]/, /[a-z]/, /[0-9]/, /[-_=+/.]/].filter(re => re.test(token)).length >= 2;
809
742
  }
810
743
  // For shorter tokens (8-10 chars), just return true if we reached here
811
744
  return true;
@@ -816,19 +749,19 @@ class CsrfUtils {
816
749
  * Global configuration for create-request
817
750
  */
818
751
  class Config {
819
- static instance;
752
+ static _instance;
820
753
  // CSRF configuration
821
- csrfHeaderName = "X-CSRF-Token";
822
- xsrfCookieName = "XSRF-TOKEN";
823
- xsrfHeaderName = "X-XSRF-TOKEN";
824
- csrfToken = null;
825
- enableAutoXsrf = true;
826
- enableAntiCsrf = true; // X-Requested-With header
754
+ _csrfHeader = "X-CSRF-Token";
755
+ _xsrfCookie = "XSRF-TOKEN";
756
+ _xsrfHeader = "X-XSRF-TOKEN";
757
+ _csrfToken = null;
758
+ _autoXsrf = true;
759
+ _antiCsrf = true; // X-Requested-With header
827
760
  // Interceptor configuration
828
- requestInterceptors = [];
829
- responseInterceptors = [];
830
- errorInterceptors = [];
831
- nextInterceptorId = 1;
761
+ _reqI = [];
762
+ _resI = [];
763
+ _errI = [];
764
+ _nextId = 1;
832
765
  constructor() { }
833
766
  /**
834
767
  * Get the singleton instance of the Config class
@@ -840,10 +773,10 @@ class Config {
840
773
  * config.setCsrfToken('token123');
841
774
  */
842
775
  static getInstance() {
843
- if (!Config.instance) {
844
- Config.instance = new Config();
776
+ if (!Config._instance) {
777
+ Config._instance = new Config();
845
778
  }
846
- return Config.instance;
779
+ return Config._instance;
847
780
  }
848
781
  /**
849
782
  * Set a global CSRF token to be used for all requests
@@ -855,7 +788,7 @@ class Config {
855
788
  * Config.getInstance().setCsrfToken('myToken123');
856
789
  */
857
790
  setCsrfToken(token) {
858
- this.csrfToken = token;
791
+ this._csrfToken = token;
859
792
  return this;
860
793
  }
861
794
  /**
@@ -864,7 +797,7 @@ class Config {
864
797
  * @returns The current CSRF token or null if not set
865
798
  */
866
799
  getCsrfToken() {
867
- return this.csrfToken;
800
+ return this._csrfToken;
868
801
  }
869
802
  /**
870
803
  * Set the CSRF header name used when sending the token
@@ -876,7 +809,7 @@ class Config {
876
809
  * Config.getInstance().setCsrfHeaderName('X-My-CSRF-Token');
877
810
  */
878
811
  setCsrfHeaderName(name) {
879
- this.csrfHeaderName = name;
812
+ this._csrfHeader = name;
880
813
  return this;
881
814
  }
882
815
  /**
@@ -885,7 +818,7 @@ class Config {
885
818
  * @returns The current CSRF header name
886
819
  */
887
820
  getCsrfHeaderName() {
888
- return this.csrfHeaderName;
821
+ return this._csrfHeader;
889
822
  }
890
823
  /**
891
824
  * Set the XSRF cookie name to look for when extracting tokens from cookies
@@ -897,7 +830,7 @@ class Config {
897
830
  * Config.getInstance().setXsrfCookieName('MY-XSRF-COOKIE');
898
831
  */
899
832
  setXsrfCookieName(name) {
900
- this.xsrfCookieName = name;
833
+ this._xsrfCookie = name;
901
834
  return this;
902
835
  }
903
836
  /**
@@ -906,7 +839,7 @@ class Config {
906
839
  * @returns The current XSRF cookie name
907
840
  */
908
841
  getXsrfCookieName() {
909
- return this.xsrfCookieName;
842
+ return this._xsrfCookie;
910
843
  }
911
844
  /**
912
845
  * Set the XSRF header name for sending tokens extracted from cookies
@@ -915,7 +848,7 @@ class Config {
915
848
  * @returns The config instance for chaining
916
849
  */
917
850
  setXsrfHeaderName(name) {
918
- this.xsrfHeaderName = name;
851
+ this._xsrfHeader = name;
919
852
  return this;
920
853
  }
921
854
  /**
@@ -924,7 +857,7 @@ class Config {
924
857
  * @returns The current XSRF header name
925
858
  */
926
859
  getXsrfHeaderName() {
927
- return this.xsrfHeaderName;
860
+ return this._xsrfHeader;
928
861
  }
929
862
  /**
930
863
  * Enable or disable automatic extraction of XSRF tokens from cookies
@@ -938,7 +871,7 @@ class Config {
938
871
  * Config.getInstance().setEnableAutoXsrf(false); // Disable XSRF extraction
939
872
  */
940
873
  setEnableAutoXsrf(enable) {
941
- this.enableAutoXsrf = enable;
874
+ this._autoXsrf = enable;
942
875
  return this;
943
876
  }
944
877
  /**
@@ -947,7 +880,7 @@ class Config {
947
880
  * @returns True if automatic XSRF is enabled
948
881
  */
949
882
  isAutoXsrfEnabled() {
950
- return this.enableAutoXsrf;
883
+ return this._autoXsrf;
951
884
  }
952
885
  /**
953
886
  * Enable or disable automatic addition of anti-CSRF headers
@@ -957,7 +890,7 @@ class Config {
957
890
  * @returns The config instance for chaining
958
891
  */
959
892
  setEnableAntiCsrf(enable) {
960
- this.enableAntiCsrf = enable;
893
+ this._antiCsrf = enable;
961
894
  return this;
962
895
  }
963
896
  /**
@@ -966,7 +899,7 @@ class Config {
966
899
  * @returns True if anti-CSRF protection is enabled
967
900
  */
968
901
  isAntiCsrfEnabled() {
969
- return this.enableAntiCsrf;
902
+ return this._antiCsrf;
970
903
  }
971
904
  /**
972
905
  * Add a global request interceptor
@@ -982,8 +915,8 @@ class Config {
982
915
  * });
983
916
  */
984
917
  addRequestInterceptor(interceptor) {
985
- const id = this.nextInterceptorId++;
986
- this.requestInterceptors.push({ id, interceptor });
918
+ const id = this._nextId++;
919
+ this._reqI.push([id, interceptor]);
987
920
  return id;
988
921
  }
989
922
  /**
@@ -1000,8 +933,8 @@ class Config {
1000
933
  * });
1001
934
  */
1002
935
  addResponseInterceptor(interceptor) {
1003
- const id = this.nextInterceptorId++;
1004
- this.responseInterceptors.push({ id, interceptor });
936
+ const id = this._nextId++;
937
+ this._resI.push([id, interceptor]);
1005
938
  return id;
1006
939
  }
1007
940
  /**
@@ -1018,8 +951,8 @@ class Config {
1018
951
  * });
1019
952
  */
1020
953
  addErrorInterceptor(interceptor) {
1021
- const id = this.nextInterceptorId++;
1022
- this.errorInterceptors.push({ id, interceptor });
954
+ const id = this._nextId++;
955
+ this._errI.push([id, interceptor]);
1023
956
  return id;
1024
957
  }
1025
958
  /**
@@ -1031,7 +964,7 @@ class Config {
1031
964
  * Config.getInstance().removeRequestInterceptor(id);
1032
965
  */
1033
966
  removeRequestInterceptor(id) {
1034
- this.requestInterceptors = this.requestInterceptors.filter(item => item.id !== id);
967
+ this._reqI = this._reqI.filter(item => item[0] !== id);
1035
968
  }
1036
969
  /**
1037
970
  * Remove a response interceptor by its ID
@@ -1042,7 +975,7 @@ class Config {
1042
975
  * Config.getInstance().removeResponseInterceptor(id);
1043
976
  */
1044
977
  removeResponseInterceptor(id) {
1045
- this.responseInterceptors = this.responseInterceptors.filter(item => item.id !== id);
978
+ this._resI = this._resI.filter(item => item[0] !== id);
1046
979
  }
1047
980
  /**
1048
981
  * Remove an error interceptor by its ID
@@ -1053,7 +986,7 @@ class Config {
1053
986
  * Config.getInstance().removeErrorInterceptor(id);
1054
987
  */
1055
988
  removeErrorInterceptor(id) {
1056
- this.errorInterceptors = this.errorInterceptors.filter(item => item.id !== id);
989
+ this._errI = this._errI.filter(item => item[0] !== id);
1057
990
  }
1058
991
  /**
1059
992
  * Clear all interceptors (request, response, and error)
@@ -1062,30 +995,30 @@ class Config {
1062
995
  * Config.getInstance().clearInterceptors();
1063
996
  */
1064
997
  clearInterceptors() {
1065
- this.requestInterceptors = [];
1066
- this.responseInterceptors = [];
1067
- this.errorInterceptors = [];
998
+ this._reqI = [];
999
+ this._resI = [];
1000
+ this._errI = [];
1068
1001
  }
1069
1002
  /**
1070
1003
  * Get all global request interceptors (in registration order)
1071
1004
  * @internal
1072
1005
  */
1073
1006
  getRequestInterceptors() {
1074
- return this.requestInterceptors.map(item => item.interceptor);
1007
+ return this._reqI.map(item => item[1]);
1075
1008
  }
1076
1009
  /**
1077
1010
  * Get all global response interceptors (in registration order)
1078
1011
  * @internal
1079
1012
  */
1080
1013
  getResponseInterceptors() {
1081
- return this.responseInterceptors.map(item => item.interceptor);
1014
+ return this._resI.map(item => item[1]);
1082
1015
  }
1083
1016
  /**
1084
1017
  * Get all global error interceptors (in registration order)
1085
1018
  * @internal
1086
1019
  */
1087
1020
  getErrorInterceptors() {
1088
- return this.errorInterceptors.map(item => item.interceptor);
1021
+ return this._errI.map(item => item[1]);
1089
1022
  }
1090
1023
  /**
1091
1024
  * Reset all configuration options to their default values
@@ -1096,12 +1029,12 @@ class Config {
1096
1029
  * Config.getInstance().reset();
1097
1030
  */
1098
1031
  reset() {
1099
- this.csrfToken = null;
1100
- this.csrfHeaderName = "X-CSRF-Token";
1101
- this.enableAntiCsrf = true;
1102
- this.xsrfCookieName = "XSRF-TOKEN";
1103
- this.xsrfHeaderName = "X-XSRF-TOKEN";
1104
- this.enableAutoXsrf = true;
1032
+ this._csrfToken = null;
1033
+ this._csrfHeader = "X-CSRF-Token";
1034
+ this._antiCsrf = true;
1035
+ this._xsrfCookie = "XSRF-TOKEN";
1036
+ this._xsrfHeader = "X-XSRF-TOKEN";
1037
+ this._autoXsrf = true;
1105
1038
  this.clearInterceptors();
1106
1039
  return this;
1107
1040
  }
@@ -1112,54 +1045,54 @@ class Config {
1112
1045
  * Provides the core request building and execution capabilities.
1113
1046
  */
1114
1047
  class BaseRequest {
1115
- url;
1116
- requestOptions = {
1048
+ _url;
1049
+ _opts = {
1117
1050
  headers: {},
1118
1051
  };
1119
- abortController;
1120
- customFetch;
1121
- queryParams = new URLSearchParams();
1122
- autoApplyCsrfProtection = true;
1052
+ _ctrl;
1053
+ _fetch;
1054
+ _query = new URLSearchParams();
1055
+ _autoCsrf = true;
1123
1056
  // Per-request interceptors
1124
- requestInterceptors = [];
1125
- responseInterceptors = [];
1126
- errorInterceptors = [];
1057
+ _reqI = [];
1058
+ _resI = [];
1059
+ _errI = [];
1127
1060
  constructor(url) {
1128
- this.url = url;
1061
+ this._url = url;
1129
1062
  }
1130
1063
  /**
1131
1064
  * Get GraphQL options if set (only for BodyRequest subclasses)
1132
1065
  * @returns GraphQL options or undefined
1133
1066
  */
1134
- getGraphQLOptions() {
1067
+ _gql() {
1135
1068
  return undefined;
1136
1069
  }
1137
1070
  /**
1138
1071
  * Creates a fluent API for setting enum-based options
1139
1072
  * Combines direct setter with convenience methods
1140
1073
  */
1141
- createFluentSetter(optionName, options) {
1074
+ _fluent(optionName, options) {
1142
1075
  const fluent = {};
1143
1076
  // Create convenience methods for each enum value
1144
1077
  Object.entries(options).forEach(([key, value]) => {
1145
1078
  fluent[key] = () => {
1146
- this.requestOptions[optionName] = value;
1079
+ this._opts[optionName] = value;
1147
1080
  return this;
1148
1081
  };
1149
1082
  });
1150
1083
  // Create the callable setter
1151
1084
  const callable = (value) => {
1152
- this.requestOptions[optionName] = value;
1085
+ this._opts[optionName] = value;
1153
1086
  return this;
1154
1087
  };
1155
1088
  return Object.assign(callable, fluent);
1156
1089
  }
1157
- validateUrl(url) {
1090
+ _validateUrl(url) {
1158
1091
  const errorMessage = "Bad URL";
1159
1092
  if (!url?.trim())
1160
- throw new RequestError(errorMessage, url, this.method);
1093
+ throw new RequestError(errorMessage, url, this._method);
1161
1094
  if (url.includes("\0") || url.includes("\r") || url.includes("\n")) {
1162
- throw new RequestError(errorMessage, url, this.method);
1095
+ throw new RequestError(errorMessage, url, this._method);
1163
1096
  }
1164
1097
  const trimmed = url.trim();
1165
1098
  if (/^https?:\/\//.test(trimmed)) {
@@ -1167,7 +1100,7 @@ class BaseRequest {
1167
1100
  new URL(trimmed);
1168
1101
  }
1169
1102
  catch {
1170
- throw new RequestError(errorMessage, trimmed, this.method);
1103
+ throw new RequestError(errorMessage, trimmed, this._method);
1171
1104
  }
1172
1105
  }
1173
1106
  }
@@ -1185,16 +1118,12 @@ class BaseRequest {
1185
1118
  */
1186
1119
  withHeaders(headers) {
1187
1120
  // Filter out null and undefined values
1188
- const filteredHeaders = {};
1189
- Object.entries(headers).forEach(([key, value]) => {
1190
- if (value !== null && value !== undefined) {
1191
- filteredHeaders[key] = value;
1192
- }
1193
- });
1194
- this.requestOptions.headers = {
1195
- ...this.getHeadersRecord(),
1196
- ...filteredHeaders,
1197
- };
1121
+ const merged = { ...this._headers() };
1122
+ for (const [key, value] of Object.entries(headers)) {
1123
+ if (value != null)
1124
+ merged[key] = value;
1125
+ }
1126
+ this._opts.headers = merged;
1198
1127
  return this;
1199
1128
  }
1200
1129
  /**
@@ -1223,8 +1152,8 @@ class BaseRequest {
1223
1152
  */
1224
1153
  withTimeout(timeout) {
1225
1154
  if (!Number.isFinite(timeout) || timeout <= 0)
1226
- throw new RequestError("Bad timeout", this.url, this.method);
1227
- this.requestOptions.timeout = timeout;
1155
+ throw new RequestError("Bad timeout", this._url, this._method);
1156
+ this._opts.timeout = timeout;
1228
1157
  return this;
1229
1158
  }
1230
1159
  /**
@@ -1260,30 +1189,22 @@ class BaseRequest {
1260
1189
  * });
1261
1190
  */
1262
1191
  withRetries(retries) {
1263
- if (typeof retries === "number") {
1264
- if (!Number.isInteger(retries) || retries < 0) {
1265
- throw new RequestError(`Bad retries: ${retries}`, this.url, this.method);
1266
- }
1267
- this.requestOptions.retries = retries;
1192
+ const isNumber = typeof retries === "number";
1193
+ const attempts = isNumber ? retries : retries.attempts;
1194
+ if (!Number.isInteger(attempts) || attempts < 0) {
1195
+ throw new RequestError(`Bad ${isNumber ? "retries" : "attempts"}: ${attempts}`, this._url, this._method);
1268
1196
  }
1269
- else {
1270
- // Validate RetryConfig
1271
- if (!Number.isInteger(retries.attempts) || retries.attempts < 0) {
1272
- throw new RequestError(`Bad attempts: ${retries.attempts}`, this.url, this.method);
1197
+ if (!isNumber && retries.delay !== undefined) {
1198
+ const delay = retries.delay;
1199
+ if (typeof delay === "number") {
1200
+ if (!Number.isFinite(delay) || delay < 0)
1201
+ throw new RequestError(`Bad delay: ${delay}`, this._url, this._method);
1273
1202
  }
1274
- // Validate delay if provided
1275
- if (retries.delay !== undefined) {
1276
- if (typeof retries.delay === "number") {
1277
- if (!Number.isFinite(retries.delay) || retries.delay < 0) {
1278
- throw new RequestError(`Bad delay: ${retries.delay}`, this.url, this.method);
1279
- }
1280
- }
1281
- else if (typeof retries.delay !== "function") {
1282
- throw new RequestError(`Bad delay: ${typeof retries.delay}`, this.url, this.method);
1283
- }
1203
+ else if (typeof delay !== "function") {
1204
+ throw new RequestError(`Bad delay: ${typeof delay}`, this._url, this._method);
1284
1205
  }
1285
- this.requestOptions.retries = retries;
1286
1206
  }
1207
+ this._opts.retries = retries;
1287
1208
  return this;
1288
1209
  }
1289
1210
  /**
@@ -1300,7 +1221,7 @@ class BaseRequest {
1300
1221
  * });
1301
1222
  */
1302
1223
  onRetry(callback) {
1303
- this.requestOptions.onRetry = callback;
1224
+ this._opts.onRetry = callback;
1304
1225
  return this;
1305
1226
  }
1306
1227
  /**
@@ -1327,11 +1248,7 @@ class BaseRequest {
1327
1248
  * request.withCredentials.INCLUDE()
1328
1249
  */
1329
1250
  get withCredentials() {
1330
- return this.createFluentSetter("credentials", {
1331
- INCLUDE: exports.CredentialsPolicy.INCLUDE,
1332
- OMIT: exports.CredentialsPolicy.OMIT,
1333
- SAME_ORIGIN: exports.CredentialsPolicy.SAME_ORIGIN,
1334
- });
1251
+ return this._fluent("credentials", CredentialsPolicy);
1335
1252
  }
1336
1253
  /**
1337
1254
  * Allows providing an external AbortController to cancel the request.
@@ -1360,7 +1277,7 @@ class BaseRequest {
1360
1277
  * controller.abort();
1361
1278
  */
1362
1279
  withAbortController(controller) {
1363
- this.abortController = controller;
1280
+ this._ctrl = controller;
1364
1281
  return this;
1365
1282
  }
1366
1283
  /**
@@ -1394,8 +1311,8 @@ class BaseRequest {
1394
1311
  */
1395
1312
  withFetch(fetchFn) {
1396
1313
  if (typeof fetchFn !== "function")
1397
- throw new RequestError("Bad fetch", this.url, this.method);
1398
- this.customFetch = fetchFn;
1314
+ throw new RequestError("Bad fetch", this._url, this._method);
1315
+ this._fetch = fetchFn;
1399
1316
  return this;
1400
1317
  }
1401
1318
  /**
@@ -1417,7 +1334,7 @@ class BaseRequest {
1417
1334
  * request.withReferrer("")
1418
1335
  */
1419
1336
  withReferrer(referrer) {
1420
- this.requestOptions.referrer = referrer;
1337
+ this._opts.referrer = referrer;
1421
1338
  return this;
1422
1339
  }
1423
1340
  /**
@@ -1449,16 +1366,7 @@ class BaseRequest {
1449
1366
  * request.withReferrerPolicy.NO_REFERRER()
1450
1367
  */
1451
1368
  get withReferrerPolicy() {
1452
- return this.createFluentSetter("referrerPolicy", {
1453
- ORIGIN: exports.ReferrerPolicy.ORIGIN,
1454
- UNSAFE_URL: exports.ReferrerPolicy.UNSAFE_URL,
1455
- SAME_ORIGIN: exports.ReferrerPolicy.SAME_ORIGIN,
1456
- NO_REFERRER: exports.ReferrerPolicy.NO_REFERRER,
1457
- STRICT_ORIGIN: exports.ReferrerPolicy.STRICT_ORIGIN,
1458
- ORIGIN_WHEN_CROSS_ORIGIN: exports.ReferrerPolicy.ORIGIN_WHEN_CROSS_ORIGIN,
1459
- NO_REFERRER_WHEN_DOWNGRADE: exports.ReferrerPolicy.NO_REFERRER_WHEN_DOWNGRADE,
1460
- STRICT_ORIGIN_WHEN_CROSS_ORIGIN: exports.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
1461
- });
1369
+ return this._fluent("referrerPolicy", ReferrerPolicy);
1462
1370
  }
1463
1371
  /**
1464
1372
  * Sets how the request handles HTTP redirects (3xx status codes).
@@ -1487,11 +1395,7 @@ class BaseRequest {
1487
1395
  * request.withRedirect.ERROR()
1488
1396
  */
1489
1397
  get withRedirect() {
1490
- return this.createFluentSetter("redirect", {
1491
- FOLLOW: exports.RedirectMode.FOLLOW,
1492
- ERROR: exports.RedirectMode.ERROR,
1493
- MANUAL: exports.RedirectMode.MANUAL,
1494
- });
1398
+ return this._fluent("redirect", RedirectMode);
1495
1399
  }
1496
1400
  /**
1497
1401
  * Sets the keepalive flag for the request. When enabled, the request can continue
@@ -1509,7 +1413,7 @@ class BaseRequest {
1509
1413
  * request.withKeepAlive(true)
1510
1414
  */
1511
1415
  withKeepAlive(keepalive) {
1512
- this.requestOptions.keepalive = keepalive;
1416
+ this._opts.keepalive = keepalive;
1513
1417
  return this;
1514
1418
  }
1515
1419
  /**
@@ -1540,11 +1444,7 @@ class BaseRequest {
1540
1444
  * request.withPriority.LOW()
1541
1445
  */
1542
1446
  get withPriority() {
1543
- return this.createFluentSetter("priority", {
1544
- HIGH: exports.RequestPriority.HIGH,
1545
- LOW: exports.RequestPriority.LOW,
1546
- AUTO: exports.RequestPriority.AUTO,
1547
- });
1447
+ return this._fluent("priority", RequestPriority);
1548
1448
  }
1549
1449
  /**
1550
1450
  * Sets the integrity hash for Subresource Integrity (SRI) verification.
@@ -1567,7 +1467,7 @@ class BaseRequest {
1567
1467
  * request.withIntegrity("sha256-... sha384-...")
1568
1468
  */
1569
1469
  withIntegrity(integrity) {
1570
- this.requestOptions.integrity = integrity;
1470
+ this._opts.integrity = integrity;
1571
1471
  return this;
1572
1472
  }
1573
1473
  /**
@@ -1605,15 +1505,7 @@ class BaseRequest {
1605
1505
  * request.withCache.ONLY_IF_CACHED()
1606
1506
  */
1607
1507
  get withCache() {
1608
- const cacheOptions = {
1609
- DEFAULT: "default",
1610
- NO_STORE: "no-store",
1611
- RELOAD: "reload",
1612
- NO_CACHE: "no-cache",
1613
- FORCE_CACHE: "force-cache",
1614
- ONLY_IF_CACHED: "only-if-cached",
1615
- };
1616
- return this.createFluentSetter("cache", cacheOptions);
1508
+ return this._fluent("cache", CacheMode);
1617
1509
  }
1618
1510
  /**
1619
1511
  * Adds query parameters to the request URL.
@@ -1652,10 +1544,10 @@ class BaseRequest {
1652
1544
  }
1653
1545
  if (Array.isArray(value)) {
1654
1546
  // Handle array values - add multiple entries with the same key
1655
- value.forEach(v => this.queryParams.append(key, String(v)));
1547
+ value.forEach(v => this._query.append(key, String(v)));
1656
1548
  }
1657
1549
  else {
1658
- this.queryParams.append(key, String(value));
1550
+ this._query.append(key, String(value));
1659
1551
  }
1660
1552
  });
1661
1553
  return this;
@@ -1713,12 +1605,7 @@ class BaseRequest {
1713
1605
  * request.withMode.SAME_ORIGIN()
1714
1606
  */
1715
1607
  get withMode() {
1716
- return this.createFluentSetter("mode", {
1717
- CORS: exports.RequestMode.CORS,
1718
- NO_CORS: exports.RequestMode.NO_CORS,
1719
- SAME_ORIGIN: exports.RequestMode.SAME_ORIGIN,
1720
- NAVIGATE: exports.RequestMode.NAVIGATE,
1721
- });
1608
+ return this._fluent("mode", RequestMode);
1722
1609
  }
1723
1610
  /**
1724
1611
  * Sets the Content-Type header for the request.
@@ -1776,28 +1663,26 @@ class BaseRequest {
1776
1663
  * ```
1777
1664
  */
1778
1665
  withBasicAuth(username, password) {
1779
- const credentials = this.encodeBase64(`${username}:${password}`);
1666
+ const credentials = this._b64(`${username}:${password}`);
1780
1667
  return this.withAuthorization(`Basic ${credentials}`);
1781
1668
  }
1782
1669
  /**
1783
1670
  * Cross-environment base64 encoding
1784
1671
  * Works in both browser and Node.js environments
1785
1672
  */
1786
- encodeBase64(str) {
1673
+ _b64(str) {
1787
1674
  // Modern approach using TextEncoder (available in both modern browsers and Node.js)
1788
- if (typeof TextEncoder !== "undefined" && typeof btoa === "function") {
1789
- const encoder = new TextEncoder();
1790
- const bytes = encoder.encode(str);
1791
- return btoa(String.fromCharCode.apply(null, [...new Uint8Array(bytes)]));
1792
- }
1793
- // Browser environment
1794
- if (typeof btoa === "function")
1675
+ if (typeof btoa === "function") {
1676
+ if (typeof TextEncoder !== "undefined")
1677
+ return btoa(String.fromCharCode(...new TextEncoder().encode(str)));
1678
+ // Browser environment without TextEncoder
1795
1679
  return btoa(str);
1680
+ }
1796
1681
  // Node.js environment
1797
1682
  if (typeof Buffer !== "undefined")
1798
1683
  return Buffer.from(str).toString("base64");
1799
1684
  // Fallback (should never happen in modern environments)
1800
- throw new RequestError("No encoder", this.url, this.method);
1685
+ throw new RequestError("No encoder", this._url, this._method);
1801
1686
  }
1802
1687
  /**
1803
1688
  * Sets a Bearer token for authentication.
@@ -1819,9 +1704,9 @@ class BaseRequest {
1819
1704
  * Safely get headers as a Record<string, string>
1820
1705
  * @returns The headers object
1821
1706
  */
1822
- getHeadersRecord() {
1823
- if (typeof this.requestOptions.headers === "object" && this.requestOptions.headers !== null) {
1824
- return this.requestOptions.headers;
1707
+ _headers() {
1708
+ if (typeof this._opts.headers === "object" && this._opts.headers !== null) {
1709
+ return this._opts.headers;
1825
1710
  }
1826
1711
  return {};
1827
1712
  }
@@ -1830,8 +1715,8 @@ class BaseRequest {
1830
1715
  * @param headerName Header name to check
1831
1716
  * @returns Boolean indicating if the header exists (case-insensitive)
1832
1717
  */
1833
- hasHeader(headerName) {
1834
- const headers = this.getHeadersRecord();
1718
+ _hasHeader(headerName) {
1719
+ const headers = this._headers();
1835
1720
  return Object.keys(headers).some(key => key.toLowerCase() === headerName.toLowerCase());
1836
1721
  }
1837
1722
  /**
@@ -1860,37 +1745,26 @@ class BaseRequest {
1860
1745
  * ```
1861
1746
  */
1862
1747
  withCookies(cookies) {
1863
- const cookieEntries = Object.entries(cookies || {});
1864
- if (cookieEntries.length === 0) {
1748
+ if (Object.keys(cookies || {}).length === 0)
1865
1749
  return this;
1866
- }
1867
- const currentHeaders = this.getHeadersRecord();
1868
- // Get all existing cookie headers with different cases
1750
+ // Collect existing cookie header values (any casing), preserving the first header's case
1751
+ const newHeaders = { ...this._headers() };
1869
1752
  const cookieValues = [];
1870
- const cookieHeaderKeys = [];
1871
- Object.keys(currentHeaders).forEach(key => {
1753
+ let headerName = "";
1754
+ for (const key of Object.keys(newHeaders)) {
1872
1755
  if (key.toLowerCase() === "cookie") {
1873
1756
  // Don't add empty cookie values
1874
- if (currentHeaders[key])
1875
- cookieValues.push(currentHeaders[key]);
1876
- cookieHeaderKeys.push(key);
1757
+ if (newHeaders[key])
1758
+ cookieValues.push(newHeaders[key]);
1759
+ headerName ||= key;
1760
+ delete newHeaders[key];
1877
1761
  }
1878
- });
1879
- // Format the new cookies
1880
- const cookieString = CookieUtils.formatRequestCookies(cookies);
1881
- // Choose which header name to use - preserve existing case if possible
1882
- const headerName = cookieHeaderKeys.length > 0 ? cookieHeaderKeys[0] : "Cookie";
1883
- // Combine all existing cookie values with the new ones
1884
- const combinedCookieValue = [...cookieValues, cookieString].filter(Boolean).join("; ");
1885
- // Create a new headers object without any cookie headers
1886
- const newHeaders = { ...currentHeaders };
1887
- cookieHeaderKeys.forEach(key => {
1888
- delete newHeaders[key];
1889
- });
1890
- // Set the new combined cookie header
1891
- this.requestOptions.headers = {
1762
+ }
1763
+ // Combine all existing cookie values with the newly formatted ones
1764
+ cookieValues.push(CookieUtils.formatRequestCookies(cookies));
1765
+ this._opts.headers = {
1892
1766
  ...newHeaders,
1893
- [headerName]: combinedCookieValue,
1767
+ [headerName || "Cookie"]: cookieValues.filter(Boolean).join("; "),
1894
1768
  };
1895
1769
  return this;
1896
1770
  }
@@ -1944,7 +1818,7 @@ class BaseRequest {
1944
1818
  * @returns The instance for chaining
1945
1819
  */
1946
1820
  withoutCsrfProtection() {
1947
- this.autoApplyCsrfProtection = false;
1821
+ this._autoCsrf = false;
1948
1822
  return this;
1949
1823
  }
1950
1824
  /**
@@ -1968,7 +1842,7 @@ class BaseRequest {
1968
1842
  * });
1969
1843
  */
1970
1844
  withRequestInterceptor(interceptor) {
1971
- this.requestInterceptors.push(interceptor);
1845
+ this._reqI.push(interceptor);
1972
1846
  return this;
1973
1847
  }
1974
1848
  /**
@@ -1985,7 +1859,7 @@ class BaseRequest {
1985
1859
  * });
1986
1860
  */
1987
1861
  withResponseInterceptor(interceptor) {
1988
- this.responseInterceptors.push(interceptor);
1862
+ this._resI.push(interceptor);
1989
1863
  return this;
1990
1864
  }
1991
1865
  /**
@@ -2002,7 +1876,7 @@ class BaseRequest {
2002
1876
  * });
2003
1877
  */
2004
1878
  withErrorInterceptor(interceptor) {
2005
- this.errorInterceptors.push(interceptor);
1879
+ this._errI.push(interceptor);
2006
1880
  return this;
2007
1881
  }
2008
1882
  /**
@@ -2016,13 +1890,13 @@ class BaseRequest {
2016
1890
  * console.log(response.status);
2017
1891
  */
2018
1892
  async getResponse() {
2019
- const url = this.formatUrlWithQueryParams(this.url);
2020
- this.applyCsrfProtection();
1893
+ const url = this._fullUrl(this._url);
1894
+ this._applyCsrf();
2021
1895
  const fetchOptions = {
2022
- ...this.requestOptions,
2023
- method: this.method,
1896
+ ...this._opts,
1897
+ method: this._method,
2024
1898
  };
2025
- return !this.requestOptions.retries ? this.executeRequest(url, fetchOptions) : this.executeWithRetries(url, fetchOptions);
1899
+ return !this._opts.retries ? this._run(url, fetchOptions) : this._retry(url, fetchOptions);
2026
1900
  }
2027
1901
  /**
2028
1902
  * Execute the request and parse the response as JSON
@@ -2163,8 +2037,8 @@ class BaseRequest {
2163
2037
  /**
2164
2038
  * Apply CSRF protection headers based on configuration
2165
2039
  */
2166
- applyCsrfProtection() {
2167
- if (!this.autoApplyCsrfProtection)
2040
+ _applyCsrf() {
2041
+ if (!this._autoCsrf)
2168
2042
  return;
2169
2043
  const config = Config.getInstance();
2170
2044
  // Apply anti-CSRF headers if enabled
@@ -2175,7 +2049,7 @@ class BaseRequest {
2175
2049
  const globalToken = config.getCsrfToken();
2176
2050
  if (globalToken) {
2177
2051
  const csrfHeaderName = config.getCsrfHeaderName();
2178
- const hasLocalToken = this.hasHeader("X-CSRF-Token") || this.hasHeader(csrfHeaderName);
2052
+ const hasLocalToken = this._hasHeader("X-CSRF-Token") || this._hasHeader(csrfHeaderName);
2179
2053
  if (!hasLocalToken) {
2180
2054
  this.withHeader(csrfHeaderName, globalToken);
2181
2055
  }
@@ -2185,7 +2059,7 @@ class BaseRequest {
2185
2059
  const xsrfToken = CsrfUtils.getTokenFromCookie(config.getXsrfCookieName());
2186
2060
  if (xsrfToken && CsrfUtils.isValidToken(xsrfToken)) {
2187
2061
  const xsrfHeaderName = config.getXsrfHeaderName();
2188
- const hasLocalToken = this.hasHeader("X-XSRF-TOKEN") || this.hasHeader(xsrfHeaderName);
2062
+ const hasLocalToken = this._hasHeader("X-XSRF-TOKEN") || this._hasHeader(xsrfHeaderName);
2189
2063
  if (!hasLocalToken) {
2190
2064
  this.withHeader(xsrfHeaderName, xsrfToken);
2191
2065
  }
@@ -2197,8 +2071,8 @@ class BaseRequest {
2197
2071
  * @param url The base URL
2198
2072
  * @returns The URL with query parameters appended
2199
2073
  */
2200
- formatUrlWithQueryParams(url) {
2201
- const queryString = this.queryParams.toString();
2074
+ _fullUrl(url) {
2075
+ const queryString = this._query.toString();
2202
2076
  if (!queryString) {
2203
2077
  return url;
2204
2078
  }
@@ -2206,7 +2080,7 @@ class BaseRequest {
2206
2080
  // Try to use the URL constructor (works for absolute URLs)
2207
2081
  const urlObj = new URL(url);
2208
2082
  // Merge our query params with any that might be in the URL already
2209
- this.queryParams.forEach((value, key) => {
2083
+ this._query.forEach((value, key) => {
2210
2084
  urlObj.searchParams.append(key, value);
2211
2085
  });
2212
2086
  return urlObj.toString();
@@ -2225,21 +2099,21 @@ class BaseRequest {
2225
2099
  * @returns A wrapped response object
2226
2100
  * @throws RequestError if the request fails after all retries
2227
2101
  */
2228
- async executeWithRetries(url, fetchOptions) {
2229
- const retriesConfig = this.requestOptions.retries;
2102
+ async _retry(url, fetchOptions) {
2103
+ const retriesConfig = this._opts.retries;
2230
2104
  const maxRetries = typeof retriesConfig === "number" ? retriesConfig : retriesConfig?.attempts || 0;
2231
2105
  const method = typeof fetchOptions.method === "string" ? fetchOptions.method : "GET";
2232
2106
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
2233
2107
  try {
2234
- return await this.executeRequest(url, fetchOptions);
2108
+ return await this._run(url, fetchOptions);
2235
2109
  }
2236
2110
  catch (error) {
2237
- const requestError = error instanceof RequestError ? error : RequestError.networkError(url, method, error instanceof Error ? error : new Error(String(error)));
2111
+ const requestError = error instanceof RequestError ? error : RequestError.networkError(url, method, toError(error));
2238
2112
  if (attempt >= maxRetries)
2239
2113
  throw requestError;
2240
2114
  // Call onRetry callback if provided
2241
- if (this.requestOptions.onRetry) {
2242
- await this.requestOptions.onRetry({ attempt: attempt + 1, error: requestError });
2115
+ if (this._opts.onRetry) {
2116
+ await this._opts.onRetry({ attempt: attempt + 1, error: requestError });
2243
2117
  }
2244
2118
  // Apply delay if configured
2245
2119
  if (typeof retriesConfig === "object" && retriesConfig.delay !== undefined) {
@@ -2263,9 +2137,9 @@ class BaseRequest {
2263
2137
  * @param configParam - The request configuration
2264
2138
  * @returns Modified config or a Response to short-circuit
2265
2139
  */
2266
- async runRequestInterceptors(configParam) {
2140
+ async _runReqI(configParam) {
2267
2141
  const globalConfig = Config.getInstance();
2268
- const allInterceptors = [...globalConfig.getRequestInterceptors(), ...this.requestInterceptors];
2142
+ const allInterceptors = [...globalConfig.getRequestInterceptors(), ...this._reqI];
2269
2143
  let currentConfig = configParam;
2270
2144
  for (let i = 0; i < allInterceptors.length; i++) {
2271
2145
  try {
@@ -2277,7 +2151,7 @@ class BaseRequest {
2277
2151
  currentConfig = result;
2278
2152
  }
2279
2153
  catch (error) {
2280
- throw new RequestError(`ReqI: ${error instanceof Error ? error.message : String(error)}`, currentConfig.url, currentConfig.method);
2154
+ throw new RequestError(`ReqI: ${errorMessage(error)}`, currentConfig.url, currentConfig.method);
2281
2155
  }
2282
2156
  }
2283
2157
  return currentConfig;
@@ -2287,18 +2161,18 @@ class BaseRequest {
2287
2161
  * @param response - The response wrapper
2288
2162
  * @returns Modified response wrapper
2289
2163
  */
2290
- async runResponseInterceptors(response) {
2164
+ async _runResI(response) {
2291
2165
  const globalConfig = Config.getInstance();
2292
2166
  const globalInterceptors = globalConfig.getResponseInterceptors();
2293
2167
  // Per-request in order, then global in reverse
2294
- const allInterceptors = [...this.responseInterceptors, ...[...globalInterceptors].reverse()];
2168
+ const allInterceptors = [...this._resI, ...[...globalInterceptors].reverse()];
2295
2169
  let currentResponse = response;
2296
2170
  for (let i = 0; i < allInterceptors.length; i++) {
2297
2171
  try {
2298
2172
  currentResponse = await allInterceptors[i](currentResponse);
2299
2173
  }
2300
2174
  catch (error) {
2301
- throw new RequestError(`ResI: ${error instanceof Error ? error.message : String(error)}`, currentResponse.url || "", currentResponse.method || "");
2175
+ throw new RequestError(`ResI: ${errorMessage(error)}`, currentResponse.url || "", currentResponse.method || "");
2302
2176
  }
2303
2177
  }
2304
2178
  return currentResponse;
@@ -2308,11 +2182,11 @@ class BaseRequest {
2308
2182
  * @param error - The error that occurred
2309
2183
  * @returns Modified error or a ResponseWrapper to recover
2310
2184
  */
2311
- async runErrorInterceptors(error) {
2185
+ async _runErrI(error) {
2312
2186
  const globalConfig = Config.getInstance();
2313
2187
  const globalInterceptors = globalConfig.getErrorInterceptors();
2314
2188
  // Per-request in order, then global in reverse
2315
- const allInterceptors = [...this.errorInterceptors, ...[...globalInterceptors].reverse()];
2189
+ const allInterceptors = [...this._errI, ...[...globalInterceptors].reverse()];
2316
2190
  let currentError = error;
2317
2191
  for (let i = 0; i < allInterceptors.length; i++) {
2318
2192
  try {
@@ -2328,24 +2202,20 @@ class BaseRequest {
2328
2202
  if (interceptorError instanceof RequestError) {
2329
2203
  currentError = interceptorError;
2330
2204
  }
2331
- else {
2332
- const em = interceptorError instanceof Error ? interceptorError.message : String(interceptorError);
2205
+ else if (currentError instanceof RequestError) {
2333
2206
  // Always wrap in RequestError when we have context
2334
- if (currentError instanceof RequestError) {
2335
- currentError = new RequestError(`ErrI${i + 1}: ${em}`, currentError.url, currentError.method, {
2336
- status: currentError.status,
2337
- response: currentError.response,
2338
- body: currentError.body,
2339
- });
2340
- }
2341
- else {
2342
- /* c8 ignore start */
2343
- // Last resort: if we have no context at all, use the original error's context
2344
- // This shouldn't happen in practice, but handle it gracefully
2345
- const errorObj = interceptorError instanceof Error ? interceptorError : new Error(String(interceptorError));
2346
- currentError = RequestError.networkError(error.url, error.method, errorObj);
2347
- /* c8 ignore end */
2348
- }
2207
+ currentError = new RequestError(`ErrI${i + 1}: ${errorMessage(interceptorError)}`, currentError.url, currentError.method, {
2208
+ status: currentError.status,
2209
+ response: currentError.response,
2210
+ body: currentError.body,
2211
+ });
2212
+ }
2213
+ else {
2214
+ /* c8 ignore start */
2215
+ // Last resort: if we have no context at all, use the original error's context
2216
+ // This shouldn't happen in practice, but handle it gracefully
2217
+ currentError = RequestError.networkError(error.url, error.method, toError(interceptorError));
2218
+ /* c8 ignore end */
2349
2219
  }
2350
2220
  }
2351
2221
  }
@@ -2355,7 +2225,7 @@ class BaseRequest {
2355
2225
  * Helper to create an abort signal with timeout support
2356
2226
  * Handles various AbortSignal API levels gracefully
2357
2227
  */
2358
- createAbortSignal(timeoutMs, externalController) {
2228
+ _signal(timeoutMs, externalController) {
2359
2229
  let timeoutId;
2360
2230
  let timeoutController;
2361
2231
  let isTimeout = false;
@@ -2391,7 +2261,7 @@ class BaseRequest {
2391
2261
  const finalSignal = externalController && hasAbortSignalAny
2392
2262
  ? AbortSignal.any([externalController.signal, timeoutSignal])
2393
2263
  : externalController
2394
- ? this.combineSignalsManually(externalController.signal, timeoutSignal)
2264
+ ? this._combine(externalController.signal, timeoutSignal)
2395
2265
  : timeoutSignal;
2396
2266
  return {
2397
2267
  signal: finalSignal,
@@ -2406,7 +2276,7 @@ class BaseRequest {
2406
2276
  * Manually combine two abort signals for older environments
2407
2277
  * Returns the first signal and listens to the second
2408
2278
  */
2409
- combineSignalsManually(signal1, signal2) {
2279
+ _combine(signal1, signal2) {
2410
2280
  // If either is already aborted, use that one
2411
2281
  if (signal1.aborted)
2412
2282
  return signal1;
@@ -2422,9 +2292,9 @@ class BaseRequest {
2422
2292
  /**
2423
2293
  * Convert fetchOptions to RequestConfig with proper typing
2424
2294
  */
2425
- createRequestConfig(url, fetchOptions) {
2295
+ _config(url, fetchOptions) {
2426
2296
  const method = typeof fetchOptions.method === "string" ? fetchOptions.method : "GET";
2427
- const headers = this.getHeadersRecord();
2297
+ const headers = this._headers();
2428
2298
  const extendedOptions = fetchOptions;
2429
2299
  return {
2430
2300
  url,
@@ -2446,7 +2316,7 @@ class BaseRequest {
2446
2316
  /**
2447
2317
  * Apply interceptor results back to fetchOptions
2448
2318
  */
2449
- applyRequestConfig(config, fetchOptions) {
2319
+ _applyConfig(config, fetchOptions) {
2450
2320
  fetchOptions.headers = config.headers;
2451
2321
  if (config.body !== undefined) {
2452
2322
  fetchOptions.body = config.body;
@@ -2458,54 +2328,54 @@ class BaseRequest {
2458
2328
  fetchOptions.cache = config.cache;
2459
2329
  }
2460
2330
  }
2461
- async executeRequest(url, fetchOptions) {
2331
+ async _run(url, fetchOptions) {
2462
2332
  const method = typeof fetchOptions.method === "string" ? fetchOptions.method : "GET";
2463
2333
  // Setup abort signal with timeout
2464
- const abortSignal = this.createAbortSignal(this.requestOptions.timeout, this.abortController);
2334
+ const abortSignal = this._signal(this._opts.timeout, this._ctrl);
2465
2335
  try {
2466
2336
  // Run request interceptors before making the request
2467
- const requestConfig = this.createRequestConfig(url, fetchOptions);
2468
- const interceptorResult = await this.runRequestInterceptors(requestConfig);
2337
+ const requestConfig = this._config(url, fetchOptions);
2338
+ const interceptorResult = await this._runReqI(requestConfig);
2469
2339
  // If interceptor returned a Response, short-circuit and wrap it
2470
2340
  if (interceptorResult instanceof Response) {
2471
- const graphQLOptions = this.getGraphQLOptions();
2472
- const wrappedResponse = new ResponseWrapper(interceptorResult, this.url, this.method, graphQLOptions);
2473
- return await this.runResponseInterceptors(wrappedResponse);
2341
+ const graphQLOptions = this._gql();
2342
+ const wrappedResponse = new ResponseWrapper(interceptorResult, this._url, this._method, graphQLOptions);
2343
+ return await this._runResI(wrappedResponse);
2474
2344
  }
2475
2345
  // Update fetchOptions with interceptor modifications
2476
2346
  url = interceptorResult.url;
2477
- this.validateUrl(url);
2478
- this.applyRequestConfig(interceptorResult, fetchOptions);
2347
+ this._validateUrl(url);
2348
+ this._applyConfig(interceptorResult, fetchOptions);
2479
2349
  // Set the combined abort signal
2480
2350
  if (abortSignal.signal) {
2481
2351
  fetchOptions.signal = abortSignal.signal;
2482
2352
  }
2483
2353
  // Execute fetch (custom implementation if provided, global fetch otherwise)
2484
- const fetchFn = this.customFetch ?? globalThis.fetch;
2354
+ const fetchFn = this._fetch ?? globalThis.fetch;
2485
2355
  let response;
2486
2356
  try {
2487
2357
  response = await fetchFn(url, fetchOptions);
2488
2358
  }
2489
2359
  catch (error) {
2490
- const errorObj = error instanceof Error ? error : new Error(String(error));
2360
+ const errorObj = toError(error);
2491
2361
  const errorName = errorObj.name;
2492
- const errorMessage = errorObj.message.toLowerCase();
2362
+ const lowerMessage = errorObj.message.toLowerCase();
2493
2363
  // Check if this is a timeout error from our internal timeout
2494
2364
  const isOurTimeout = abortSignal.wasTimeout();
2495
2365
  // Check if it's an abort error (DOMException in browsers, or AbortSignal abort)
2496
2366
  if (error instanceof DOMException && error.name === "AbortError") {
2497
2367
  // If it was our timeout that caused the abort, throw timeout error
2498
- if (isOurTimeout && this.requestOptions.timeout) {
2499
- throw RequestError.timeout(url, method, this.requestOptions.timeout);
2368
+ if (isOurTimeout && this._opts.timeout) {
2369
+ throw RequestError.timeout(url, method, this._opts.timeout);
2500
2370
  }
2501
2371
  // Otherwise it's a manual abort
2502
2372
  throw RequestError.abortError(url, method);
2503
2373
  }
2504
2374
  // Check for Node.js/undici TimeoutError or other timeout indicators
2505
2375
  // This catches timeout errors that aren't thrown as AbortError
2506
- const isTimeoutError = isOurTimeout || errorName === "TimeoutError" || errorMessage.includes("timeout") || errorMessage.includes("aborted due to timeout");
2507
- if (isTimeoutError && this.requestOptions.timeout) {
2508
- throw RequestError.timeout(url, method, this.requestOptions.timeout);
2376
+ const isTimeoutError = isOurTimeout || errorName === "TimeoutError" || lowerMessage.includes("timeout");
2377
+ if (isTimeoutError && this._opts.timeout) {
2378
+ throw RequestError.timeout(url, method, this._opts.timeout);
2509
2379
  }
2510
2380
  // For other network errors, let RequestError.networkError handle them
2511
2381
  // It will check for timeout patterns as a safety net (useful for external AbortControllers)
@@ -2521,22 +2391,15 @@ class BaseRequest {
2521
2391
  // (reads from a clone, so error.response remains readable)
2522
2392
  throw RequestError.fromResponse(response, url, method, await RequestError.captureBody(response));
2523
2393
  }
2524
- const graphQLOptions = this.getGraphQLOptions();
2394
+ const graphQLOptions = this._gql();
2525
2395
  const wrappedResponse = new ResponseWrapper(response, url, method, graphQLOptions);
2526
- return await this.runResponseInterceptors(wrappedResponse);
2396
+ return await this._runResI(wrappedResponse);
2527
2397
  }
2528
2398
  catch (error) {
2529
2399
  // Convert to RequestError if needed
2530
- let requestError;
2531
- if (error instanceof RequestError) {
2532
- requestError = error;
2533
- }
2534
- else {
2535
- const errorObj = error instanceof Error ? error : new Error(String(error));
2536
- requestError = RequestError.networkError(url, method, errorObj);
2537
- }
2400
+ const requestError = error instanceof RequestError ? error : RequestError.networkError(url, method, toError(error));
2538
2401
  // Run error interceptors
2539
- const interceptorResult = await this.runErrorInterceptors(requestError);
2402
+ const interceptorResult = await this._runErrI(requestError);
2540
2403
  // If error interceptor returned a ResponseWrapper, recover from error
2541
2404
  if (interceptorResult instanceof ResponseWrapper) {
2542
2405
  return interceptorResult;
@@ -2553,12 +2416,9 @@ class BaseRequest {
2553
2416
  * Base class for requests that can have a body (POST, PUT, PATCH)
2554
2417
  */
2555
2418
  class BodyRequest extends BaseRequest {
2556
- body;
2557
- bodyType;
2558
- graphQLOptions = undefined;
2559
- constructor(url) {
2560
- super(url);
2561
- }
2419
+ _body;
2420
+ _bodyType;
2421
+ _gqlOpts = undefined;
2562
2422
  /**
2563
2423
  * Sets the request body. Automatically detects the body type and sets appropriate Content-Type header.
2564
2424
  * Supports JSON objects/arrays, strings, FormData, Blob, ArrayBuffer, URLSearchParams, and ReadableStream.
@@ -2595,11 +2455,11 @@ class BodyRequest extends BaseRequest {
2595
2455
  * ```
2596
2456
  */
2597
2457
  withBody(body) {
2598
- this.body = body;
2458
+ this._body = body;
2599
2459
  // Set body type and validate
2600
2460
  if (typeof body === "string") {
2601
- this.bodyType = BodyType.STRING;
2602
- this.setContentTypeIfNeeded("text/plain");
2461
+ this._bodyType = BodyType.STRING;
2462
+ this._setCT("text/plain");
2603
2463
  }
2604
2464
  else if (body !== null &&
2605
2465
  typeof body === "object" &&
@@ -2610,18 +2470,18 @@ class BodyRequest extends BaseRequest {
2610
2470
  ArrayBuffer.isView(body) || // Handles TypedArray and DataView
2611
2471
  body instanceof URLSearchParams ||
2612
2472
  body instanceof ReadableStream)) {
2613
- this.bodyType = BodyType.JSON;
2614
- this.setContentTypeIfNeeded("application/json");
2473
+ this._bodyType = BodyType.JSON;
2474
+ this._setCT("application/json");
2615
2475
  // Validate JSON is stringifiable early
2616
2476
  try {
2617
2477
  JSON.stringify(body);
2618
2478
  }
2619
2479
  catch (error) {
2620
- throw new RequestError(`Bad JSON: ${error instanceof Error ? error.message : String(error)}`, this.url, this.method);
2480
+ throw new RequestError(`Bad JSON: ${errorMessage(error)}`, this._url, this._method);
2621
2481
  }
2622
2482
  }
2623
2483
  else {
2624
- this.bodyType = BodyType.BINARY;
2484
+ this._bodyType = BodyType.BINARY;
2625
2485
  }
2626
2486
  return this;
2627
2487
  }
@@ -2664,25 +2524,25 @@ class BodyRequest extends BaseRequest {
2664
2524
  */
2665
2525
  withGraphQL(query, variables, options) {
2666
2526
  if (typeof query !== "string" || query.length === 0) {
2667
- throw new RequestError("Bad query", this.url, this.method);
2527
+ throw new RequestError("Bad query", this._url, this._method);
2668
2528
  }
2669
2529
  const graphQLBody = {
2670
2530
  query: query,
2671
2531
  };
2672
2532
  if (variables !== undefined) {
2673
2533
  if (typeof variables !== "object" || variables === null || Array.isArray(variables)) {
2674
- throw new RequestError("Bad vars", this.url, this.method);
2534
+ throw new RequestError("Bad vars", this._url, this._method);
2675
2535
  }
2676
2536
  graphQLBody.variables = variables;
2677
2537
  }
2678
2538
  // Store GraphQL options if provided
2679
2539
  if (options !== undefined) {
2680
2540
  if (typeof options !== "object" || options === null || Array.isArray(options)) {
2681
- throw new RequestError("Bad opts", this.url, this.method);
2541
+ throw new RequestError("Bad opts", this._url, this._method);
2682
2542
  }
2683
2543
  // Store only the known GraphQL options properties
2684
2544
  const opts = options;
2685
- this.graphQLOptions = {
2545
+ this._gqlOpts = {
2686
2546
  throwOnError: typeof opts.throwOnError === "boolean" ? opts.throwOnError : undefined,
2687
2547
  };
2688
2548
  }
@@ -2691,26 +2551,26 @@ class BodyRequest extends BaseRequest {
2691
2551
  JSON.stringify(graphQLBody);
2692
2552
  }
2693
2553
  catch (error) {
2694
- throw new RequestError(`Bad JSON: ${error instanceof Error ? error.message : String(error)}`, this.url, this.method);
2554
+ throw new RequestError(`Bad JSON: ${errorMessage(error)}`, this._url, this._method);
2695
2555
  }
2696
- this.body = graphQLBody;
2697
- this.bodyType = BodyType.JSON;
2698
- this.setContentTypeIfNeeded("application/json");
2556
+ this._body = graphQLBody;
2557
+ this._bodyType = BodyType.JSON;
2558
+ this._setCT("application/json");
2699
2559
  return this;
2700
2560
  }
2701
2561
  /**
2702
2562
  * Check if Content-Type header is already set (case-insensitive)
2703
2563
  */
2704
- hasContentType() {
2705
- const headers = this.requestOptions.headers;
2564
+ _hasCT() {
2565
+ const headers = this._opts.headers;
2706
2566
  if (typeof headers === "object" && headers !== null) {
2707
2567
  const headersObj = headers;
2708
2568
  return Object.keys(headersObj).some(header => header.toLowerCase() === "content-type");
2709
2569
  }
2710
2570
  return false;
2711
2571
  }
2712
- setContentTypeIfNeeded(contentType) {
2713
- if (!this.hasContentType()) {
2572
+ _setCT(contentType) {
2573
+ if (!this._hasCT()) {
2714
2574
  this.withContentType(contentType);
2715
2575
  }
2716
2576
  }
@@ -2718,24 +2578,24 @@ class BodyRequest extends BaseRequest {
2718
2578
  * Get the GraphQL options if set
2719
2579
  * @returns The GraphQL options or undefined
2720
2580
  */
2721
- getGraphQLOptions() {
2722
- return this.graphQLOptions;
2581
+ _gql() {
2582
+ return this._gqlOpts;
2723
2583
  }
2724
2584
  /**
2725
2585
  * Execute the request and return the ResponseWrapper
2726
2586
  * Overrides the base implementation to add body handling
2727
2587
  */
2728
2588
  async getResponse() {
2729
- if (this.body !== undefined) {
2589
+ if (this._body !== undefined) {
2730
2590
  // Remove previous body if it exists
2731
- if (this.requestOptions.body)
2732
- delete this.requestOptions.body;
2591
+ if (this._opts.body)
2592
+ delete this._opts.body;
2733
2593
  // Process the body based on its type
2734
- if (this.bodyType === BodyType.JSON) {
2735
- this.requestOptions.body = JSON.stringify(this.body);
2594
+ if (this._bodyType === BodyType.JSON) {
2595
+ this._opts.body = JSON.stringify(this._body);
2736
2596
  }
2737
2597
  else {
2738
- this.requestOptions.body = this.body;
2598
+ this._opts.body = this._body;
2739
2599
  }
2740
2600
  }
2741
2601
  return super.getResponse();
@@ -2752,10 +2612,7 @@ class BodyRequest extends BaseRequest {
2752
2612
  * const data = await request.getData();
2753
2613
  */
2754
2614
  class GetRequest extends BaseRequest {
2755
- method = exports.HttpMethod.GET;
2756
- constructor(url) {
2757
- super(url);
2758
- }
2615
+ _method = HttpMethod.GET;
2759
2616
  }
2760
2617
  /**
2761
2618
  * HTTP HEAD request implementation
@@ -2766,10 +2623,7 @@ class GetRequest extends BaseRequest {
2766
2623
  * const response = await request.getResponse();
2767
2624
  */
2768
2625
  class HeadRequest extends BaseRequest {
2769
- method = exports.HttpMethod.HEAD;
2770
- constructor(url) {
2771
- super(url);
2772
- }
2626
+ _method = HttpMethod.HEAD;
2773
2627
  }
2774
2628
  /**
2775
2629
  * HTTP OPTIONS request implementation
@@ -2780,10 +2634,7 @@ class HeadRequest extends BaseRequest {
2780
2634
  * const response = await request.getResponse();
2781
2635
  */
2782
2636
  class OptionsRequest extends BaseRequest {
2783
- method = exports.HttpMethod.OPTIONS;
2784
- constructor(url) {
2785
- super(url);
2786
- }
2637
+ _method = HttpMethod.OPTIONS;
2787
2638
  }
2788
2639
  /**
2789
2640
  * HTTP DELETE request implementation
@@ -2794,10 +2645,7 @@ class OptionsRequest extends BaseRequest {
2794
2645
  * await request.getData();
2795
2646
  */
2796
2647
  class DeleteRequest extends BaseRequest {
2797
- method = exports.HttpMethod.DELETE;
2798
- constructor(url) {
2799
- super(url);
2800
- }
2648
+ _method = HttpMethod.DELETE;
2801
2649
  }
2802
2650
  /**
2803
2651
  * HTTP POST request implementation
@@ -2809,10 +2657,7 @@ class DeleteRequest extends BaseRequest {
2809
2657
  * const data = await request.getData();
2810
2658
  */
2811
2659
  class PostRequest extends BodyRequest {
2812
- method = exports.HttpMethod.POST;
2813
- constructor(url) {
2814
- super(url);
2815
- }
2660
+ _method = HttpMethod.POST;
2816
2661
  }
2817
2662
  /**
2818
2663
  * HTTP PUT request implementation
@@ -2824,10 +2669,7 @@ class PostRequest extends BodyRequest {
2824
2669
  * const data = await request.getData();
2825
2670
  */
2826
2671
  class PutRequest extends BodyRequest {
2827
- method = exports.HttpMethod.PUT;
2828
- constructor(url) {
2829
- super(url);
2830
- }
2672
+ _method = HttpMethod.PUT;
2831
2673
  }
2832
2674
  /**
2833
2675
  * HTTP PATCH request implementation
@@ -2839,10 +2681,7 @@ class PutRequest extends BodyRequest {
2839
2681
  * const data = await request.getData();
2840
2682
  */
2841
2683
  class PatchRequest extends BodyRequest {
2842
- method = exports.HttpMethod.PATCH;
2843
- constructor(url) {
2844
- super(url);
2845
- }
2684
+ _method = HttpMethod.PATCH;
2846
2685
  }
2847
2686
 
2848
2687
  /**
@@ -2954,73 +2793,60 @@ function options(url) {
2954
2793
  * Internal API builder implementation.
2955
2794
  */
2956
2795
  class ApiBuilderImpl {
2957
- baseURL;
2958
- modifiers = [];
2959
- proxy;
2796
+ _baseURL;
2797
+ _mods = [];
2798
+ _proxy;
2960
2799
  withBaseURL(baseURL) {
2961
- this.baseURL = baseURL;
2962
- return this.getProxy();
2800
+ this._baseURL = baseURL;
2801
+ return this._getProxy();
2963
2802
  }
2964
- resolveURL(url) {
2803
+ _resolve(url) {
2965
2804
  if (!url)
2966
- return this.baseURL || "";
2805
+ return this._baseURL || "";
2967
2806
  if (/^https?:\/\//.test(url))
2968
2807
  return url;
2969
- if (!this.baseURL)
2808
+ if (!this._baseURL)
2970
2809
  return url;
2971
- return this.baseURL.replace(/\/$/, "") + (url[0] === "/" ? url : "/" + url);
2810
+ return this._baseURL.replace(/\/$/, "") + (url[0] === "/" ? url : "/" + url);
2972
2811
  }
2973
- applyModifiers(request) {
2974
- if (this.modifiers)
2975
- for (const modifier of this.modifiers)
2976
- modifier(request);
2812
+ _new(Ctor, url) {
2813
+ const request = new Ctor(this._resolve(url));
2814
+ for (const modifier of this._mods)
2815
+ modifier(request);
2816
+ return request;
2977
2817
  }
2978
2818
  get(url) {
2979
- const request = new GetRequest(this.resolveURL(url));
2980
- this.applyModifiers(request);
2981
- return request;
2819
+ return this._new(GetRequest, url);
2982
2820
  }
2983
2821
  post(url) {
2984
- const request = new PostRequest(this.resolveURL(url));
2985
- this.applyModifiers(request);
2986
- return request;
2822
+ return this._new(PostRequest, url);
2987
2823
  }
2988
2824
  put(url) {
2989
- const request = new PutRequest(this.resolveURL(url));
2990
- this.applyModifiers(request);
2991
- return request;
2825
+ return this._new(PutRequest, url);
2992
2826
  }
2993
2827
  del(url) {
2994
- const request = new DeleteRequest(this.resolveURL(url));
2995
- this.applyModifiers(request);
2996
- return request;
2828
+ return this._new(DeleteRequest, url);
2997
2829
  }
2998
2830
  patch(url) {
2999
- const request = new PatchRequest(this.resolveURL(url));
3000
- this.applyModifiers(request);
3001
- return request;
2831
+ return this._new(PatchRequest, url);
3002
2832
  }
3003
2833
  head(url) {
3004
- const request = new HeadRequest(this.resolveURL(url));
3005
- this.applyModifiers(request);
3006
- return request;
2834
+ return this._new(HeadRequest, url);
3007
2835
  }
3008
2836
  options(url) {
3009
- const request = new OptionsRequest(this.resolveURL(url));
3010
- this.applyModifiers(request);
3011
- return request;
2837
+ return this._new(OptionsRequest, url);
3012
2838
  }
3013
- addModifier(modifier) {
3014
- this.modifiers.push(modifier);
3015
- return this.getProxy();
2839
+ _add(modifier) {
2840
+ this._mods.push(modifier);
2841
+ return this._getProxy();
3016
2842
  }
3017
- getProxy() {
3018
- if (!this.proxy) {
3019
- this.proxy = this.createProxy();
2843
+ _getProxy() {
2844
+ if (!this._proxy) {
2845
+ this._proxy = this._mkProxy();
3020
2846
  }
3021
- return this.proxy;
2847
+ return this._proxy;
3022
2848
  }
3023
- createProxy() {
2849
+ _mkProxy() {
3024
2850
  const disallowedMethods = new Set(["withBody", "withGraphQL", "withAbortController"]);
3025
2851
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
3026
2852
  return new Proxy(this, {
@@ -3042,7 +2868,7 @@ class ApiBuilderImpl {
3042
2868
  // If it's a 'with...' method or other chainable method, create a modifier for it
3043
2869
  if (typeof prop === "string" && (prop.startsWith("with") || prop === "onRetry")) {
3044
2870
  return (...args) => {
3045
- return implTarget.addModifier((request) => {
2871
+ return implTarget._add((request) => {
3046
2872
  const method = request[prop];
3047
2873
  if (typeof method === "function") {
3048
2874
  method.apply(request, args);
@@ -3057,7 +2883,7 @@ class ApiBuilderImpl {
3057
2883
  });
3058
2884
  }
3059
2885
  static create() {
3060
- return new ApiBuilderImpl().getProxy();
2886
+ return new ApiBuilderImpl()._getProxy();
3061
2887
  }
3062
2888
  }
3063
2889
  /**
@@ -3138,16 +2964,24 @@ const create = {
3138
2964
  config: Config.getInstance(),
3139
2965
  };
3140
2966
 
2967
+ exports.CacheMode = CacheMode;
3141
2968
  exports.CookieUtils = CookieUtils;
2969
+ exports.CredentialsPolicy = CredentialsPolicy;
3142
2970
  exports.DeleteRequest = DeleteRequest;
3143
2971
  exports.GetRequest = GetRequest;
3144
2972
  exports.HeadRequest = HeadRequest;
2973
+ exports.HttpMethod = HttpMethod;
3145
2974
  exports.OptionsRequest = OptionsRequest;
3146
2975
  exports.PatchRequest = PatchRequest;
3147
2976
  exports.PostRequest = PostRequest;
3148
2977
  exports.PutRequest = PutRequest;
2978
+ exports.RedirectMode = RedirectMode;
2979
+ exports.ReferrerPolicy = ReferrerPolicy;
3149
2980
  exports.RequestError = RequestError;
2981
+ exports.RequestMode = RequestMode;
2982
+ exports.RequestPriority = RequestPriority;
3150
2983
  exports.ResponseWrapper = ResponseWrapper;
2984
+ exports.SameSitePolicy = SameSitePolicy;
3151
2985
  exports.createApi = api;
3152
2986
  exports.createDelete = del;
3153
2987
  exports.createGet = get;