create-request 1.4.3-rc.4 → 1.5.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.
@@ -146,8 +146,8 @@ class RequestError extends Error {
146
146
  this.method = method;
147
147
  this.status = options.status;
148
148
  this.response = options.response;
149
- this.isTimeout = options.isTimeout;
150
- this.isAborted = options.isAborted;
149
+ this.isTimeout = !!options.isTimeout;
150
+ this.isAborted = !!options.isAborted;
151
151
  // For better stack traces in modern environments
152
152
  if (Error.captureStackTrace) {
153
153
  Error.captureStackTrace(this, RequestError);
@@ -169,7 +169,7 @@ class RequestError extends Error {
169
169
  * ```
170
170
  */
171
171
  static timeout(url, method, timeoutMs) {
172
- return new RequestError(`Timeout ${timeoutMs}ms`, url, method, {
172
+ return new RequestError(`Timeout:${timeoutMs}`, url, method, {
173
173
  isTimeout: true,
174
174
  });
175
175
  }
@@ -248,16 +248,16 @@ class RequestError extends Error {
248
248
  // Check for connection errors (but not timeout errors)
249
249
  const isConnectionError = !isTimeoutError && (errorCode === "ECONNREFUSED" || errorCode === "ECONNRESET" || stack.includes("ECONNREFUSED") || stack.includes("connect"));
250
250
  if (isTimeoutError) {
251
- message = `Timeout ${url}`;
251
+ message = `Timeout:${url}`;
252
252
  }
253
253
  else if (isDnsError) {
254
- message = `DNS error ${url}`;
254
+ message = `DNS:${url}`;
255
255
  }
256
256
  else if (isConnectionError) {
257
- message = `Connection refused ${url}`;
257
+ message = `Conn:${url}`;
258
258
  }
259
259
  else {
260
- message = `Network error ${url}`;
260
+ message = `Net:${url}`;
261
261
  }
262
262
  }
263
263
  const error = new RequestError(message, url, method, {
@@ -367,7 +367,7 @@ class ResponseWrapper {
367
367
  */
368
368
  checkBodyNotConsumed() {
369
369
  if (this.response.bodyUsed) {
370
- throw new RequestError("Body already consumed", this.url || "", this.method || "", {
370
+ throw new RequestError("Body used", this.url || "", this.method || "", {
371
371
  status: this.response.status,
372
372
  response: this.response,
373
373
  });
@@ -409,7 +409,7 @@ class ResponseWrapper {
409
409
  return String(x);
410
410
  });
411
411
  const errorMessage = errorMessages.join(", ");
412
- throw new RequestError(`GraphQL errors: ${errorMessage}`, this.url || "", this.method || "", {
412
+ throw new RequestError(`GQL: ${errorMessage}`, this.url || "", this.method || "", {
413
413
  status: this.response.status,
414
414
  response: this.response,
415
415
  });
@@ -449,8 +449,7 @@ class ResponseWrapper {
449
449
  if (error instanceof RequestError) {
450
450
  throw error;
451
451
  }
452
- const errorMessage = error instanceof Error ? error.message : String(error);
453
- throw new RequestError(`Invalid JSON: ${errorMessage}`, this.url || "", this.method || "", {
452
+ throw new RequestError(`Bad JSON: ${error instanceof Error ? error.message : String(error)}`, this.url || "", this.method || "", {
454
453
  status: this.response.status,
455
454
  response: this.response,
456
455
  });
@@ -479,8 +478,7 @@ class ResponseWrapper {
479
478
  return text;
480
479
  }
481
480
  catch (e) {
482
- const errorMessage = e instanceof Error ? e.message : String(e);
483
- throw new RequestError(`Read failed: ${errorMessage}`, this.url || "", this.method || "", {
481
+ throw new RequestError(`Read: ${e instanceof Error ? e.message : String(e)}`, this.url || "", this.method || "", {
484
482
  status: this.response.status,
485
483
  response: this.response,
486
484
  });
@@ -511,8 +509,7 @@ class ResponseWrapper {
511
509
  return blob;
512
510
  }
513
511
  catch (e) {
514
- const errorMessage = e instanceof Error ? e.message : String(e);
515
- throw new RequestError(`Read failed: ${errorMessage}`, this.url || "", this.method || "", {
512
+ throw new RequestError(`Read: ${e instanceof Error ? e.message : String(e)}`, this.url || "", this.method || "", {
516
513
  status: this.response.status,
517
514
  response: this.response,
518
515
  });
@@ -544,8 +541,7 @@ class ResponseWrapper {
544
541
  return arrayBuffer;
545
542
  }
546
543
  catch (e) {
547
- const errorMessage = e instanceof Error ? e.message : String(e);
548
- throw new RequestError(`Read failed: ${errorMessage}`, this.url || "", this.method || "", {
544
+ throw new RequestError(`Read: ${e instanceof Error ? e.message : String(e)}`, this.url || "", this.method || "", {
549
545
  status: this.response.status,
550
546
  response: this.response,
551
547
  });
@@ -611,8 +607,7 @@ class ResponseWrapper {
611
607
  }
612
608
  // Enhance selector errors with context
613
609
  if (selector) {
614
- const errorMessage = error instanceof Error ? error.message : String(error);
615
- throw new RequestError(`Data selector failed: ${errorMessage}`, this.url || "", this.method || "", {
610
+ throw new RequestError(`Selector: ${error instanceof Error ? error.message : String(error)}`, this.url || "", this.method || "", {
616
611
  status: this.response.status,
617
612
  response: this.response,
618
613
  });
@@ -1058,10 +1053,11 @@ class BaseRequest {
1058
1053
  return Object.assign(callable, fluent);
1059
1054
  }
1060
1055
  validateUrl(url) {
1056
+ const errorMessage = "Bad URL";
1061
1057
  if (!url?.trim())
1062
- throw new RequestError("Invalid URL", url, this.method);
1058
+ throw new RequestError(errorMessage, url, this.method);
1063
1059
  if (url.includes("\0") || url.includes("\r") || url.includes("\n")) {
1064
- throw new RequestError("Invalid URL", url, this.method);
1060
+ throw new RequestError(errorMessage, url, this.method);
1065
1061
  }
1066
1062
  const trimmed = url.trim();
1067
1063
  if (/^https?:\/\//.test(trimmed)) {
@@ -1069,7 +1065,7 @@ class BaseRequest {
1069
1065
  new URL(trimmed);
1070
1066
  }
1071
1067
  catch {
1072
- throw new RequestError("Invalid URL", trimmed, this.method);
1068
+ throw new RequestError(errorMessage, trimmed, this.method);
1073
1069
  }
1074
1070
  }
1075
1071
  }
@@ -1125,7 +1121,7 @@ class BaseRequest {
1125
1121
  */
1126
1122
  withTimeout(timeout) {
1127
1123
  if (!Number.isFinite(timeout) || timeout <= 0)
1128
- throw new RequestError("Invalid timeout", this.url, this.method);
1124
+ throw new RequestError("Bad timeout", this.url, this.method);
1129
1125
  this.requestOptions.timeout = timeout;
1130
1126
  return this;
1131
1127
  }
@@ -1164,24 +1160,24 @@ class BaseRequest {
1164
1160
  withRetries(retries) {
1165
1161
  if (typeof retries === "number") {
1166
1162
  if (!Number.isInteger(retries) || retries < 0) {
1167
- throw new RequestError(`Invalid retries: ${retries}`, this.url, this.method);
1163
+ throw new RequestError(`Bad retries: ${retries}`, this.url, this.method);
1168
1164
  }
1169
1165
  this.requestOptions.retries = retries;
1170
1166
  }
1171
1167
  else {
1172
1168
  // Validate RetryConfig
1173
1169
  if (!Number.isInteger(retries.attempts) || retries.attempts < 0) {
1174
- throw new RequestError(`Invalid attempts: ${retries.attempts}`, this.url, this.method);
1170
+ throw new RequestError(`Bad attempts: ${retries.attempts}`, this.url, this.method);
1175
1171
  }
1176
1172
  // Validate delay if provided
1177
1173
  if (retries.delay !== undefined) {
1178
1174
  if (typeof retries.delay === "number") {
1179
1175
  if (!Number.isFinite(retries.delay) || retries.delay < 0) {
1180
- throw new RequestError(`Invalid delay: ${retries.delay}`, this.url, this.method);
1176
+ throw new RequestError(`Bad delay: ${retries.delay}`, this.url, this.method);
1181
1177
  }
1182
1178
  }
1183
1179
  else if (typeof retries.delay !== "function") {
1184
- throw new RequestError(`Invalid delay: ${typeof retries.delay}`, this.url, this.method);
1180
+ throw new RequestError(`Bad delay: ${typeof retries.delay}`, this.url, this.method);
1185
1181
  }
1186
1182
  }
1187
1183
  this.requestOptions.retries = retries;
@@ -1664,7 +1660,7 @@ class BaseRequest {
1664
1660
  if (typeof Buffer !== "undefined")
1665
1661
  return Buffer.from(str).toString("base64");
1666
1662
  // Fallback (should never happen in modern environments)
1667
- throw new RequestError("Encoding not supported", this.url, this.method);
1663
+ throw new RequestError("No encoder", this.url, this.method);
1668
1664
  }
1669
1665
  /**
1670
1666
  * Sets a Bearer token for authentication.
@@ -1948,6 +1944,24 @@ class BaseRequest {
1948
1944
  const response = await this.getResponse();
1949
1945
  return response.getBlob();
1950
1946
  }
1947
+ /**
1948
+ * Execute the request and get the response body as an ArrayBuffer.
1949
+ * Useful for processing binary data at a low level.
1950
+ *
1951
+ * @returns A promise that resolves to the response body as an ArrayBuffer
1952
+ * @throws {RequestError} When the request fails or reading the response fails
1953
+ *
1954
+ * @example
1955
+ * ```typescript
1956
+ * const buffer = await request.getArrayBuffer();
1957
+ * const uint8Array = new Uint8Array(buffer);
1958
+ * // Process the binary data
1959
+ * ```
1960
+ */
1961
+ async getArrayBuffer() {
1962
+ const response = await this.getResponse();
1963
+ return response.getArrayBuffer();
1964
+ }
1951
1965
  /**
1952
1966
  * Execute the request and get the response body as a ReadableStream.
1953
1967
  * Note: Unlike other methods, streams cannot be cached. The body can only be consumed once.
@@ -2083,7 +2097,7 @@ class BaseRequest {
2083
2097
  const delay = typeof retriesConfig.delay === "function" ? retriesConfig.delay({ attempt: attempt + 1, error: requestError }) : retriesConfig.delay;
2084
2098
  // Validate delay result
2085
2099
  if (typeof delay !== "number" || !Number.isFinite(delay) || delay < 0) {
2086
- throw new RequestError(`Invalid delay: ${delay}`, url, method);
2100
+ throw new RequestError(`Bad delay: ${delay}`, url, method);
2087
2101
  }
2088
2102
  // Wait for the delay
2089
2103
  if (delay > 0) {
@@ -2114,8 +2128,7 @@ class BaseRequest {
2114
2128
  currentConfig = result;
2115
2129
  }
2116
2130
  catch (error) {
2117
- const errorMessage = error instanceof Error ? error.message : String(error);
2118
- throw new RequestError(`Req Interceptor failed: ${errorMessage}`, currentConfig.url, currentConfig.method);
2131
+ throw new RequestError(`ReqI: ${error instanceof Error ? error.message : String(error)}`, currentConfig.url, currentConfig.method);
2119
2132
  }
2120
2133
  }
2121
2134
  return currentConfig;
@@ -2129,17 +2142,14 @@ class BaseRequest {
2129
2142
  const globalConfig = Config.getInstance();
2130
2143
  const globalInterceptors = globalConfig.getResponseInterceptors();
2131
2144
  // Per-request in order, then global in reverse
2132
- const allInterceptors = [...this.responseInterceptors, ...globalInterceptors.reverse()];
2145
+ const allInterceptors = [...this.responseInterceptors, ...[...globalInterceptors].reverse()];
2133
2146
  let currentResponse = response;
2134
2147
  for (let i = 0; i < allInterceptors.length; i++) {
2135
2148
  try {
2136
2149
  currentResponse = await allInterceptors[i](currentResponse);
2137
2150
  }
2138
2151
  catch (error) {
2139
- const errorMessage = error instanceof Error ? error.message : String(error);
2140
- const url = currentResponse.url || "";
2141
- const method = currentResponse.method || "";
2142
- throw new RequestError(`Res Interceptor failed: ${errorMessage}`, url, method);
2152
+ throw new RequestError(`ResI: ${error instanceof Error ? error.message : String(error)}`, currentResponse.url || "", currentResponse.method || "");
2143
2153
  }
2144
2154
  }
2145
2155
  return currentResponse;
@@ -2153,7 +2163,7 @@ class BaseRequest {
2153
2163
  const globalConfig = Config.getInstance();
2154
2164
  const globalInterceptors = globalConfig.getErrorInterceptors();
2155
2165
  // Per-request in order, then global in reverse
2156
- const allInterceptors = [...this.errorInterceptors, ...globalInterceptors.reverse()];
2166
+ const allInterceptors = [...this.errorInterceptors, ...[...globalInterceptors].reverse()];
2157
2167
  let currentError = error;
2158
2168
  for (let i = 0; i < allInterceptors.length; i++) {
2159
2169
  try {
@@ -2170,10 +2180,10 @@ class BaseRequest {
2170
2180
  currentError = interceptorError;
2171
2181
  }
2172
2182
  else {
2173
- const errorMessage = interceptorError instanceof Error ? interceptorError.message : String(interceptorError);
2183
+ const em = interceptorError instanceof Error ? interceptorError.message : String(interceptorError);
2174
2184
  // Always wrap in RequestError when we have context
2175
2185
  if (currentError instanceof RequestError) {
2176
- currentError = new RequestError(`Err Interceptor ${i + 1} failed: ${errorMessage}`, currentError.url, currentError.method, {
2186
+ currentError = new RequestError(`ErrI${i + 1}: ${em}`, currentError.url, currentError.method, {
2177
2187
  status: currentError.status,
2178
2188
  response: currentError.response,
2179
2189
  });
@@ -2350,6 +2360,11 @@ class BaseRequest {
2350
2360
  // It will check for timeout patterns as a safety net (useful for external AbortControllers)
2351
2361
  throw RequestError.networkError(url, method, errorObj);
2352
2362
  }
2363
+ // Status 0 indicates the request failed before receiving a proper HTTP response
2364
+ // (e.g., CORS errors, network failures that don't throw). Treat as network error.
2365
+ if (response.status === 0) {
2366
+ throw RequestError.networkError(url, method, new Error("Failed with status 0 (network error or CORS blocked)"));
2367
+ }
2353
2368
  if (!response.ok) {
2354
2369
  throw RequestError.fromResponse(response, url, method);
2355
2370
  }
@@ -2449,8 +2464,7 @@ class BodyRequest extends BaseRequest {
2449
2464
  JSON.stringify(body);
2450
2465
  }
2451
2466
  catch (error) {
2452
- const errorMessage = error instanceof Error ? error.message : String(error);
2453
- throw new RequestError(`Invalid JSON: ${errorMessage}`, this.url, this.method);
2467
+ throw new RequestError(`Bad JSON: ${error instanceof Error ? error.message : String(error)}`, this.url, this.method);
2454
2468
  }
2455
2469
  }
2456
2470
  else {
@@ -2497,21 +2511,21 @@ class BodyRequest extends BaseRequest {
2497
2511
  */
2498
2512
  withGraphQL(query, variables, options) {
2499
2513
  if (typeof query !== "string" || query.length === 0) {
2500
- throw new RequestError("Invalid query", this.url, this.method);
2514
+ throw new RequestError("Bad query", this.url, this.method);
2501
2515
  }
2502
2516
  const graphQLBody = {
2503
2517
  query: query,
2504
2518
  };
2505
2519
  if (variables !== undefined) {
2506
2520
  if (typeof variables !== "object" || variables === null || Array.isArray(variables)) {
2507
- throw new RequestError("Invalid vars", this.url, this.method);
2521
+ throw new RequestError("Bad vars", this.url, this.method);
2508
2522
  }
2509
2523
  graphQLBody.variables = variables;
2510
2524
  }
2511
2525
  // Store GraphQL options if provided
2512
2526
  if (options !== undefined) {
2513
2527
  if (typeof options !== "object" || options === null || Array.isArray(options)) {
2514
- throw new RequestError("Invalid options", this.url, this.method);
2528
+ throw new RequestError("Bad opts", this.url, this.method);
2515
2529
  }
2516
2530
  // Store only the known GraphQL options properties
2517
2531
  const opts = options;
@@ -2524,8 +2538,7 @@ class BodyRequest extends BaseRequest {
2524
2538
  JSON.stringify(graphQLBody);
2525
2539
  }
2526
2540
  catch (error) {
2527
- const errorMessage = error instanceof Error ? error.message : String(error);
2528
- throw new RequestError(`Invalid JSON: ${errorMessage}`, this.url, this.method);
2541
+ throw new RequestError(`Bad JSON: ${error instanceof Error ? error.message : String(error)}`, this.url, this.method);
2529
2542
  }
2530
2543
  this.body = graphQLBody;
2531
2544
  this.bodyType = BodyType.JSON;
@@ -2639,7 +2652,7 @@ class DeleteRequest extends BaseRequest {
2639
2652
  *
2640
2653
  * @example
2641
2654
  * const request = new PostRequest('/api/users')
2642
- * .withJson({ name: 'John', email: 'john@example.com' });
2655
+ * .withBody({ name: 'John', email: 'john@example.com' });
2643
2656
  * const data = await request.getData();
2644
2657
  */
2645
2658
  class PostRequest extends BodyRequest {
@@ -2654,7 +2667,7 @@ class PostRequest extends BodyRequest {
2654
2667
  *
2655
2668
  * @example
2656
2669
  * const request = new PutRequest('/api/users/123')
2657
- * .withJson({ id: '123', name: 'John', email: 'john@example.com' });
2670
+ * .withBody({ id: '123', name: 'John', email: 'john@example.com' });
2658
2671
  * const data = await request.getData();
2659
2672
  */
2660
2673
  class PutRequest extends BodyRequest {
@@ -2669,7 +2682,7 @@ class PutRequest extends BodyRequest {
2669
2682
  *
2670
2683
  * @example
2671
2684
  * const request = new PatchRequest('/api/users/123')
2672
- * .withJson({ email: 'new.email@example.com' });
2685
+ * .withBody({ email: 'new.email@example.com' });
2673
2686
  * const data = await request.getData();
2674
2687
  */
2675
2688
  class PatchRequest extends BodyRequest {
@@ -2703,7 +2716,7 @@ function get(url) {
2703
2716
  *
2704
2717
  * @example
2705
2718
  * const request = post('/api/users')
2706
- * .withJson({ name: 'John', email: 'john@example.com' });
2719
+ * .withBody({ name: 'John', email: 'john@example.com' });
2707
2720
  * const newUser = await request.getData();
2708
2721
  */
2709
2722
  function post(url) {
@@ -2718,7 +2731,7 @@ function post(url) {
2718
2731
  *
2719
2732
  * @example
2720
2733
  * const request = put('/api/users/123')
2721
- * .withJson({ name: 'John Updated', email: 'john@example.com' });
2734
+ * .withBody({ name: 'John Updated', email: 'john@example.com' });
2722
2735
  * const updatedUser = await request.getData();
2723
2736
  */
2724
2737
  function put(url) {
@@ -2747,7 +2760,7 @@ function del(url) {
2747
2760
  *
2748
2761
  * @example
2749
2762
  * const request = patch('/api/users/123')
2750
- * .withJson({ status: 'active' });
2763
+ * .withBody({ status: 'active' });
2751
2764
  * const patchedUser = await request.getData();
2752
2765
  */
2753
2766
  function patch(url) {
@@ -2785,267 +2798,155 @@ function options(url) {
2785
2798
  }
2786
2799
 
2787
2800
  /**
2788
- * Resolves a URL against a base URL.
2789
- * If the URL is absolute (starts with http:// or https://), it is returned as-is.
2790
- * Otherwise, it is resolved relative to the base URL.
2791
- *
2792
- * @param baseURL - The base URL to resolve against, or undefined if not set
2793
- * @param url - The URL to resolve, or undefined to return the base URL
2794
- * @returns The resolved absolute URL string
2795
- * @example
2796
- * resolveURL("https://api.example.com", "/users") // "https://api.example.com/users"
2797
- * resolveURL("https://api.example.com", "users") // "https://api.example.com/users"
2798
- * resolveURL("https://api.example.com", "https://other.com") // "https://other.com"
2799
- */
2800
- function resolveURL(baseURL, url) {
2801
- if (!url)
2802
- return baseURL || "";
2803
- if (!baseURL)
2804
- return url;
2805
- if (/^https?:\/\//.test(url))
2806
- return url;
2807
- try {
2808
- return new URL(url, baseURL.endsWith("/") ? baseURL : baseURL + "/").toString();
2809
- }
2810
- catch {
2811
- return baseURL.replace(/\/$/, "") + (url.startsWith("/") ? url : "/" + url);
2812
- }
2813
- }
2814
- /**
2815
- * API builder for creating configured API instances with default settings.
2816
- * Allows you to set default headers, timeouts, authentication, and other options
2817
- * that will be applied to all requests created through this builder.
2818
- *
2819
- * @example
2820
- * ```typescript
2821
- * const api = create.api()
2822
- * .withBaseURL("https://api.example.com")
2823
- * .withBearerToken("token123")
2824
- * .withTimeout(5000);
2825
- *
2826
- * // All requests will use the base URL, bearer token, and timeout
2827
- * await api.get("/users").getJson();
2828
- * await api.post("/posts").withBody({ title: "Hello" }).getJson();
2829
- * ```
2801
+ * Internal API builder implementation.
2830
2802
  */
2831
- class ApiBuilder {
2803
+ class ApiBuilderImpl {
2832
2804
  baseURL;
2833
- modifiers;
2834
- /**
2835
- * Sets the base URL for all requests created through this API builder.
2836
- * Relative URLs will be resolved against this base URL.
2837
- *
2838
- * @param baseURL - The base URL to use for all requests
2839
- * @returns The API builder instance for method chaining
2840
- * @example
2841
- * ```typescript
2842
- * const api = create.api().withBaseURL("https://api.example.com");
2843
- * await api.get("/users").getJson(); // Requests https://api.example.com/users
2844
- * ```
2845
- */
2805
+ modifiers = [];
2806
+ proxy;
2846
2807
  withBaseURL(baseURL) {
2847
2808
  this.baseURL = baseURL;
2848
- return this;
2809
+ return this.getProxy();
2849
2810
  }
2850
- /**
2851
- * Adds a modifier function that will be applied to all requests created through this builder.
2852
- *
2853
- * @private
2854
- * @param modifier - A function that modifies a request and returns it
2855
- * @returns The API builder instance for method chaining
2856
- */
2857
- addModifier(modifier) {
2858
- if (!this.modifiers)
2859
- this.modifiers = [];
2860
- this.modifiers.push(modifier);
2861
- return this;
2811
+ resolveURL(url) {
2812
+ if (!url)
2813
+ return this.baseURL || "";
2814
+ if (/^https?:\/\//.test(url))
2815
+ return url;
2816
+ if (!this.baseURL)
2817
+ return url;
2818
+ return this.baseURL.replace(/\/$/, "") + (url[0] === "/" ? url : "/" + url);
2862
2819
  }
2863
- /**
2864
- * Creates a GET request with the configured default settings.
2865
- *
2866
- * @param url - Optional URL path. If not provided, uses the base URL. If relative, resolves against base URL.
2867
- * @returns A GetRequest instance ready to be executed
2868
- * @example
2869
- * ```typescript
2870
- * const api = create.api().withBaseURL("https://api.example.com");
2871
- * await api.get("/users").getJson();
2872
- * await api.get("https://other.com/data").getJson(); // Absolute URL overrides base
2873
- * ```
2874
- */
2875
- get = (url) => {
2876
- const request = get(resolveURL(this.baseURL, url));
2820
+ applyModifiers(request) {
2877
2821
  if (this.modifiers)
2878
2822
  for (const modifier of this.modifiers)
2879
2823
  modifier(request);
2824
+ }
2825
+ get(url) {
2826
+ const request = new GetRequest(this.resolveURL(url));
2827
+ this.applyModifiers(request);
2880
2828
  return request;
2881
- };
2882
- /**
2883
- * Creates a POST request with the configured default settings.
2884
- *
2885
- * @param url - Optional URL path. If not provided, uses the base URL. If relative, resolves against base URL.
2886
- * @returns A PostRequest instance ready to be executed
2887
- * @example
2888
- * ```typescript
2889
- * const api = create.api().withBaseURL("https://api.example.com");
2890
- * await api.post("/users").withBody({ name: "John" }).getJson();
2891
- * ```
2892
- */
2893
- post = (url) => {
2894
- const request = post(resolveURL(this.baseURL, url));
2895
- if (this.modifiers)
2896
- for (const modifier of this.modifiers)
2897
- modifier(request);
2829
+ }
2830
+ post(url) {
2831
+ const request = new PostRequest(this.resolveURL(url));
2832
+ this.applyModifiers(request);
2898
2833
  return request;
2899
- };
2900
- /**
2901
- * Creates a PUT request with the configured default settings.
2902
- *
2903
- * @param url - Optional URL path. If not provided, uses the base URL. If relative, resolves against base URL.
2904
- * @returns A PutRequest instance ready to be executed
2905
- * @example
2906
- * ```typescript
2907
- * const api = create.api().withBaseURL("https://api.example.com");
2908
- * await api.put("/users/123").withBody({ name: "Jane" }).getJson();
2909
- * ```
2910
- */
2911
- put = (url) => {
2912
- const request = put(resolveURL(this.baseURL, url));
2913
- if (this.modifiers)
2914
- for (const modifier of this.modifiers)
2915
- modifier(request);
2834
+ }
2835
+ put(url) {
2836
+ const request = new PutRequest(this.resolveURL(url));
2837
+ this.applyModifiers(request);
2916
2838
  return request;
2917
- };
2918
- /**
2919
- * Creates a DELETE request with the configured default settings.
2920
- *
2921
- * @param url - Optional URL path. If not provided, uses the base URL. If relative, resolves against base URL.
2922
- * @returns A DeleteRequest instance ready to be executed
2923
- * @example
2924
- * ```typescript
2925
- * const api = create.api().withBaseURL("https://api.example.com");
2926
- * await api.del("/users/123").getResponse();
2927
- * ```
2928
- */
2929
- del = (url) => {
2930
- const request = del(resolveURL(this.baseURL, url));
2931
- if (this.modifiers)
2932
- for (const modifier of this.modifiers)
2933
- modifier(request);
2839
+ }
2840
+ del(url) {
2841
+ const request = new DeleteRequest(this.resolveURL(url));
2842
+ this.applyModifiers(request);
2934
2843
  return request;
2935
- };
2936
- /**
2937
- * Creates a PATCH request with the configured default settings.
2938
- *
2939
- * @param url - Optional URL path. If not provided, uses the base URL. If relative, resolves against base URL.
2940
- * @returns A PatchRequest instance ready to be executed
2941
- * @example
2942
- * ```typescript
2943
- * const api = create.api().withBaseURL("https://api.example.com");
2944
- * await api.patch("/users/123").withBody({ name: "Updated" }).getJson();
2945
- * ```
2946
- */
2947
- patch = (url) => {
2948
- const request = patch(resolveURL(this.baseURL, url));
2949
- if (this.modifiers)
2950
- for (const modifier of this.modifiers)
2951
- modifier(request);
2844
+ }
2845
+ patch(url) {
2846
+ const request = new PatchRequest(this.resolveURL(url));
2847
+ this.applyModifiers(request);
2952
2848
  return request;
2953
- };
2954
- /**
2955
- * Creates a HEAD request with the configured default settings.
2956
- *
2957
- * @param url - Optional URL path. If not provided, uses the base URL. If relative, resolves against base URL.
2958
- * @returns A HeadRequest instance ready to be executed
2959
- * @example
2960
- * ```typescript
2961
- * const api = create.api().withBaseURL("https://api.example.com");
2962
- * const response = await api.head("/users").getResponse();
2963
- * ```
2964
- */
2965
- head = (url) => {
2966
- const request = head(resolveURL(this.baseURL, url));
2967
- if (this.modifiers)
2968
- for (const modifier of this.modifiers)
2969
- modifier(request);
2849
+ }
2850
+ head(url) {
2851
+ const request = new HeadRequest(this.resolveURL(url));
2852
+ this.applyModifiers(request);
2970
2853
  return request;
2971
- };
2972
- /**
2973
- * Creates an OPTIONS request with the configured default settings.
2974
- *
2975
- * @param url - Optional URL path. If not provided, uses the base URL. If relative, resolves against base URL.
2976
- * @returns An OptionsRequest instance ready to be executed
2977
- * @example
2978
- * ```typescript
2979
- * const api = create.api().withBaseURL("https://api.example.com");
2980
- * await api.options("/users").getResponse();
2981
- * ```
2982
- */
2983
- options = (url) => {
2984
- const request = options(resolveURL(this.baseURL, url));
2985
- if (this.modifiers)
2986
- for (const modifier of this.modifiers)
2987
- modifier(request);
2854
+ }
2855
+ options(url) {
2856
+ const request = new OptionsRequest(this.resolveURL(url));
2857
+ this.applyModifiers(request);
2988
2858
  return request;
2989
- };
2990
- /**
2991
- * Creates a new ApiBuilder instance with a Proxy that enables dynamic method forwarding.
2992
- * The Proxy allows calling any `with*` method from BaseRequest on the API builder,
2993
- * which will apply that configuration to all requests created through this builder.
2994
- *
2995
- * @internal
2996
- */
2997
- constructor() {
2998
- const proxy = new Proxy(this, {
2859
+ }
2860
+ addModifier(modifier) {
2861
+ this.modifiers.push(modifier);
2862
+ return this.getProxy();
2863
+ }
2864
+ getProxy() {
2865
+ if (!this.proxy) {
2866
+ this.proxy = this.createProxy();
2867
+ }
2868
+ return this.proxy;
2869
+ }
2870
+ createProxy() {
2871
+ const disallowedMethods = new Set(["withBody", "withGraphQL", "withAbortController"]);
2872
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
2873
+ return new Proxy(this, {
2999
2874
  get(target, prop) {
3000
- const propertyValue = target[prop];
3001
- if (propertyValue !== undefined) {
3002
- if (typeof propertyValue === "function") {
3003
- return (...args) => {
3004
- const result = propertyValue.apply(target, args);
3005
- return result === target ? proxy : result;
3006
- };
3007
- }
3008
- return propertyValue;
2875
+ const implTarget = target;
2876
+ // Return undefined for disallowed methods
2877
+ if (typeof prop === "string" && disallowedMethods.has(prop)) {
2878
+ return undefined;
3009
2879
  }
3010
- if (typeof prop === "string" && prop.startsWith("with") && prop !== "withBaseURL") {
3011
- if (prop === "withAbortController" || prop === "withBody" || prop === "withGraphQL" || prop === "withQueryParam" || prop === "withQueryParams")
3012
- return undefined;
3013
- const prototypeMethod = BaseRequest.prototype[prop];
3014
- if (typeof prototypeMethod === "function") {
3015
- return (...args) => {
3016
- target.addModifier((request) => prototypeMethod.apply(request, args));
3017
- return proxy;
3018
- };
3019
- }
2880
+ // Check if it's an HTTP method - these should be called directly
2881
+ if (prop === "get" || prop === "post" || prop === "put" || prop === "del" || prop === "patch" || prop === "head" || prop === "options") {
2882
+ return implTarget[prop].bind(implTarget);
2883
+ }
2884
+ // Check if it's a configuration method that already exists
2885
+ if (prop === "withBaseURL") {
2886
+ return implTarget[prop].bind(implTarget);
3020
2887
  }
3021
- return undefined;
2888
+ // Check if the property exists on BaseRequest prototype
2889
+ // If it's a 'with...' method or other chainable method, create a modifier for it
2890
+ if (typeof prop === "string" && (prop.startsWith("with") || prop === "onRetry")) {
2891
+ return (...args) => {
2892
+ return implTarget.addModifier((request) => {
2893
+ const method = request[prop];
2894
+ if (typeof method === "function") {
2895
+ method.apply(request, args);
2896
+ }
2897
+ });
2898
+ };
2899
+ }
2900
+ // For other properties, return them directly if they exist
2901
+ const targetValue = implTarget[prop];
2902
+ return targetValue;
3022
2903
  },
3023
2904
  });
3024
- return proxy;
2905
+ }
2906
+ static create() {
2907
+ return new ApiBuilderImpl().getProxy();
3025
2908
  }
3026
2909
  }
3027
2910
  /**
3028
- * Creates a new API builder instance for configuring default request settings.
3029
- * The builder allows you to set base URLs, authentication, headers, timeouts,
3030
- * and other options that will be applied to all requests created through it.
2911
+ * Creates a new API builder for configuring default request settings.
2912
+ * The API builder allows you to set up a base URL, default headers, timeout,
2913
+ * and other configuration options that will be applied to all requests made through it.
2914
+ *
2915
+ * @returns A new API builder instance
3031
2916
  *
3032
- * @returns A new ApiBuilder instance with all configuration methods available
3033
2917
  * @example
3034
2918
  * ```typescript
3035
- * // Create an API instance with default configuration
3036
- * const api = create.api()
3037
- * .withBaseURL("https://api.example.com")
3038
- * .withBearerToken("your-token")
3039
- * .withTimeout(5000)
3040
- * .withHeaders({ "X-Custom": "value" });
2919
+ * // Create an API instance with defaults
2920
+ * const api = api()
2921
+ * .withBaseURL('https://api.example.com')
2922
+ * .withBearerToken('token123')
2923
+ * .withTimeout(5000);
3041
2924
  *
3042
2925
  * // All requests will use these defaults
3043
- * const users = await api.get("/users").getJson();
3044
- * const newUser = await api.post("/users").withBody({ name: "John" }).getJson();
2926
+ * const users = await api.get('/users').getJson();
2927
+ * const newUser = await api.post('/users').withBody({ name: 'John' }).getJson();
2928
+ * ```
2929
+ *
2930
+ * @example
2931
+ * ```typescript
2932
+ * // Use without URL when baseURL is set
2933
+ * const api = api().withBaseURL('https://api.example.com');
2934
+ * const data = await api.get().getJson(); // Requests to https://api.example.com
2935
+ * ```
2936
+ *
2937
+ * @example
2938
+ * ```typescript
2939
+ * // Override defaults per request
2940
+ * const api = api()
2941
+ * .withBaseURL('https://api.example.com')
2942
+ * .withTimeout(5000);
2943
+ *
2944
+ * // This request uses a longer timeout
2945
+ * await api.get('/slow-endpoint').withTimeout(30000).getJson();
3045
2946
  * ```
3046
2947
  */
3047
2948
  function api() {
3048
- return new ApiBuilder();
2949
+ return ApiBuilderImpl.create();
3049
2950
  }
3050
2951
 
3051
2952
  /**
@@ -3061,7 +2962,7 @@ function api() {
3061
2962
  *
3062
2963
  * // POST request with body
3063
2964
  * const newUser = await create.post('/api/users')
3064
- * .withJson({ name: 'John', email: 'john@example.com' })
2965
+ * .withBody({ name: 'John', email: 'john@example.com' })
3065
2966
  * .getJson();
3066
2967
  *
3067
2968
  * // Configure API instance with defaults
@@ -3094,13 +2995,13 @@ exports.PostRequest = PostRequest;
3094
2995
  exports.PutRequest = PutRequest;
3095
2996
  exports.RequestError = RequestError;
3096
2997
  exports.ResponseWrapper = ResponseWrapper;
3097
- exports.api = api;
2998
+ exports.createApi = api;
2999
+ exports.createDelete = del;
3000
+ exports.createGet = get;
3001
+ exports.createHead = head;
3002
+ exports.createOptions = options;
3003
+ exports.createPatch = patch;
3004
+ exports.createPost = post;
3005
+ exports.createPut = put;
3098
3006
  exports["default"] = create;
3099
- exports.del = del;
3100
- exports.get = get;
3101
- exports.head = head;
3102
- exports.options = options;
3103
- exports.patch = patch;
3104
- exports.post = post;
3105
- exports.put = put;
3106
3007
  //# sourceMappingURL=index.cjs.map