@zayne-labs/callapi 1.11.1 → 1.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,22 @@
1
1
  <h1 align="center">CallApi</h1>
2
2
 
3
3
  <p align="center">
4
- <img src="https://raw.githubusercontent.com/zayne-labs/callapi/refs/heads/main/apps/docs/public/logo.png" alt="CallApi Logo" width="30%">
4
+ <img src="https://raw.githubusercontent.com/zayne-labs/callapi/refs/heads/main/apps/docs/public/logo.png" alt="CallApi Logo" width="30%">
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
+ <!-- <a href="https://deno.bundlejs.com/badge?q=@zayne-labs/callapi,@zayne-labs/callapi&treeshake=%5B*%5D,%5B%7B+createFetchClient+%7D%5D&config=%7B%22compression%22:%7B%22type%22:%22brotli%22,%22quality%22:11%7D%7D"><img src="https://deno.bundlejs.com/badge?q=@zayne-labs/callapi,@zayne-labs/callapi&treeshake=%5B*%5D,%5B%7B+createFetchClient+%7D%5D&config=%7B%22compression%22:%7B%22type%22:%22brotli%22,%22quality%22:11%7D%7D" alt="bundle size"></a> -->
8
9
  <a href="https://www.npmjs.com/package/@zayne-labs/callapi"><img src="https://img.shields.io/npm/v/@zayne-labs/callapi?style=flat&color=EFBA5F" alt="npm version"></a>
9
10
  <a href="https://github.com/zayne-labs/callapi/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/@zayne-labs/callapi?style=flat&color=EFBA5F" alt="license"></a>
10
11
  <a href="https://www.npmjs.com/package/@zayne-labs/callapi"><img src="https://img.shields.io/npm/dm/@zayne-labs/callapi?style=flat&color=EFBA5F" alt="downloads per month"></a>
11
12
  <a href="https://github.com/zayne-labs/callapi/graphs/commit-activity"><img src="https://img.shields.io/github/commit-activity/m/zayne-labs/callapi?style=flat&color=EFBA5F" alt="commit activity"></a>
12
- <a href="https://deepwiki.com/zayne-labs/callapi"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
13
- <a href="https://code2tutorial.com/tutorial/02b6c57c-4847-4e76-b91e-d64dde370609/index.md"><img src="https://img.shields.io/badge/Code2Tutorial-blue?color=blue&logo=victoriametrics" alt="Code2Tutorial"></a>
14
- </p>
13
+ <a href="https://deepwiki.com/zayne-labs/callapi"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
14
+ <a href="https://code2tutorial.com/tutorial/f77cfbd0-3c37-4c37-9608-b3c977e46f00/index.md"><img src="https://img.shields.io/badge/Code2Tutorial-blue?color=blue&logo=victoriametrics" alt="Code2Tutorial"></a>
15
+ </p>
15
16
 
16
- <p align="center">A fetch wrapper that actually solves real problems.</p>
17
+ <p align="center">
18
+ <strong>An advanced fetch library that actually solves real problems.</strong>
19
+ </p>
17
20
 
18
21
  <p align="center">
19
22
  <a href="https://zayne-labs-callapi.netlify.app"><strong>Documentation</strong></a> ·
@@ -23,9 +26,11 @@
23
26
 
24
27
  ---
25
28
 
26
- Stop writing the same HTTP boilerplate in every project. CallApi is a drop-in replacement for fetch with all the features you'd build yourself anyway - just done properly.
29
+ ## Why?
27
30
 
28
- **Under 6KB. Zero dependencies. Runs everywhere.**
31
+ Fetch is too basic for real apps. You end up writing the same boilerplate: error handling, retries, deduplication, response parsing etc. CallApi handles all of that and practically more.
32
+
33
+ **Drop-in replacement for fetch. Under 6KB. Zero dependencies.**
29
34
 
30
35
  ```js
31
36
  import { callApi } from "@zayne-labs/callapi";
@@ -33,180 +38,118 @@ import { callApi } from "@zayne-labs/callapi";
33
38
  const { data, error } = await callApi("/api/users");
34
39
  ```
35
40
 
36
- ## The Problem
37
-
38
- Fetch is great for simple requests, but real apps need more:
39
-
40
- - Handling duplicate requests (user spam-clicks a button)
41
- - Retrying failed requests (network flaky, API rate-limiting)
42
- - Parsing responses (stop writing `await response.json()` everywhere)
43
- - Error handling that makes sense (not just `response.ok`)
44
- - TypeScript types that actually work
41
+ ## Features
45
42
 
46
- You end up writing the same code over and over. Or pulling in a 100KB library.
47
-
48
- ## What CallApi Does
49
-
50
- It's fetch, but with the stuff you actually need:
51
-
52
- ### Request Deduplication
53
-
54
- User spam-clicks? No problem. Duplicate requests are handled automatically.
43
+ **Request Deduplication** - User spam-clicks a button? Handled. No race conditions.
55
44
 
56
45
  ```js
57
- // These share the same request - no race conditions
58
46
  const req1 = callApi("/api/user");
59
- const req2 = callApi("/api/user"); // Reuses req1's response
47
+ const req2 = callApi("/api/user"); // Shares req1's response
60
48
  ```
61
49
 
62
- Three strategies:
63
-
64
- - **Cancel**: Latest request wins (perfect for search-as-you-type)
65
- - **Defer**: Share response between duplicates (when multiple components need the same data)
66
- - **None**: Let them all through (for polling)
67
-
68
- ### Smart Response Parsing
69
-
70
- Looks at Content-Type and does the right thing. No more manual parsing.
50
+ **Smart Response Parsing** - Looks at Content-Type, does the right thing.
71
51
 
72
52
  ```js
73
53
  const { data } = await callApi("/api/data"); // JSON? Parsed.
74
- const { data } = await callApi("/page.html"); // HTML? String.
75
- const { data } = await callApi("/image.png"); // Image? Blob.
76
54
  ```
77
55
 
78
- ### Error Handling That Makes Sense
56
+ **Error Handling** - Structured errors you can actually use.
79
57
 
80
58
  ```js
81
59
  const { data, error } = await callApi("/api/users");
82
-
83
60
  if (error) {
84
- console.log(error.name); // "HTTPError", "ValidationError", "TimeoutError"
85
- console.log(error.errorData); // The actual error response from your API
61
+ console.log(error.name); // "HTTPError", "ValidationError"
62
+ console.log(error.errorData); // Actual API response
86
63
  }
87
64
  ```
88
65
 
89
- No more `try/catch` hell. No more checking `response.ok`. Just clean, predictable errors.
90
-
91
- ### Retries That Actually Work
92
-
93
- Network flaky? API rate-limiting you? Handled.
66
+ **Retries** - Exponential backoff, custom conditions.
94
67
 
95
68
  ```js
96
69
  await callApi("/api/data", {
97
70
  retryAttempts: 3,
98
- retryStrategy: "exponential", // 1s, 2s, 4s, 8s...
71
+ retryStrategy: "exponential",
99
72
  retryStatusCodes: [429, 500, 502, 503],
100
73
  });
101
74
  ```
102
75
 
103
- ### Schema Validation (Type-Safe + Runtime)
104
-
105
- Define your API schema once, get TypeScript types AND runtime validation:
76
+ **Schema Validation** - TypeScript types + runtime validation.
106
77
 
107
78
  ```js
108
79
  import { z } from "zod";
109
80
  import { defineSchema, createFetchClient } from "@zayne-labs/callapi";
110
81
 
111
82
  const api = createFetchClient({
112
- baseURL: "https://api.example.com",
113
83
  schema: defineSchema({
114
84
  "/users/:id": {
115
85
  data: z.object({
116
86
  id: z.number(),
117
87
  name: z.string(),
118
- email: z.string(),
119
88
  }),
120
89
  },
121
90
  }),
122
91
  });
123
92
 
124
- const user = await api("/users/123");
125
- // TypeScript knows the exact shape
126
- // Runtime validates it matches
127
- // If it doesn't? ValidationError with details
128
- ```
129
-
130
- Works with Zod, Valibot, ArkType, or any Standard Schema validator.
131
-
132
- ### URL Helpers
133
-
134
- ```js
135
- // Dynamic params
136
- await callApi("/users/:id/posts/:postId", {
137
- params: { id: 123, postId: 456 },
138
- }); // → /users/123/posts/456
139
-
140
- // Query strings
141
- await callApi("/search", {
142
- query: { q: "javascript", limit: 10 },
143
- }); // → /search?q=javascript&limit=10
144
-
145
- // Method prefixes
146
- await callApi("@delete/users/123"); // Sets method to DELETE
93
+ const user = await api("/users/123"); // Fully typed + validated
147
94
  ```
148
95
 
149
- ### Hooks for Everything
96
+ **Hooks** - Intercept at any point.
150
97
 
151
98
  ```js
152
99
  const api = createFetchClient({
153
100
  onRequest: ({ request }) => {
154
- // Add auth, modify headers
155
101
  request.headers.set("Authorization", `Bearer ${token}`);
156
102
  },
157
-
158
- onResponse: ({ data, response }) => {
159
- // Log, cache, transform
160
- console.log(`${response.status} - ${response.url}`);
161
- },
162
-
163
103
  onError: ({ error }) => {
164
- // Send to error tracking
165
104
  Sentry.captureException(error);
166
105
  },
167
-
168
- onRequestStream: ({ event }) => {
169
- // Upload progress
170
- console.log(`Uploaded ${event.progress}%`);
171
- },
172
-
173
106
  onResponseStream: ({ event }) => {
174
- // Download progress
175
- updateProgressBar(event.progress);
107
+ console.log(`Downloaded ${event.progress}%`);
176
108
  },
177
109
  });
178
110
  ```
179
111
 
180
- ### Plugin System
181
-
182
- Build plugins for caching, upload progress with XHR, offline detection, whatever you need:
112
+ **Plugins** - Extend with middleware.
183
113
 
184
114
  ```js
185
115
  const cachingPlugin = definePlugin({
186
- id: "caching",
116
+ id: "caching-plugin",
117
+ name: "Caching plugin",
187
118
 
188
- middlewares: ({ options }) => {
119
+ middlewares: (ctx) => {
189
120
  const cache = new Map();
190
121
 
191
122
  return {
192
123
  fetchMiddleware: (fetchImpl) => async (input, init) => {
193
- // Check cache first
194
- const cached = cache.get(input.toString());
195
- if (cached && !isExpired(cached)) {
196
- return cached.response.clone();
124
+ const key = input.toString();
125
+
126
+ if (cache.has(key)) {
127
+ return cache.get(key).clone();
197
128
  }
198
129
 
199
- // Fetch and cache
200
130
  const response = await fetchImpl(input, init);
201
- cache.set(input.toString(), { response: response.clone(), timestamp: Date.now() });
131
+ cache.set(key, response.clone());
132
+
202
133
  return response;
203
134
  },
204
135
  };
205
136
  },
206
137
  });
138
+
139
+ const callBackendApi = createFetchClient({
140
+ plugins: [cachingPlugin],
141
+ });
207
142
  ```
208
143
 
209
- Plugins can wrap fetch (middleware), add hooks, define custom options. They compose automatically.
144
+ **URL Helpers** - Dynamic params, query strings, method prefixes.
145
+
146
+ ```js
147
+ await callApi("/users/:id", { params: { id: 123 } });
148
+ await callApi("/search", { query: { q: "test" } });
149
+ await callApi("@delete/users/123");
150
+ ```
151
+
152
+ And so much more.
210
153
 
211
154
  ## Installation
212
155
 
@@ -217,42 +160,33 @@ npm install @zayne-labs/callapi
217
160
  ```js
218
161
  import { callApi, createFetchClient } from "@zayne-labs/callapi";
219
162
 
220
- // Simple usage
221
- const { data, error } = await callApi("/api/users");
163
+ // Simple
164
+ const { data } = await callApi("/api/users");
222
165
 
223
- // Configured client
166
+ // Configured
224
167
  const api = createFetchClient({
225
168
  baseURL: "https://api.example.com",
226
169
  retryAttempts: 2,
227
170
  timeout: 10000,
228
- dedupeStrategy: "cancel",
229
171
  onError: ({ error }) => trackError(error),
230
172
  });
231
-
232
- const users = await api("/users");
233
173
  ```
234
174
 
235
- ### CDN (No Build Step)
175
+ ### CDN
236
176
 
237
177
  ```html
238
178
  <script type="module">
239
179
  import { callApi } from "https://esm.run/@zayne-labs/callapi";
240
-
241
- const { data } = await callApi("/api/users");
242
180
  </script>
243
181
  ```
244
182
 
245
- ## Why It's Nice to Use
246
-
247
- **TypeScript just works.** Full inference everywhere. Your editor knows what `data` is without you telling it.
248
-
249
- **The API feels familiar.** If you know fetch, you know 90% of CallApi. The rest is just additions that make sense.
250
-
251
- **It's actually small.** Under 6KB. Zero dependencies. Tree-shakeable. Not one of those "lightweight" libraries that's actually 50KB.
252
-
253
- **It's fast.** Built on native Web APIs (Fetch, AbortController, Streams). No abstractions that slow things down.
183
+ ## What makes it worth considering?
254
184
 
255
- **It works everywhere.** Browsers, Node 18+, Deno, Bun, Cloudflare Workers. If it runs JavaScript, it runs CallApi.
185
+ - **TypeScript-first** - Full inference everywhere
186
+ - **Familiar API** - If you know fetch, you know CallApi
187
+ - **Actually small** - Zero dependencies and Under 6KB, unlike other 50kb libs in the wild
188
+ - **Fast** - Built on native Web APIs
189
+ - **Works everywhere** - Browsers, Node 18+, Deno, Bun, Cloudflare Workers
256
190
 
257
191
  ## License
258
192
 
@@ -424,9 +424,9 @@ interface Middlewares {
424
424
  /**
425
425
  * Wraps the fetch implementation to intercept requests at the network layer.
426
426
  *
427
- * Takes the current fetch function and returns a new one. Use it to cache responses,
428
- * add logging, handle offline mode, or short-circuit requests etc. Multiple middleware
429
- * compose in order: plugins → base config → per-request.
427
+ * Takes a context object containing the current fetch function and returns a new fetch function.
428
+ * Use it to cache responses, add logging, handle offline mode, or short-circuit requests etc.
429
+ * Multiple middleware compose in order: plugins → base config → per-request.
430
430
  *
431
431
  * Unlike `customFetchImpl`, middleware can call through to the original fetch.
432
432
  *
@@ -434,25 +434,27 @@ interface Middlewares {
434
434
  * ```ts
435
435
  * // Cache responses
436
436
  * const cache = new Map();
437
- * fetchMiddleware: (fetchImpl) => async (input, init) => {
437
+ * fetchMiddleware: (ctx) => async (input, init) => {
438
438
  * const key = input.toString();
439
439
  * if (cache.has(key)) return cache.get(key).clone();
440
440
  *
441
- * const response = await fetchImpl(input, init);
441
+ * const response = await ctx.fetchImpl(input, init);
442
442
  * cache.set(key, response.clone());
443
443
  * return response;
444
444
  * }
445
445
  *
446
446
  * // Handle offline
447
- * fetchMiddleware: (fetchImpl) => async (input, init) => {
447
+ * fetchMiddleware: (ctx) => async (input, init) => {
448
448
  * if (!navigator.onLine) {
449
449
  * return new Response('{"error": "offline"}', { status: 503 });
450
450
  * }
451
- * return fetchImpl(input, init);
451
+ * return ctx.fetchImpl(input, init);
452
452
  * }
453
453
  * ```
454
454
  */
455
- fetchMiddleware?: (fetchImpl: FetchImpl) => FetchImpl;
455
+ fetchMiddleware?: (context: RequestContext & {
456
+ fetchImpl: FetchImpl;
457
+ }) => FetchImpl;
456
458
  }
457
459
  //#endregion
458
460
  //#region src/plugins.d.ts
@@ -557,18 +559,21 @@ type CallApiResultErrorVariant<TErrorData> = {
557
559
  error: PossibleJavaScriptOrValidationError;
558
560
  response: Response | null;
559
561
  };
560
- type ResultModeMapWithoutException<TData, TErrorData, TResponseType extends ResponseTypeUnion, TComputedData = GetResponseType<TData, TResponseType>, TComputedErrorData = GetResponseType<TErrorData, TResponseType>> = UnmaskType<{
561
- all: CallApiResultErrorVariant<TComputedErrorData> | CallApiResultSuccessVariant<TComputedData>;
562
- onlyData: CallApiResultErrorVariant<TComputedErrorData>["data"] | CallApiResultSuccessVariant<TComputedData>["data"];
562
+ type CallApiSuccessOrErrorVariant<TData, TError> = CallApiResultErrorVariant<TError> | CallApiResultSuccessVariant<TData>;
563
+ type ResultModeMapWithoutException<TData, TErrorData, TResponseType extends ResponseTypeUnion, TComputedData = GetResponseType<TData, TResponseType>, TComputedErrorData = GetResponseType<TErrorData, TResponseType>, TComputedResult extends CallApiSuccessOrErrorVariant<TComputedData, TComputedErrorData> = CallApiSuccessOrErrorVariant<TComputedData, TComputedErrorData>> = UnmaskType<{
564
+ all: TComputedResult;
565
+ onlyData: TComputedResult["data"];
566
+ onlyResponse: TComputedResult["response"];
563
567
  }>;
564
- type ResultModeMapWithException<TData, TResponseType extends ResponseTypeUnion, TComputedData = GetResponseType<TData, TResponseType>> = {
565
- all: CallApiResultSuccessVariant<TComputedData>;
566
- onlyData: CallApiResultSuccessVariant<TComputedData>["data"];
568
+ type ResultModeMapWithException<TData, TResponseType extends ResponseTypeUnion, TComputedData = GetResponseType<TData, TResponseType>, TComputedResult extends CallApiResultSuccessVariant<TComputedData> = CallApiResultSuccessVariant<TComputedData>> = {
569
+ all: TComputedResult;
570
+ onlyData: TComputedResult["data"];
571
+ onlyResponse: TComputedResult["response"];
567
572
  };
568
573
  type ResultModeMap<TData = DefaultDataType, TErrorData = DefaultDataType, TResponseType extends ResponseTypeUnion = ResponseTypeUnion, TThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError> = TThrowOnError extends true ? ResultModeMapWithException<TData, TResponseType> : ResultModeMapWithoutException<TData, TErrorData, TResponseType>;
569
574
  type ResultModePlaceholder = null;
570
575
  type ResultModeUnion = keyof ResultModeMap | ResultModePlaceholder;
571
- type GetCallApiResult<TData, TErrorData, TResultMode extends ResultModeUnion, TThrowOnError extends ThrowOnErrorUnion, TResponseType extends ResponseTypeUnion> = TErrorData extends false ? ResultModeMapWithException<TData, TResponseType>["onlyData"] : TErrorData extends false | undefined ? ResultModeMapWithException<TData, TResponseType>["onlyData"] : ResultModePlaceholder extends TResultMode ? ResultModeMap<TData, TErrorData, TResponseType, TThrowOnError>["all"] : TResultMode extends Exclude<ResultModeUnion, ResultModePlaceholder> ? ResultModeMap<TData, TErrorData, TResponseType, TThrowOnError>[TResultMode] : never;
576
+ type GetCallApiResult<TData, TErrorData, TResultMode extends ResultModeUnion, TThrowOnError extends ThrowOnErrorUnion, TResponseType extends ResponseTypeUnion, TComputedResultModeMapWithException extends ResultModeMapWithException<TData, TResponseType> = ResultModeMapWithException<TData, TResponseType>, TComputedResultModeMap extends ResultModeMap<TData, TErrorData, TResponseType, TThrowOnError> = ResultModeMap<TData, TErrorData, TResponseType, TThrowOnError>> = TErrorData extends false ? TComputedResultModeMapWithException["onlyData"] : TErrorData extends false | undefined ? TComputedResultModeMapWithException["onlyData"] : ResultModePlaceholder extends TResultMode ? TComputedResultModeMap["all"] : TResultMode extends Exclude<ResultModeUnion, ResultModePlaceholder> ? TComputedResultModeMap[TResultMode] : never;
572
577
  //#endregion
573
578
  //#region src/stream.d.ts
574
579
  type StreamProgressEvent = {
@@ -1487,7 +1492,7 @@ type SharedExtraOptions<TData = DefaultDataType, TErrorData = DefaultDataType, T
1487
1492
  *
1488
1493
  * ```
1489
1494
  */
1490
- responseParser?: (responseString: string) => Awaitable<unknown>;
1495
+ responseParser?: (responseString: string) => Awaitable<TData>;
1491
1496
  /**
1492
1497
  * Expected response type, determines how the response body is parsed.
1493
1498
  *
@@ -1791,7 +1796,7 @@ type BaseCallApiConfig<TBaseData = DefaultDataType, TBaseErrorData = DefaultData
1791
1796
  }) => CallApiRequestOptions & BaseCallApiExtraOptions<TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBasePluginArray, TBaseSchemaAndConfig>);
1792
1797
  type CallApiConfig<TData = DefaultDataType, TErrorData = DefaultDataType, TResultMode extends ResultModeUnion = ResultModeUnion, TThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType extends ResponseTypeUnion = ResponseTypeUnion, TBaseSchemaRoutes extends BaseCallApiSchemaRoutes = BaseCallApiSchemaRoutes, TSchema extends CallApiSchema = CallApiSchema, TBaseSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TInitURL extends InitURLOrURLObject = InitURLOrURLObject, TCurrentRouteSchemaKey extends string = string, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TPluginArray extends CallApiPlugin[] = DefaultPluginArray> = InferExtraOptions<TSchema, TBaseSchemaRoutes, TCurrentRouteSchemaKey> & InferRequestOptions<TSchema, TInitURL> & Omit<CallApiExtraOptions<TData, TErrorData, TResultMode, TThrowOnError, TResponseType, TBasePluginArray, TPluginArray, TBaseSchemaRoutes, TSchema, TBaseSchemaConfig, TSchemaConfig, TCurrentRouteSchemaKey>, keyof InferExtraOptions<CallApiSchema, BaseCallApiSchemaRoutes, string>> & Omit<CallApiRequestOptions, keyof InferRequestOptions<CallApiSchema, string>>;
1793
1798
  type CallApiParameters<TData = DefaultDataType, TErrorData = DefaultDataType, TResultMode extends ResultModeUnion = ResultModeUnion, TThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType extends ResponseTypeUnion = ResponseTypeUnion, TBaseSchemaRoutes extends BaseCallApiSchemaRoutes = BaseCallApiSchemaRoutes, TSchema extends CallApiSchema = CallApiSchema, TBaseSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TInitURL extends InitURLOrURLObject = InitURLOrURLObject, TCurrentRouteSchemaKey extends string = string, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TPluginArray extends CallApiPlugin[] = DefaultPluginArray> = [initURL: TInitURL, config?: CallApiConfig<TData, TErrorData, TResultMode, TThrowOnError, TResponseType, TBaseSchemaRoutes, TSchema, TBaseSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, TBasePluginArray, TPluginArray>];
1794
- type CallApiResult<TData, TErrorData, TResultMode extends ResultModeUnion, TThrowOnError extends ThrowOnErrorUnion, TResponseType extends ResponseTypeUnion> = Promise<GetCallApiResult<TData, TErrorData, TResultMode, TThrowOnError, TResponseType>>;
1799
+ type CallApiResult<TData, TErrorData, TResultMode extends ResultModeUnion, TThrowOnError extends ThrowOnErrorUnion, TResponseType extends ResponseTypeUnion> = GetCallApiResult<TData, TErrorData, TResultMode, TThrowOnError, TResponseType>;
1795
1800
  //#endregion
1796
- export { AnyFunction, AnyString, ApplyStrictConfig, ApplyURLBasedConfig, BaseCallApiConfig, BaseCallApiExtraOptions, BaseCallApiSchemaAndConfig, BaseCallApiSchemaRoutes, CallApiConfig, CallApiExtraOptions, CallApiExtraOptionsForHooks, CallApiParameters, CallApiPlugin, CallApiRequestOptions, CallApiRequestOptionsForHooks, CallApiResult, CallApiResultErrorVariant, CallApiResultSuccessVariant, CallApiSchema, CallApiSchemaConfig, DedupeOptions, DefaultDataType, DefaultPluginArray, DefaultThrowOnError, ErrorContext, GetCurrentRouteSchema, GetCurrentRouteSchemaKey, GetResponseType, HTTPError, Hooks, HooksOrHooksArray, InferInitURL, InferParamsFromRoute, InferSchemaOutputResult, PluginExtraOptions, PluginHooks, PluginHooksWithMoreOptions, PluginSetupContext, PossibleHTTPError, PossibleJavaScriptError, PossibleJavaScriptOrValidationError, PossibleValidationError, Register, RequestContext, RequestStreamContext, ResponseContext, ResponseErrorContext, ResponseStreamContext, ResponseTypeMap, ResponseTypeUnion, ResultModeUnion, RetryOptions, SuccessContext, ThrowOnErrorUnion, URLOptions, ValidationError, Writeable, fallBackRouteSchemaKey };
1797
- //# sourceMappingURL=common-BMWVqV15.d.ts.map
1801
+ export { AnyFunction, AnyString, ApplyStrictConfig, ApplyURLBasedConfig, BaseCallApiConfig, BaseCallApiExtraOptions, BaseCallApiSchemaAndConfig, BaseCallApiSchemaRoutes, CallApiConfig, CallApiExtraOptions, CallApiExtraOptionsForHooks, CallApiParameters, CallApiPlugin, CallApiRequestOptions, CallApiRequestOptionsForHooks, CallApiResult, CallApiResultErrorVariant, CallApiResultSuccessVariant, CallApiSchema, CallApiSchemaConfig, CallApiSuccessOrErrorVariant, DedupeOptions, DefaultDataType, DefaultPluginArray, DefaultThrowOnError, ErrorContext, GetCallApiResult, GetCurrentRouteSchema, GetCurrentRouteSchemaKey, GetResponseType, HTTPError, Hooks, HooksOrHooksArray, InferInitURL, InferParamsFromRoute, InferSchemaOutputResult, PluginExtraOptions, PluginHooks, PluginHooksWithMoreOptions, PluginSetupContext, PossibleHTTPError, PossibleJavaScriptError, PossibleJavaScriptOrValidationError, PossibleValidationError, Register, RequestContext, RequestStreamContext, ResponseContext, ResponseErrorContext, ResponseStreamContext, ResponseTypeMap, ResponseTypeUnion, ResultModeMap, ResultModeUnion, RetryOptions, SuccessContext, ThrowOnErrorUnion, URLOptions, ValidationError, Writeable, fallBackRouteSchemaKey };
1802
+ //# sourceMappingURL=common-B-TYbBQa.d.ts.map
@@ -2,7 +2,7 @@
2
2
  const defineEnum = (value) => Object.freeze(value);
3
3
 
4
4
  //#endregion
5
- //#region src/constants/default-options.ts
5
+ //#region src/constants/defaults.ts
6
6
  const extraOptionDefaults = Object.freeze(defineEnum({
7
7
  bodySerializer: JSON.stringify,
8
8
  defaultHTTPErrorMessage: "HTTP request failed unexpectedly",
@@ -529,9 +529,13 @@ const getInitFetchImpl = (customFetchImpl) => {
529
529
  if (typeof globalThis !== "undefined" && isFunction(globalThis.fetch)) return globalThis.fetch;
530
530
  throw new Error("No fetch implementation found");
531
531
  };
532
- const getFetchImpl = (customFetchImpl, fetchMiddleware) => {
533
- const initFetchApi = getInitFetchImpl(customFetchImpl);
534
- return fetchMiddleware ? fetchMiddleware(initFetchApi) : initFetchApi;
532
+ const getFetchImpl = (context) => {
533
+ const { customFetchImpl, fetchMiddleware, requestContext } = context;
534
+ const initFetchImpl = getInitFetchImpl(customFetchImpl);
535
+ return fetchMiddleware ? fetchMiddleware({
536
+ ...requestContext,
537
+ fetchImpl: initFetchImpl
538
+ }) : initFetchImpl;
535
539
  };
536
540
  const PromiseWithResolvers = () => {
537
541
  let reject;
@@ -573,4 +577,4 @@ const toArray = (value) => isArray(value) ? value : [value];
573
577
 
574
578
  //#endregion
575
579
  export { HTTPError, ValidationError, createCombinedSignal, createTimeoutSignal, deterministicHashFn, extraOptionDefaults, fallBackRouteSchemaKey, getBody, getCurrentRouteSchemaKeyAndMainInitURL, getFetchImpl, getFullAndNormalizedURL, getHeaders, getMethod, handleConfigValidation, handleSchemaValidation, isArray, isBoolean, isFunction, isHTTPError, isHTTPErrorInstance, isJavascriptError, isObject, isPlainObject, isReadableStream, isString, isValidationError, isValidationErrorInstance, splitBaseConfig, splitConfig, toQueryString, waitFor };
576
- //# sourceMappingURL=common-B2rPuIEQ.js.map
580
+ //# sourceMappingURL=common-CfCB_X1k.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common-CfCB_X1k.js","names":["validatedResultObject: Prettify<\n\t\tPick<CallApiExtraOptions, (typeof extraOptionsToBeValidated)[number]>\n\t>","validatedResultObject: Prettify<\n\t\tPick<CallApiRequestOptions, (typeof requestOptionsToBeValidated)[number]>\n\t>","toQueryString: ToQueryStringFn","headersObject: Record<string, string | undefined>","reject!: (reason?: unknown) => void","resolve!: (value: unknown) => void","result: Record<string, unknown>"],"sources":["../../src/types/type-helpers.ts","../../src/constants/defaults.ts","../../src/error.ts","../../src/utils/guards.ts","../../src/auth.ts","../../src/constants/common.ts","../../src/validation.ts","../../src/url.ts","../../src/utils/polyfills/combinedSignal.ts","../../src/utils/polyfills/timeoutSignal.ts","../../src/utils/common.ts"],"sourcesContent":["// == These two types allows for adding arbitrary literal types, while still provided autocomplete for defaults.\n// == Usually intersection with \"{}\" or \"NonNullable<unknown>\" would make it work fine, but the placeholder with never type is added to make the AnyWhatever type appear last in a given union.\nexport type AnyString = string & NonNullable<unknown>;\nexport type AnyNumber = number & NonNullable<unknown>;\n\n// eslint-disable-next-line ts-eslint/no-explicit-any -- Any is fine here\nexport type AnyObject = Record<keyof any, any>;\n\n// eslint-disable-next-line ts-eslint/no-explicit-any -- Any is required here so that one can pass custom function type without type errors\nexport type AnyFunction<TResult = unknown> = (...args: any[]) => TResult;\n\nexport type Prettify<TObject> = NonNullable<unknown> & { [Key in keyof TObject]: TObject[Key] };\n\nexport type WriteableLevel = \"deep\" | \"shallow\";\n\n/**\n * Makes all properties in an object type writeable (removes readonly modifiers).\n * Supports both shallow and deep modes, and handles special cases like arrays, tuples, and unions.\n * @template TObject - The object type to make writeable\n * @template TVariant - The level of writeable transformation (\"shallow\" | \"deep\")\n */\n\ntype ArrayOrObject = Record<number | string | symbol, unknown> | unknown[];\n\nexport type Writeable<TObject, TLevel extends WriteableLevel = \"shallow\"> =\n\tTObject extends readonly [...infer TTupleItems] ?\n\t\t[\n\t\t\t...{\n\t\t\t\t[Index in keyof TTupleItems]: TLevel extends \"deep\" ? Writeable<TTupleItems[Index], \"deep\">\n\t\t\t\t:\tTTupleItems[Index];\n\t\t\t},\n\t\t]\n\t: TObject extends ArrayOrObject ?\n\t\t{\n\t\t\t-readonly [Key in keyof TObject]: TLevel extends \"deep\" ? Writeable<TObject[Key], \"deep\">\n\t\t\t:\tTObject[Key];\n\t\t}\n\t:\tTObject;\n\nexport const defineEnum = <const TValue extends object>(value: TValue) =>\n\tObject.freeze(value) as Readonly<Writeable<TValue>>;\n\nexport type UnionToIntersection<TUnion> =\n\t(TUnion extends unknown ? (param: TUnion) => void : never) extends (param: infer TParam) => void ?\n\t\tTParam\n\t:\tnever;\n\n// == Using this Immediately Indexed Mapped type helper to help show computed type of anything passed to it instead of just the type name\nexport type UnmaskType<TValue> = { _: TValue }[\"_\"];\n\nexport type RemovePrefix<TPrefix extends \"dedupe\" | \"retry\", TKey extends string> =\n\tTKey extends `${TPrefix}${infer TRest}` ? Uncapitalize<TRest> : TKey;\n\nexport type Awaitable<TValue> = Promise<TValue> | TValue;\n\nexport type CommonRequestHeaders =\n\t| \"Access-Control-Allow-Credentials\"\n\t| \"Access-Control-Allow-Headers\"\n\t| \"Access-Control-Allow-Methods\"\n\t| \"Access-Control-Allow-Origin\"\n\t| \"Access-Control-Expose-Headers\"\n\t| \"Access-Control-Max-Age\"\n\t| \"Age\"\n\t| \"Allow\"\n\t| \"Cache-Control\"\n\t| \"Clear-Site-Data\"\n\t| \"Content-Disposition\"\n\t| \"Content-Encoding\"\n\t| \"Content-Language\"\n\t| \"Content-Length\"\n\t| \"Content-Location\"\n\t| \"Content-Range\"\n\t| \"Content-Security-Policy-Report-Only\"\n\t| \"Content-Security-Policy\"\n\t| \"Cookie\"\n\t| \"Cross-Origin-Embedder-Policy\"\n\t| \"Cross-Origin-Opener-Policy\"\n\t| \"Cross-Origin-Resource-Policy\"\n\t| \"Date\"\n\t| \"ETag\"\n\t| \"Expires\"\n\t| \"Last-Modified\"\n\t| \"Location\"\n\t| \"Permissions-Policy\"\n\t| \"Pragma\"\n\t| \"Retry-After\"\n\t| \"Save-Data\"\n\t| \"Sec-CH-Prefers-Color-Scheme\"\n\t| \"Sec-CH-Prefers-Reduced-Motion\"\n\t| \"Sec-CH-UA-Arch\"\n\t| \"Sec-CH-UA-Bitness\"\n\t| \"Sec-CH-UA-Form-Factor\"\n\t| \"Sec-CH-UA-Full-Version-List\"\n\t| \"Sec-CH-UA-Full-Version\"\n\t| \"Sec-CH-UA-Mobile\"\n\t| \"Sec-CH-UA-Model\"\n\t| \"Sec-CH-UA-Platform-Version\"\n\t| \"Sec-CH-UA-Platform\"\n\t| \"Sec-CH-UA-WoW64\"\n\t| \"Sec-CH-UA\"\n\t| \"Sec-Fetch-Dest\"\n\t| \"Sec-Fetch-Mode\"\n\t| \"Sec-Fetch-Site\"\n\t| \"Sec-Fetch-User\"\n\t| \"Sec-GPC\"\n\t| \"Server-Timing\"\n\t| \"Server\"\n\t| \"Service-Worker-Navigation-Preload\"\n\t| \"Set-Cookie\"\n\t| \"Strict-Transport-Security\"\n\t| \"Timing-Allow-Origin\"\n\t| \"Trailer\"\n\t| \"Transfer-Encoding\"\n\t| \"Upgrade\"\n\t| \"Vary\"\n\t| \"Warning\"\n\t| \"WWW-Authenticate\"\n\t| \"X-Content-Type-Options\"\n\t| \"X-DNS-Prefetch-Control\"\n\t| \"X-Frame-Options\"\n\t| \"X-Permitted-Cross-Domain-Policies\"\n\t| \"X-Powered-By\"\n\t| \"X-Robots-Tag\"\n\t| \"X-XSS-Protection\"\n\t| AnyString;\n\nexport type CommonAuthorizationHeaders = `${\"Basic\" | \"Bearer\" | \"Token\"} ${string}`;\n\nexport type CommonContentTypes =\n\t| \"application/epub+zip\"\n\t| \"application/gzip\"\n\t| \"application/json\"\n\t| \"application/ld+json\"\n\t| \"application/octet-stream\"\n\t| \"application/ogg\"\n\t| \"application/pdf\"\n\t| \"application/rtf\"\n\t| \"application/vnd.ms-fontobject\"\n\t| \"application/wasm\"\n\t| \"application/xhtml+xml\"\n\t| \"application/xml\"\n\t| \"application/zip\"\n\t| \"audio/aac\"\n\t| \"audio/mpeg\"\n\t| \"audio/ogg\"\n\t| \"audio/opus\"\n\t| \"audio/webm\"\n\t| \"audio/x-midi\"\n\t| \"font/otf\"\n\t| \"font/ttf\"\n\t| \"font/woff\"\n\t| \"font/woff2\"\n\t| \"image/avif\"\n\t| \"image/bmp\"\n\t| \"image/gif\"\n\t| \"image/jpeg\"\n\t| \"image/png\"\n\t| \"image/svg+xml\"\n\t| \"image/tiff\"\n\t| \"image/webp\"\n\t| \"image/x-icon\"\n\t| \"model/gltf-binary\"\n\t| \"model/gltf+json\"\n\t| \"text/calendar\"\n\t| \"text/css\"\n\t| \"text/csv\"\n\t| \"text/html\"\n\t| \"text/javascript\"\n\t| \"text/plain\"\n\t| \"video/3gpp\"\n\t| \"video/3gpp2\"\n\t| \"video/av1\"\n\t| \"video/mp2t\"\n\t| \"video/mp4\"\n\t| \"video/mpeg\"\n\t| \"video/ogg\"\n\t| \"video/webm\"\n\t| \"video/x-msvideo\"\n\t| AnyString;\n","import type { CallApiConfig, CallApiExtraOptions } from \"../types/common\";\nimport { defineEnum } from \"../types/type-helpers\";\n\nexport const extraOptionDefaults = Object.freeze(\n\tdefineEnum({\n\t\t// Common defaults\n\t\tbodySerializer: JSON.stringify,\n\t\tdefaultHTTPErrorMessage: \"HTTP request failed unexpectedly\",\n\n\t\t// Dedupe defaults\n\t\t/* eslint-disable perfectionist/sort-objects -- Allow */\n\t\tdedupeCacheScope: \"local\",\n\t\tdedupeCacheScopeKey: \"default\",\n\t\tdedupeStrategy: \"cancel\",\n\t\t/* eslint-enable perfectionist/sort-objects -- Allow */\n\n\t\t// Hook defaults\n\t\thooksExecutionMode: \"parallel\",\n\n\t\t// Response defaults\n\t\tresponseParser: JSON.parse,\n\t\tresponseType: \"json\",\n\t\tresultMode: \"all\",\n\n\t\t// Retry Defaults\n\t\tretryAttempts: 0,\n\t\tretryCondition: () => true,\n\t\tretryDelay: 1000,\n\t\tretryMaxDelay: 10000,\n\t\tretryMethods: [\"GET\", \"POST\"],\n\t\tretryStatusCodes: [],\n\t\tretryStrategy: \"linear\",\n\t} satisfies CallApiExtraOptions)\n);\n\nexport const requestOptionDefaults = defineEnum({\n\tmethod: \"GET\",\n} satisfies CallApiConfig);\n","import { extraOptionDefaults } from \"./constants/defaults\";\nimport type { CallApiExtraOptions } from \"./types\";\nimport type { StandardSchemaV1 } from \"./types/standard-schema\";\nimport { isObject, isString } from \"./utils/guards\";\nimport type { CallApiSchema, CallApiSchemaConfig } from \"./validation\";\n\ntype HTTPErrorDetails<TErrorData> = Pick<CallApiExtraOptions, \"defaultHTTPErrorMessage\"> & {\n\terrorData: TErrorData;\n\tresponse: Response;\n};\n\nconst httpErrorSymbol = Symbol(\"HTTPError\");\n\nexport class HTTPError<TErrorData = Record<string, unknown>> extends Error {\n\terrorData: HTTPErrorDetails<TErrorData>[\"errorData\"];\n\n\treadonly httpErrorSymbol = httpErrorSymbol;\n\n\toverride name = \"HTTPError\" as const;\n\n\tresponse: HTTPErrorDetails<TErrorData>[\"response\"];\n\n\tconstructor(errorDetails: HTTPErrorDetails<TErrorData>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultHTTPErrorMessage, errorData, response } = errorDetails;\n\n\t\tconst resolvedDefaultHTTPErrorMessage =\n\t\t\tisString(defaultHTTPErrorMessage) ? defaultHTTPErrorMessage : (\n\t\t\t\tdefaultHTTPErrorMessage?.({ errorData, response })\n\t\t\t);\n\n\t\tconst selectedDefaultErrorMessage =\n\t\t\tresolvedDefaultHTTPErrorMessage\n\t\t\t?? (response.statusText || extraOptionDefaults.defaultHTTPErrorMessage);\n\n\t\tconst message =\n\t\t\t(errorData as { message?: string } | undefined)?.message ?? selectedDefaultErrorMessage;\n\n\t\tsuper(message, errorOptions);\n\n\t\tthis.errorData = errorData;\n\t\tthis.response = response;\n\t}\n\n\t/**\n\t * @description Checks if the given error is an instance of HTTPError\n\t * @param error - The error to check\n\t * @returns true if the error is an instance of HTTPError, false otherwise\n\t */\n\tstatic override isError<TErrorData>(error: unknown): error is HTTPError<TErrorData> {\n\t\tif (!isObject<HTTPError>(error)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (error instanceof HTTPError) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst actualError = error as HTTPError;\n\n\t\treturn (\n\t\t\tactualError.httpErrorSymbol === httpErrorSymbol\n\t\t\t// eslint-disable-next-line ts-eslint/no-unnecessary-condition -- Allow\n\t\t\t&& actualError.name === \"HTTPError\"\n\t\t);\n\t}\n}\n\nconst prettifyPath = (path: ValidationError[\"errorData\"][number][\"path\"]) => {\n\tif (!path || path.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst pathString = path.map((segment) => (isObject(segment) ? segment.key : segment)).join(\".\");\n\n\treturn ` → at ${pathString}`;\n};\n\nconst prettifyValidationIssues = (issues: ValidationError[\"errorData\"]) => {\n\tconst issuesString = issues\n\t\t.map((issue) => `✖ ${issue.message}${prettifyPath(issue.path)}`)\n\t\t.join(\" | \");\n\n\treturn issuesString;\n};\n\ntype LockedExtract<TUnion, TKey extends TUnion> = Extract<TUnion, TKey>;\n\ntype ValidationErrorDetails = {\n\t/**\n\t * The cause of the validation error.\n\t *\n\t * It's either the name the schema for which validation failed, or the name of the schema config option that led to the validation error.\n\t */\n\tissueCause:\n\t\t| \"unknown\"\n\t\t| `schemaConfig-(${LockedExtract<keyof CallApiSchemaConfig, \"strict\">})`\n\t\t| keyof CallApiSchema;\n\n\t/**\n\t * The issues that caused the validation error.\n\t */\n\tissues: readonly StandardSchemaV1.Issue[];\n\n\t/**\n\t * The response from server, if any.\n\t */\n\tresponse: Response | null;\n};\n\nconst validationErrorSymbol = Symbol(\"ValidationErrorSymbol\");\n\nexport class ValidationError extends Error {\n\terrorData: ValidationErrorDetails[\"issues\"];\n\n\tissueCause: ValidationErrorDetails[\"issueCause\"];\n\n\toverride name = \"ValidationError\" as const;\n\n\tresponse: ValidationErrorDetails[\"response\"];\n\n\treadonly validationErrorSymbol = validationErrorSymbol;\n\n\tconstructor(details: ValidationErrorDetails, errorOptions?: ErrorOptions) {\n\t\tconst { issueCause, issues, response } = details;\n\n\t\tconst message = prettifyValidationIssues(issues);\n\n\t\tsuper(message, errorOptions);\n\n\t\tthis.errorData = issues;\n\t\tthis.response = response;\n\t\tthis.issueCause = issueCause;\n\t}\n\n\t/**\n\t * @description Checks if the given error is an instance of ValidationError\n\t * @param error - The error to check\n\t * @returns true if the error is an instance of ValidationError, false otherwise\n\t */\n\tstatic override isError(error: unknown): error is ValidationError {\n\t\tif (!isObject<ValidationError>(error)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (error instanceof ValidationError) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst actualError = error as ValidationError;\n\n\t\treturn (\n\t\t\tactualError.validationErrorSymbol === validationErrorSymbol\n\t\t\t// eslint-disable-next-line ts-eslint/no-unnecessary-condition -- Allow\n\t\t\t&& actualError.name === \"ValidationError\"\n\t\t);\n\t}\n}\n","import { HTTPError, ValidationError } from \"../error\";\nimport type {\n\tCallApiResultErrorVariant,\n\tPossibleHTTPError,\n\tPossibleJavaScriptError,\n\tPossibleValidationError,\n} from \"../result\";\nimport type { AnyFunction } from \"../types/type-helpers\";\n\nexport const isHTTPError = <TErrorData>(\n\terror: CallApiResultErrorVariant<TErrorData>[\"error\"] | null\n): error is PossibleHTTPError<TErrorData> => {\n\treturn isObject(error) && error.name === \"HTTPError\";\n};\n\nexport const isHTTPErrorInstance = <TErrorData>(error: unknown) => {\n\treturn HTTPError.isError<TErrorData>(error);\n};\n\nexport const isValidationError = (\n\terror: CallApiResultErrorVariant<unknown>[\"error\"] | null\n): error is PossibleValidationError => {\n\treturn isObject(error) && error.name === \"ValidationError\";\n};\n\nexport const isValidationErrorInstance = (error: unknown): error is ValidationError => {\n\treturn ValidationError.isError(error);\n};\n\nexport const isJavascriptError = (\n\terror: CallApiResultErrorVariant<unknown>[\"error\"] | null\n): error is PossibleJavaScriptError => {\n\treturn isObject(error) && !isHTTPError(error) && !isValidationError(error);\n};\n\nexport const isArray = <TArrayItem>(value: unknown): value is TArrayItem[] => Array.isArray(value);\n\nexport const isBoolean = (value: unknown): value is boolean => typeof value === \"boolean\";\n\nexport const isObject = <TObject extends object>(value: unknown): value is TObject => {\n\treturn typeof value === \"object\" && value !== null;\n};\n\nconst hasObjectPrototype = (value: unknown) => {\n\treturn Object.prototype.toString.call(value) === \"[object Object]\";\n};\n\n/**\n * @description Copied from TanStack Query's isPlainObject\n * @see https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L321\n */\nexport const isPlainObject = <TPlainObject extends Record<string, unknown>>(\n\tvalue: unknown\n): value is TPlainObject => {\n\tif (!hasObjectPrototype(value)) {\n\t\treturn false;\n\t}\n\n\t// If has no constructor\n\tconst constructor = (value as object | undefined)?.constructor;\n\tif (constructor === undefined) {\n\t\treturn true;\n\t}\n\n\t// If has modified prototype\n\tconst prototype = constructor.prototype as object;\n\tif (!hasObjectPrototype(prototype)) {\n\t\treturn false;\n\t}\n\n\t// If constructor does not have an Object-specific method\n\tif (!Object.hasOwn(prototype, \"isPrototypeOf\")) {\n\t\treturn false;\n\t}\n\n\t// Handles Objects created by Object.create(<arbitrary prototype>)\n\tif (Object.getPrototypeOf(value) !== Object.prototype) {\n\t\treturn false;\n\t}\n\n\t// It's probably a plain object at this point\n\treturn true;\n};\n\nexport const isValidJsonString = (value: unknown): value is string => {\n\tif (!isString(value)) {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tJSON.parse(value);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nexport const isSerializable = (value: unknown) => {\n\treturn (\n\t\tisPlainObject(value)\n\t\t|| isArray(value)\n\t\t|| typeof (value as { toJSON: unknown } | undefined)?.toJSON === \"function\"\n\t);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n\nexport const isQueryString = (value: unknown): value is string => isString(value) && value.includes(\"=\");\n\nexport const isString = (value: unknown) => typeof value === \"string\";\n\nexport const isPromise = (value: unknown) => value instanceof Promise;\n\nexport const isReadableStream = (value: unknown): value is ReadableStream<unknown> => {\n\treturn value instanceof ReadableStream;\n};\n\n// https://github.com/unjs/ofetch/blob/main/src/utils.ts\nexport const isJSONSerializable = (value: unknown) => {\n\tif (value === undefined) {\n\t\treturn false;\n\t}\n\tconst t = typeof value;\n\t// eslint-disable-next-line ts-eslint/no-unnecessary-condition -- No time to make this more type-safe\n\tif (t === \"string\" || t === \"number\" || t === \"boolean\" || t === null) {\n\t\treturn true;\n\t}\n\tif (t !== \"object\") {\n\t\treturn false;\n\t}\n\tif (isArray(value)) {\n\t\treturn true;\n\t}\n\tif ((value as Buffer | null)?.buffer) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\t(value?.constructor && value.constructor.name === \"Object\")\n\t\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing -- Nullish coalescing makes no sense in this boolean context\n\t\t|| typeof (value as { toJSON: () => unknown } | null)?.toJSON === \"function\"\n\t);\n};\n","/* eslint-disable perfectionist/sort-object-types -- Avoid Sorting for now */\n\nimport type { CallApiExtraOptions } from \"./types/common\";\nimport type { Awaitable } from \"./types/type-helpers\";\nimport { isFunction, isObject, isPromise } from \"./utils/guards\";\n\ntype PossibleAuthValue = Awaitable<string | null | undefined>;\n\ntype PossibleAuthValueOrGetter = PossibleAuthValue | (() => PossibleAuthValue);\n\nexport type BearerOrTokenAuth =\n\t| {\n\t\t\ttype?: \"Bearer\";\n\t\t\tbearer?: PossibleAuthValueOrGetter;\n\t\t\ttoken?: never;\n\t }\n\t| {\n\t\t\ttype?: \"Token\";\n\t\t\tbearer?: never;\n\t\t\ttoken?: PossibleAuthValueOrGetter;\n\t };\n\nexport type BasicAuth = {\n\ttype: \"Basic\";\n\tusername: PossibleAuthValueOrGetter;\n\tpassword: PossibleAuthValueOrGetter;\n};\n\n/**\n * Custom auth\n *\n * @param prefix - prefix of the header\n * @param authValue - value of the header\n *\n * @example\n * ```ts\n * {\n * type: \"Custom\",\n * prefix: \"Token\",\n * authValue: \"token\"\n * }\n * ```\n */\nexport type CustomAuth = {\n\ttype: \"Custom\";\n\tprefix: PossibleAuthValueOrGetter;\n\tvalue: PossibleAuthValueOrGetter;\n};\n\n// eslint-disable-next-line perfectionist/sort-union-types -- Let the first one be first\nexport type Auth = PossibleAuthValueOrGetter | BearerOrTokenAuth | BasicAuth | CustomAuth;\n\nconst resolveAuthValue = (value: PossibleAuthValueOrGetter) => (isFunction(value) ? value() : value);\n\ntype AuthHeaderObject = { Authorization: string };\n\nexport const getAuthHeader = async (\n\tauth: CallApiExtraOptions[\"auth\"]\n): Promise<AuthHeaderObject | undefined> => {\n\tif (auth === undefined) return;\n\n\tif (isPromise(auth) || isFunction(auth) || !isObject(auth)) {\n\t\tconst authValue = await resolveAuthValue(auth);\n\n\t\tif (authValue === undefined) return;\n\n\t\treturn {\n\t\t\tAuthorization: `Bearer ${authValue}`,\n\t\t};\n\t}\n\n\tswitch (auth.type) {\n\t\tcase \"Basic\": {\n\t\t\tconst [username, password] = await Promise.all([\n\t\t\t\tresolveAuthValue(auth.username),\n\t\t\t\tresolveAuthValue(auth.password),\n\t\t\t]);\n\n\t\t\tif (username === undefined || password === undefined) return;\n\n\t\t\treturn {\n\t\t\t\tAuthorization: `Basic ${globalThis.btoa(`${username}:${password}`)}`,\n\t\t\t};\n\t\t}\n\n\t\tcase \"Custom\": {\n\t\t\tconst [prefix, value] = await Promise.all([\n\t\t\t\tresolveAuthValue(auth.prefix),\n\t\t\t\tresolveAuthValue(auth.value),\n\t\t\t]);\n\n\t\t\tif (value === undefined) return;\n\n\t\t\treturn {\n\t\t\t\tAuthorization: `${prefix} ${value}`,\n\t\t\t};\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst [bearer, token] = await Promise.all([\n\t\t\t\tresolveAuthValue(auth.bearer),\n\t\t\t\tresolveAuthValue(auth.token),\n\t\t\t]);\n\n\t\t\tif (bearer !== undefined) {\n\t\t\t\treturn { Authorization: `Bearer ${bearer}` };\n\t\t\t}\n\n\t\t\tif (token === undefined) return;\n\n\t\t\treturn { Authorization: `Token ${token}` };\n\t\t}\n\t}\n};\n","import type { ModifiedRequestInit } from \"../types\";\nimport { defineEnum } from \"../types/type-helpers\";\n\nexport const fetchSpecificKeys = defineEnum([\n\t\"body\",\n\t\"integrity\",\n\t\"duplex\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof ModifiedRequestInit> as Array<keyof ModifiedRequestInit>);\n","import { ValidationError } from \"./error\";\nimport type {\n\tBaseCallApiExtraOptions,\n\tBody,\n\tCallApiExtraOptions,\n\tCallApiRequestOptions,\n\tGlobalMeta,\n\tHeadersOption,\n\tMethodUnion,\n} from \"./types\";\nimport type { StandardSchemaV1 } from \"./types/standard-schema\";\nimport {\n\ttype AnyFunction,\n\ttype AnyString,\n\ttype Awaitable,\n\tdefineEnum,\n\ttype Prettify,\n\ttype UnionToIntersection,\n} from \"./types/type-helpers\";\nimport type { Params, Query } from \"./url\";\nimport { toArray } from \"./utils/common\";\nimport { isFunction } from \"./utils/guards\";\n\ntype InferSchemaInput<TSchema extends CallApiSchema[keyof CallApiSchema]> =\n\tTSchema extends StandardSchemaV1 ? StandardSchemaV1.InferInput<TSchema> : never;\n\nexport type InferSchemaOutputResult<TSchema, TFallbackResult = unknown> =\n\t// == Checking for undefined first and returning fallback to avoid type errors when passing the config around (weird tbh)\n\tundefined extends TSchema ? TFallbackResult\n\t: TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema>\n\t: TSchema extends AnyFunction<infer TResult> ? Awaited<TResult>\n\t: TFallbackResult;\n\nexport type InferSchemaInputResult<TSchema, TFallbackResult = unknown> =\n\t// == Checking for undefined first and returning fallback to avoid type errors when passing the config around (weird tbh)\n\tundefined extends TSchema ? TFallbackResult\n\t: TSchema extends StandardSchemaV1 ? StandardSchemaV1.InferInput<TSchema>\n\t: TSchema extends AnyFunction<infer TResult> ? Awaited<TResult>\n\t: TFallbackResult;\n\nconst handleValidatorFunction = async <TInput>(\n\tvalidator: Extract<CallApiSchema[keyof CallApiSchema], AnyFunction>,\n\tinputData: TInput\n): Promise<StandardSchemaV1.Result<TInput>> => {\n\ttry {\n\t\tconst result = await validator(inputData as never);\n\n\t\treturn { issues: undefined, value: result as never };\n\t} catch (error) {\n\t\treturn { issues: toArray(error) as never, value: undefined };\n\t}\n};\n\nexport const standardSchemaParser = async <\n\tTFullSchema extends CallApiSchema,\n\tTSchemaName extends keyof CallApiSchema,\n\tTSchema extends NonNullable<TFullSchema[TSchemaName]>,\n>(\n\tfullSchema: TFullSchema | undefined,\n\tschemaName: TSchemaName,\n\tinputData: InferSchemaInput<TSchema>,\n\tresponse?: Response | null\n): Promise<InferSchemaOutputResult<TSchema>> => {\n\tconst schema = fullSchema?.[schemaName];\n\n\tif (!schema) {\n\t\treturn inputData as never;\n\t}\n\n\tconst result =\n\t\tisFunction(schema) ?\n\t\t\tawait handleValidatorFunction(schema, inputData)\n\t\t:\tawait schema[\"~standard\"].validate(inputData);\n\n\t// == If the `issues` field exists, it means the validation failed\n\n\tif (result.issues) {\n\t\tthrow new ValidationError({\n\t\t\tissueCause: schemaName,\n\t\t\tissues: result.issues,\n\t\t\tresponse: response ?? null,\n\t\t});\n\t}\n\n\treturn result.value as never;\n};\n\nexport interface CallApiSchemaConfig {\n\t/**\n\t * The base url of the schema. By default it's the baseURL of the callApi instance.\n\t */\n\tbaseURL?: string;\n\n\t/**\n\t * Disables runtime validation for the schema.\n\t */\n\tdisableRuntimeValidation?: boolean;\n\n\t/**\n\t * If `true`, the original input value will be used instead of the transformed/validated output.\n\t *\n\t * This is useful when you want to validate the input but don't want any transformations\n\t * applied by the validation schema (e.g., type coercion, default values, etc).\n\t */\n\tdisableValidationOutputApplication?: boolean;\n\n\t/**\n\t * Optional url prefix that will be substituted for the `baseURL` of the schemaConfig at runtime.\n\t *\n\t * This allows you to reuse the same schema against different base URLs (for example,\n\t * swapping between `/api/v1` and `/api/v2`) without redefining the entire schema.\n\t */\n\tprefix?: string;\n\n\t/**\n\t * Controls the strictness of API route validation.\n\t *\n\t * When true:\n\t * - Only routes explicitly defined in the schema will be considered valid to typescript and the runtime.\n\t * - Attempting to call routes not defined in the schema will result in both type errors and runtime validation errors.\n\t * - Useful for ensuring API calls conform exactly to your schema definition\n\t *\n\t * When false or undefined (default):\n\t * - All routes will be allowed, whether they are defined in the schema or not\n\t */\n\tstrict?: boolean;\n}\n\nexport interface CallApiSchema {\n\t/**\n\t * The schema to use for validating the request body.\n\t */\n\tbody?: StandardSchemaV1<Body> | ((body: Body) => Awaitable<Body>);\n\n\t/**\n\t * The schema to use for validating the response data.\n\t */\n\tdata?: StandardSchemaV1 | ((data: unknown) => unknown);\n\n\t/**\n\t * The schema to use for validating the response error data.\n\t */\n\terrorData?: StandardSchemaV1 | ((errorData: unknown) => unknown);\n\n\t/**\n\t * The schema to use for validating the request headers.\n\t */\n\theaders?:\n\t\t| StandardSchemaV1<HeadersOption | undefined>\n\t\t| ((headers: HeadersOption) => Awaitable<HeadersOption | undefined>);\n\n\t/**\n\t * The schema to use for validating the meta option.\n\t */\n\tmeta?:\n\t\t| StandardSchemaV1<GlobalMeta | undefined>\n\t\t| ((meta: GlobalMeta) => Awaitable<GlobalMeta | undefined>);\n\n\t/**\n\t * The schema to use for validating the request method.\n\t */\n\tmethod?:\n\t\t| StandardSchemaV1<MethodUnion | undefined>\n\t\t| ((method: MethodUnion) => Awaitable<MethodUnion | undefined>);\n\n\t/**\n\t * The schema to use for validating the request url parameters.\n\t */\n\tparams?: StandardSchemaV1<Params | undefined> | ((params: Params) => Awaitable<Params | undefined>);\n\n\t/**\n\t * The schema to use for validating the request url queries.\n\t */\n\tquery?: StandardSchemaV1<Query | undefined> | ((query: Query) => Awaitable<Query | undefined>);\n}\n\nexport const routeKeyMethods = defineEnum([\"delete\", \"get\", \"patch\", \"post\", \"put\"]);\n\nexport type RouteKeyMethods = (typeof routeKeyMethods)[number];\n\nexport type RouteKeyMethodsURLUnion = `@${RouteKeyMethods}/`;\n\nexport type BaseCallApiSchemaRoutes = Partial<Record<AnyString | RouteKeyMethodsURLUnion, CallApiSchema>>;\n\nexport type BaseCallApiSchemaAndConfig = {\n\tconfig?: CallApiSchemaConfig;\n\troutes: BaseCallApiSchemaRoutes;\n};\n\ntype ValidationOptions<\n\tTSchema extends CallApiSchema[keyof CallApiSchema] = CallApiSchema[keyof CallApiSchema],\n> = {\n\tinputValue: InferSchemaInput<TSchema>;\n\tresponse?: Response | null;\n\tschemaConfig: CallApiSchemaConfig | undefined;\n};\n\nexport const handleSchemaValidation = async <\n\tTFullSchema extends CallApiSchema,\n\tTSchemaName extends keyof CallApiSchema,\n\tTSchema extends NonNullable<TFullSchema[TSchemaName]>,\n>(\n\tfullSchema: TFullSchema | undefined,\n\tschemaName: TSchemaName,\n\tvalidationOptions: ValidationOptions<TSchema>\n): Promise<InferSchemaOutputResult<TSchema>> => {\n\tconst { inputValue, response, schemaConfig } = validationOptions;\n\n\tif (schemaConfig?.disableRuntimeValidation) {\n\t\treturn inputValue as never;\n\t}\n\n\tconst validResult = await standardSchemaParser(fullSchema, schemaName, inputValue, response);\n\n\treturn validResult as never;\n};\n\ntype LastOf<TValue> =\n\tUnionToIntersection<TValue extends unknown ? () => TValue : never> extends () => infer R ? R : never;\n\ntype Push<TArray extends unknown[], TArrayItem> = [...TArray, TArrayItem];\n\ntype UnionToTuple<\n\tTUnion,\n\tTComputedLastUnion = LastOf<TUnion>,\n\tTComputedIsUnionEqualToNever = [TUnion] extends [never] ? true : false,\n> =\n\ttrue extends TComputedIsUnionEqualToNever ? []\n\t:\tPush<UnionToTuple<Exclude<TUnion, TComputedLastUnion>>, TComputedLastUnion>;\n\nexport type Tuple<TTuple, TArray extends TTuple[] = []> =\n\tUnionToTuple<TTuple>[\"length\"] extends TArray[\"length\"] ? [...TArray]\n\t:\tTuple<TTuple, [TTuple, ...TArray]>;\n\nconst extraOptionsToBeValidated = [\"meta\", \"params\", \"query\"] satisfies Tuple<\n\tExtract<keyof CallApiSchema, keyof CallApiExtraOptions>\n>;\n\ntype ExtraOptionsValidationOptions = {\n\toptions: CallApiExtraOptions;\n\tschema: CallApiSchema | undefined;\n\tschemaConfig: CallApiSchemaConfig | undefined;\n};\n\nconst handleExtraOptionsValidation = async (validationOptions: ExtraOptionsValidationOptions) => {\n\tconst { options, schema, schemaConfig } = validationOptions;\n\n\tconst validationResultArray = await Promise.all(\n\t\textraOptionsToBeValidated.map((schemaName) =>\n\t\t\thandleSchemaValidation(schema, schemaName, {\n\t\t\t\tinputValue: options[schemaName],\n\t\t\t\tschemaConfig,\n\t\t\t})\n\t\t)\n\t);\n\n\tconst validatedResultObject: Prettify<\n\t\tPick<CallApiExtraOptions, (typeof extraOptionsToBeValidated)[number]>\n\t> = {};\n\n\tfor (const [index, schemaName] of extraOptionsToBeValidated.entries()) {\n\t\tconst validationResult = validationResultArray[index];\n\n\t\tif (validationResult === undefined) continue;\n\n\t\tvalidatedResultObject[schemaName] = validationResult as never;\n\t}\n\n\treturn validatedResultObject;\n};\n\nconst requestOptionsToBeValidated = [\"body\", \"headers\", \"method\"] satisfies Tuple<\n\tExtract<keyof CallApiSchema, keyof CallApiRequestOptions>\n>;\n\ntype RequestOptionsValidationOptions = {\n\trequestOptions: CallApiRequestOptions;\n\tschema: CallApiSchema | undefined;\n\tschemaConfig: CallApiSchemaConfig | undefined;\n};\n\nconst handleRequestOptionsValidation = async (validationOptions: RequestOptionsValidationOptions) => {\n\tconst { requestOptions, schema, schemaConfig } = validationOptions;\n\n\tconst validationResultArray = await Promise.all(\n\t\trequestOptionsToBeValidated.map((schemaName) =>\n\t\t\thandleSchemaValidation(schema, schemaName, {\n\t\t\t\tinputValue: requestOptions[schemaName],\n\t\t\t\tschemaConfig,\n\t\t\t})\n\t\t)\n\t);\n\n\tconst validatedResultObject: Prettify<\n\t\tPick<CallApiRequestOptions, (typeof requestOptionsToBeValidated)[number]>\n\t> = {};\n\n\tfor (const [index, propertyKey] of requestOptionsToBeValidated.entries()) {\n\t\tconst validationResult = validationResultArray[index];\n\n\t\tif (validationResult === undefined) continue;\n\n\t\tvalidatedResultObject[propertyKey] = validationResult as never;\n\t}\n\n\treturn validatedResultObject;\n};\n\nexport const handleConfigValidation = async (\n\tvalidationOptions: GetResolvedSchemaContext\n\t\t& Omit<ExtraOptionsValidationOptions & RequestOptionsValidationOptions, \"schema\" | \"schemaConfig\">\n) => {\n\tconst { baseExtraOptions, currentRouteSchemaKey, extraOptions, options, requestOptions } =\n\t\tvalidationOptions;\n\n\tconst { currentRouteSchema, resolvedSchema } = getResolvedSchema({\n\t\tbaseExtraOptions,\n\t\tcurrentRouteSchemaKey,\n\t\textraOptions,\n\t});\n\n\tconst resolvedSchemaConfig = getResolvedSchemaConfig({ baseExtraOptions, extraOptions });\n\n\tif (resolvedSchemaConfig?.strict === true && !currentRouteSchema) {\n\t\tthrow new ValidationError({\n\t\t\tissueCause: \"schemaConfig-(strict)\",\n\t\t\tissues: [{ message: `Strict Mode - No schema found for route '${currentRouteSchemaKey}' ` }],\n\t\t\tresponse: null,\n\t\t});\n\t}\n\n\tif (resolvedSchemaConfig?.disableRuntimeValidation) {\n\t\treturn {\n\t\t\textraOptionsValidationResult: null,\n\t\t\trequestOptionsValidationResult: null,\n\t\t\tresolvedSchema,\n\t\t\tresolvedSchemaConfig,\n\t\t\tshouldApplySchemaOutput: false,\n\t\t};\n\t}\n\n\tconst [extraOptionsValidationResult, requestOptionsValidationResult] = await Promise.all([\n\t\thandleExtraOptionsValidation({\n\t\t\toptions,\n\t\t\tschema: resolvedSchema,\n\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t}),\n\t\thandleRequestOptionsValidation({\n\t\t\trequestOptions,\n\t\t\tschema: resolvedSchema,\n\t\t\tschemaConfig: resolvedSchemaConfig,\n\t\t}),\n\t]);\n\n\tconst shouldApplySchemaOutput =\n\t\t(Boolean(extraOptionsValidationResult) || Boolean(requestOptionsValidationResult))\n\t\t&& !resolvedSchemaConfig?.disableValidationOutputApplication;\n\n\treturn {\n\t\textraOptionsValidationResult,\n\t\trequestOptionsValidationResult,\n\t\tresolvedSchema,\n\t\tresolvedSchemaConfig,\n\t\tshouldApplySchemaOutput,\n\t};\n};\n\ntype GetResolvedSchemaContext = {\n\tbaseExtraOptions: BaseCallApiExtraOptions;\n\tcurrentRouteSchemaKey: string;\n\textraOptions: CallApiExtraOptions;\n};\n\nexport const fallBackRouteSchemaKey = \".\";\n\nexport type FallBackRouteSchemaKey = typeof fallBackRouteSchemaKey;\n\nexport const getResolvedSchema = (context: GetResolvedSchemaContext) => {\n\tconst { baseExtraOptions, currentRouteSchemaKey, extraOptions } = context;\n\n\tconst fallbackRouteSchema = baseExtraOptions.schema?.routes[fallBackRouteSchemaKey];\n\tconst currentRouteSchema = baseExtraOptions.schema?.routes[currentRouteSchemaKey];\n\n\tconst resolvedRouteSchema = {\n\t\t...fallbackRouteSchema,\n\t\t// == Current route schema takes precedence over fallback route schema\n\t\t...currentRouteSchema,\n\t} satisfies CallApiSchema as CallApiSchema | undefined;\n\n\tconst resolvedSchema =\n\t\tisFunction(extraOptions.schema) ?\n\t\t\textraOptions.schema({\n\t\t\t\tbaseSchemaRoutes: baseExtraOptions.schema?.routes ?? {},\n\t\t\t\tcurrentRouteSchema: resolvedRouteSchema ?? {},\n\t\t\t})\n\t\t:\t(extraOptions.schema ?? resolvedRouteSchema);\n\n\treturn { currentRouteSchema, resolvedSchema };\n};\n\nexport const getResolvedSchemaConfig = (\n\tcontext: Omit<GetResolvedSchemaContext, \"currentRouteSchemaKey\">\n) => {\n\tconst { baseExtraOptions, extraOptions } = context;\n\n\tconst resolvedSchemaConfig =\n\t\tisFunction(extraOptions.schemaConfig) ?\n\t\t\textraOptions.schemaConfig({ baseSchemaConfig: baseExtraOptions.schema?.config ?? {} })\n\t\t:\t(extraOptions.schemaConfig ?? baseExtraOptions.schema?.config);\n\n\treturn resolvedSchemaConfig;\n};\n\nexport const getCurrentRouteSchemaKeyAndMainInitURL = (\n\tcontext: Pick<GetResolvedSchemaContext, \"baseExtraOptions\" | \"extraOptions\"> & { initURL: string }\n) => {\n\tconst { baseExtraOptions, extraOptions, initURL } = context;\n\n\tconst schemaConfig = getResolvedSchemaConfig({ baseExtraOptions, extraOptions });\n\n\tlet currentRouteSchemaKey = initURL;\n\tlet mainInitURL = initURL;\n\n\tif (schemaConfig?.prefix && currentRouteSchemaKey.startsWith(schemaConfig.prefix)) {\n\t\tcurrentRouteSchemaKey = currentRouteSchemaKey.replace(schemaConfig.prefix, \"\");\n\n\t\tmainInitURL = mainInitURL.replace(schemaConfig.prefix, schemaConfig.baseURL ?? \"\");\n\t}\n\n\tif (schemaConfig?.baseURL && currentRouteSchemaKey.startsWith(schemaConfig.baseURL)) {\n\t\tcurrentRouteSchemaKey = currentRouteSchemaKey.replace(schemaConfig.baseURL, \"\");\n\t}\n\n\treturn { currentRouteSchemaKey, mainInitURL };\n};\n","import type { CallApiExtraOptions } from \"./types/common\";\nimport type { AnyString, UnmaskType } from \"./types/type-helpers\";\nimport { toQueryString } from \"./utils\";\nimport { isArray } from \"./utils/guards\";\nimport { type RouteKeyMethodsURLUnion, routeKeyMethods } from \"./validation\";\n\nconst slash = \"/\";\nconst colon = \":\";\nconst openBrace = \"{\";\nconst closeBrace = \"}\";\n\nconst mergeUrlWithParams = (url: string, params: CallApiExtraOptions[\"params\"]) => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tlet newUrl = url;\n\n\tif (isArray(params)) {\n\t\tconst urlParts = newUrl.split(slash);\n\n\t\t// == Find all parameters in order (both :param and {param} patterns)\n\t\tconst matchedParamsArray = urlParts.filter(\n\t\t\t(part) => part.startsWith(colon) || (part.startsWith(openBrace) && part.endsWith(closeBrace))\n\t\t);\n\n\t\tfor (const [paramIndex, matchedParam] of matchedParamsArray.entries()) {\n\t\t\tconst stringParamValue = String(params[paramIndex]);\n\t\t\tnewUrl = newUrl.replace(matchedParam, stringParamValue);\n\t\t}\n\n\t\treturn newUrl;\n\t}\n\n\t// == Handle object params - replace both :param and {param} patterns\n\tfor (const [paramKey, paramValue] of Object.entries(params)) {\n\t\tconst colonPattern = `${colon}${paramKey}` as const;\n\t\tconst bracePattern = `${openBrace}${paramKey}${closeBrace}` as const;\n\t\tconst stringValue = String(paramValue);\n\n\t\tnewUrl = newUrl.replace(colonPattern, stringValue);\n\t\tnewUrl = newUrl.replace(bracePattern, stringValue);\n\t}\n\n\treturn newUrl;\n};\n\nconst questionMark = \"?\";\nconst ampersand = \"&\";\nconst mergeUrlWithQuery = (url: string, query: CallApiExtraOptions[\"query\"]): string => {\n\tif (!query) {\n\t\treturn url;\n\t}\n\n\tconst queryString = toQueryString(query);\n\n\tif (queryString?.length === 0) {\n\t\treturn url;\n\t}\n\n\tif (url.endsWith(questionMark)) {\n\t\treturn `${url}${queryString}`;\n\t}\n\n\tif (url.includes(questionMark)) {\n\t\treturn `${url}${ampersand}${queryString}`;\n\t}\n\n\treturn `${url}${questionMark}${queryString}`;\n};\n\n/**\n * @description Extracts the HTTP method from method-prefixed route patterns.\n *\n * Analyzes URLs that start with method modifiers (e.g., \"@get/\", \"@post/\") and extracts\n * the HTTP method for use in API requests. This enables method specification directly\n * in route definitions.\n *\n * @param initURL - The URL string to analyze for method modifiers\n * @returns The extracted HTTP method (lowercase) if found, otherwise undefined\n *\n * @example\n * ```typescript\n * // Method extraction from prefixed routes\n * extractMethodFromURL(\"@get/users\"); // Returns: \"get\"\n * extractMethodFromURL(\"@post/users\"); // Returns: \"post\"\n * extractMethodFromURL(\"@put/users/:id\"); // Returns: \"put\"\n * extractMethodFromURL(\"@delete/users/:id\"); // Returns: \"delete\"\n * extractMethodFromURL(\"@patch/users/:id\"); // Returns: \"patch\"\n *\n * // No method modifier\n * extractMethodFromURL(\"/users\"); // Returns: undefined\n * extractMethodFromURL(\"users\"); // Returns: undefined\n *\n * // Invalid or unsupported methods\n * extractMethodFromURL(\"@invalid/users\"); // Returns: undefined\n * extractMethodFromURL(\"@/users\"); // Returns: undefined\n *\n * // Edge cases\n * extractMethodFromURL(undefined); // Returns: undefined\n * extractMethodFromURL(\"\"); // Returns: undefined\n * ```\n */\nexport const extractMethodFromURL = (initURL: string | undefined) => {\n\tif (!initURL?.startsWith(\"@\")) return;\n\n\tconst method = initURL.split(\"@\")[1]?.split(\"/\")[0];\n\n\tif (!method || !routeKeyMethods.includes(method as (typeof routeKeyMethods)[number])) return;\n\n\treturn method;\n};\n\nconst normalizeURL = (initURL: string) => {\n\tconst methodFromURL = extractMethodFromURL(initURL);\n\n\tif (!methodFromURL) {\n\t\treturn initURL;\n\t}\n\n\tconst normalizedURL = initURL.replace(`@${methodFromURL}/`, \"/\");\n\n\treturn normalizedURL;\n};\n\ntype GetFullURLOptions = {\n\t/** Base URL to prepend to relative URLs */\n\tbaseURL: string | undefined;\n\t/** Initial URL pattern that may contain parameters and method modifiers */\n\tinitURL: string;\n\t/** Parameters to substitute into the URL path */\n\tparams: CallApiExtraOptions[\"params\"];\n\t/** Query parameters to append to the URL */\n\tquery: CallApiExtraOptions[\"query\"];\n};\n\nexport const getFullAndNormalizedURL = (options: GetFullURLOptions) => {\n\tconst { baseURL, initURL, params, query } = options;\n\n\tconst normalizedInitURL = normalizeURL(initURL);\n\n\tconst urlWithMergedParams = mergeUrlWithParams(normalizedInitURL, params);\n\n\tconst urlWithMergedQueryAndParams = mergeUrlWithQuery(urlWithMergedParams, query);\n\n\tconst shouldPrependBaseURL = !urlWithMergedQueryAndParams.startsWith(\"http\") && baseURL;\n\n\tconst fullURL =\n\t\tshouldPrependBaseURL ? `${baseURL}${urlWithMergedQueryAndParams}` : urlWithMergedQueryAndParams;\n\n\treturn {\n\t\tfullURL,\n\t\tnormalizedInitURL,\n\t};\n};\n\nexport type AllowedQueryParamValues = UnmaskType<boolean | number | string>;\n\nexport type RecordStyleParams = UnmaskType<Record<string, AllowedQueryParamValues>>;\n\nexport type TupleStyleParams = UnmaskType<AllowedQueryParamValues[]>;\n\nexport type Params = UnmaskType<RecordStyleParams | TupleStyleParams>;\n\nexport type Query = UnmaskType<Record<string, AllowedQueryParamValues>>;\n\nexport type InitURLOrURLObject = AnyString | RouteKeyMethodsURLUnion | URL;\n\nexport interface URLOptions {\n\t/**\n\t * Base URL for all API requests. Will only be prepended to relative URLs.\n\t *\n\t * Absolute URLs (starting with http/https) will not be prepended by the baseURL.\n\t *\n\t * @example\n\t * ```ts\n\t * // Set base URL for all requests\n\t * baseURL: \"https://api.example.com/v1\"\n\t *\n\t * // Then use relative URLs in requests\n\t * callApi(\"/users\") // → https://api.example.com/v1/users\n\t * callApi(\"/posts/123\") // → https://api.example.com/v1/posts/123\n\t *\n\t * // Environment-specific base URLs\n\t * baseURL: process.env.NODE_ENV === \"production\"\n\t * ? \"https://api.example.com\"\n\t * : \"http://localhost:3000/api\"\n\t * ```\n\t */\n\tbaseURL?: string;\n\n\t/**\n\t * Resolved request URL after processing baseURL, parameters, and query strings (readonly)\n\t *\n\t * This is the final URL that will be used for the HTTP request, computed from\n\t * baseURL, initURL, params, and query parameters.\n\t *\n\t */\n\treadonly fullURL?: string;\n\n\t/**\n\t * The original URL string passed to the callApi instance (readonly)\n\t *\n\t * This preserves the original URL as provided, including any method modifiers like \"@get/\" or \"@post/\".\n\t *\n\t */\n\treadonly initURL?: string;\n\n\t/**\n\t * The URL string after normalization, with method modifiers removed(readonly)\n\t *\n\t * Method modifiers like \"@get/\", \"@post/\" are stripped to create a clean URL\n\t * for parameter substitution and final URL construction.\n\t *\n\t */\n\treadonly initURLNormalized?: string;\n\n\t/**\n\t * Parameters to be substituted into URL path segments.\n\t *\n\t * Supports both object-style (named parameters) and array-style (positional parameters)\n\t * for flexible URL parameter substitution.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Object-style parameters (recommended)\n\t * const namedParams: URLOptions = {\n\t * initURL: \"/users/:userId/posts/:postId\",\n\t * params: { userId: \"123\", postId: \"456\" }\n\t * };\n\t * // Results in: /users/123/posts/456\n\t *\n\t * // Array-style parameters (positional)\n\t * const positionalParams: URLOptions = {\n\t * initURL: \"/users/:userId/posts/:postId\",\n\t * params: [\"123\", \"456\"] // Maps in order: userId=123, postId=456\n\t * };\n\t * // Results in: /users/123/posts/456\n\t *\n\t * // Single parameter\n\t * const singleParam: URLOptions = {\n\t * initURL: \"/users/:id\",\n\t * params: { id: \"user-123\" }\n\t * };\n\t * // Results in: /users/user-123\n\t * ```\n\t */\n\tparams?: Params;\n\n\t/**\n\t * Query parameters to append to the URL as search parameters.\n\t *\n\t * These will be serialized into the URL query string using standard\n\t * URL encoding practices.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Basic query parameters\n\t * const queryOptions: URLOptions = {\n\t * initURL: \"/users\",\n\t * query: {\n\t * page: 1,\n\t * limit: 10,\n\t * search: \"john doe\",\n\t * active: true\n\t * }\n\t * };\n\t * // Results in: /users?page=1&limit=10&search=john%20doe&active=true\n\t *\n\t * // Filtering and sorting\n\t * const filterOptions: URLOptions = {\n\t * initURL: \"/products\",\n\t * query: {\n\t * category: \"electronics\",\n\t * minPrice: 100,\n\t * maxPrice: 500,\n\t * sortBy: \"price\",\n\t * order: \"asc\"\n\t * }\n\t * };\n\t * // Results in: /products?category=electronics&minPrice=100&maxPrice=500&sortBy=price&order=asc\n\t * ```\n\t */\n\tquery?: Query;\n}\n","export const createCombinedSignalPolyfill = (signals: AbortSignal[]) => {\n\tconst controller = new AbortController();\n\n\tconst handleAbort = (actualSignal: AbortSignal) => {\n\t\tif (controller.signal.aborted) return;\n\n\t\tcontroller.abort(actualSignal.reason);\n\t};\n\n\tfor (const actualSignal of signals) {\n\t\tif (actualSignal.aborted) {\n\t\t\thandleAbort(actualSignal);\n\t\t\tbreak;\n\t\t}\n\n\t\tactualSignal.addEventListener(\"abort\", () => handleAbort(actualSignal), {\n\t\t\tsignal: controller.signal,\n\t\t});\n\t}\n\n\treturn controller.signal;\n};\n","export const createTimeoutSignalPolyfill = (milliseconds: number) => {\n\tconst controller = new AbortController();\n\n\tconst reason = new DOMException(\"Request timed out\", \"TimeoutError\");\n\n\tconst timeout = setTimeout(() => controller.abort(reason), milliseconds);\n\n\tcontroller.signal.addEventListener(\"abort\", () => clearTimeout(timeout));\n\n\treturn controller.signal;\n};\n","import { getAuthHeader } from \"../auth\";\nimport { fetchSpecificKeys } from \"../constants/common\";\nimport { extraOptionDefaults, requestOptionDefaults } from \"../constants/defaults\";\nimport type { RequestContext } from \"../hooks\";\nimport type { Middlewares } from \"../middlewares\";\nimport type { BaseCallApiExtraOptions, CallApiExtraOptions, CallApiRequestOptions } from \"../types/common\";\nimport { extractMethodFromURL } from \"../url\";\nimport {\n\tisArray,\n\tisFunction,\n\tisPlainObject,\n\tisQueryString,\n\tisSerializable,\n\tisValidJsonString,\n} from \"./guards\";\nimport { createCombinedSignalPolyfill, createTimeoutSignalPolyfill } from \"./polyfills\";\n\nexport const omitKeys = <\n\tTObject extends Record<string, unknown>,\n\tconst TOmitArray extends Array<keyof TObject> | ReadonlyArray<keyof TObject>,\n>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst updatedObject = {} as Record<string, unknown>;\n\n\tconst keysToOmitSet = new Set(keysToOmit);\n\n\tfor (const [key, value] of Object.entries(initialObject)) {\n\t\tif (!keysToOmitSet.has(key)) {\n\t\t\tupdatedObject[key] = value;\n\t\t}\n\t}\n\n\treturn updatedObject as Omit<TObject, TOmitArray[number]>;\n};\n\nexport const pickKeys = <\n\tTObject extends Record<string, unknown>,\n\tconst TPickArray extends Array<keyof TObject> | ReadonlyArray<keyof TObject>,\n>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst updatedObject = {} as Record<string, unknown>;\n\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tfor (const [key, value] of Object.entries(initialObject)) {\n\t\tif (keysToPickSet.has(key)) {\n\t\t\tupdatedObject[key] = value;\n\t\t}\n\t}\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\n// eslint-disable-next-line ts-eslint/no-explicit-any -- Any is required here so that one can pass custom function type without type errors\nexport const splitBaseConfig = (baseConfig: Record<string, any>) =>\n\t[\n\t\tpickKeys(baseConfig, fetchSpecificKeys) as CallApiRequestOptions,\n\t\tomitKeys(baseConfig, fetchSpecificKeys) as BaseCallApiExtraOptions,\n\t] as const;\n\n// eslint-disable-next-line ts-eslint/no-explicit-any -- Any is required here so that one can pass custom function type without type errors\nexport const splitConfig = (config: Record<string, any>) =>\n\t[\n\t\tpickKeys(config, fetchSpecificKeys) as CallApiRequestOptions,\n\t\tomitKeys(config, fetchSpecificKeys) as CallApiExtraOptions,\n\t] as const;\n\ntype ToQueryStringFn = {\n\t(params: CallApiExtraOptions[\"query\"]): string | null;\n\t(params: Required<CallApiExtraOptions>[\"query\"]): string;\n};\n\nexport const toQueryString: ToQueryStringFn = (params) => {\n\tif (!params) {\n\t\tconsole.error(\"toQueryString:\", \"No query params provided!\");\n\n\t\treturn null as never;\n\t}\n\n\treturn new URLSearchParams(params as Record<string, string>).toString();\n};\n\nexport const objectifyHeaders = (headers: CallApiRequestOptions[\"headers\"]) => {\n\tif (!headers || isPlainObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(headers);\n};\n\nexport type GetHeadersOptions = {\n\tauth: CallApiExtraOptions[\"auth\"];\n\tbody: CallApiRequestOptions[\"body\"];\n\theaders: CallApiRequestOptions[\"headers\"];\n};\n\nexport const getHeaders = async (options: GetHeadersOptions) => {\n\tconst { auth, body, headers } = options;\n\n\t// == Return early if any of the following conditions are not met (so that native fetch would auto set the correct headers):\n\tconst shouldResolveHeaders = Boolean(headers) || Boolean(body) || Boolean(auth);\n\n\tif (!shouldResolveHeaders) return;\n\n\tconst headersObject: Record<string, string | undefined> = {\n\t\t...(await getAuthHeader(auth)),\n\t\t...objectifyHeaders(headers),\n\t};\n\n\tif (isQueryString(body)) {\n\t\theadersObject[\"Content-Type\"] = \"application/x-www-form-urlencoded\";\n\n\t\treturn headersObject;\n\t}\n\n\tif (isSerializable(body) || isValidJsonString(body)) {\n\t\theadersObject[\"Content-Type\"] = \"application/json\";\n\t\theadersObject.Accept = \"application/json\";\n\t}\n\n\treturn headersObject;\n};\n\nexport type GetMethodContext = {\n\t/** The URL string that may contain method modifiers like \"@get/\" or \"@post/\" */\n\tinitURL: string | undefined;\n\t/** Explicitly specified HTTP method */\n\tmethod: CallApiRequestOptions[\"method\"];\n};\n\nexport const getMethod = (ctx: GetMethodContext) => {\n\tconst { initURL, method } = ctx;\n\n\treturn (\n\t\tmethod?.toUpperCase() ?? extractMethodFromURL(initURL)?.toUpperCase() ?? requestOptionDefaults.method\n\t);\n};\n\nexport type GetBodyOptions = {\n\tbody: CallApiRequestOptions[\"body\"];\n\tbodySerializer: CallApiExtraOptions[\"bodySerializer\"];\n};\n\nexport const getBody = (options: GetBodyOptions) => {\n\tconst { body, bodySerializer } = options;\n\n\tif (isSerializable(body)) {\n\t\tconst selectedBodySerializer = bodySerializer ?? extraOptionDefaults.bodySerializer;\n\n\t\treturn selectedBodySerializer(body);\n\t}\n\n\treturn body;\n};\n\nexport const getInitFetchImpl = (customFetchImpl: CallApiExtraOptions[\"customFetchImpl\"]) => {\n\tif (customFetchImpl) {\n\t\treturn customFetchImpl;\n\t}\n\n\tif (typeof globalThis !== \"undefined\" && isFunction(globalThis.fetch)) {\n\t\treturn globalThis.fetch;\n\t}\n\n\tthrow new Error(\"No fetch implementation found\");\n};\n\nexport const getFetchImpl = (context: {\n\tcustomFetchImpl: CallApiExtraOptions[\"customFetchImpl\"];\n\tfetchMiddleware: Middlewares[\"fetchMiddleware\"];\n\trequestContext: RequestContext;\n}) => {\n\tconst { customFetchImpl, fetchMiddleware, requestContext } = context;\n\n\tconst initFetchImpl = getInitFetchImpl(customFetchImpl);\n\n\tconst resolvedFetchImpl =\n\t\tfetchMiddleware ? fetchMiddleware({ ...requestContext, fetchImpl: initFetchImpl }) : initFetchImpl;\n\n\treturn resolvedFetchImpl;\n};\n\nconst PromiseWithResolvers = () => {\n\tlet reject!: (reason?: unknown) => void;\n\tlet resolve!: (value: unknown) => void;\n\n\tconst promise = new Promise((res, rej) => {\n\t\tresolve = res;\n\t\treject = rej;\n\t});\n\n\treturn { promise, reject, resolve };\n};\n\nexport const waitFor = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = PromiseWithResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n\nexport const createCombinedSignal = (...signals: Array<AbortSignal | null | undefined>) => {\n\tconst cleanedSignals = signals.filter((signal) => signal != null);\n\n\tif (!(\"any\" in AbortSignal)) {\n\t\treturn createCombinedSignalPolyfill(cleanedSignals);\n\t}\n\n\tconst combinedSignal = AbortSignal.any(cleanedSignals);\n\n\treturn combinedSignal;\n};\n\nexport const createTimeoutSignal = (milliseconds: number) => {\n\tif (!(\"timeout\" in AbortSignal)) {\n\t\treturn createTimeoutSignalPolyfill(milliseconds);\n\t}\n\n\treturn AbortSignal.timeout(milliseconds);\n};\n\nexport const deterministicHashFn = (value: unknown): string => {\n\treturn JSON.stringify(value, (_, val: unknown) => {\n\t\tif (!isPlainObject(val)) {\n\t\t\treturn val;\n\t\t}\n\n\t\tconst sortedKeys = Object.keys(val).toSorted();\n\n\t\tconst result: Record<string, unknown> = {};\n\n\t\tfor (const key of sortedKeys) {\n\t\t\tresult[key] = val[key];\n\t\t}\n\n\t\treturn result;\n\t});\n};\n\nexport const toArray = (value: unknown) => (isArray(value) ? value : [value]);\n"],"mappings":"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"}