@zayne-labs/callapi 1.11.28 → 1.11.29

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.
@@ -1,4 +1,4 @@
1
- import { r as fetchSpecificKeys, t as FallBackRouteSchemaKey } from "./validation-Dq--Q5zC.js";
1
+ import { r as fetchSpecificKeys, t as FallBackRouteSchemaKey } from "./validation-Do6HBp6Z.js";
2
2
 
3
3
  //#region src/types/type-helpers.d.ts
4
4
  type AnyString = string & NonNullable<unknown>;
@@ -15,11 +15,11 @@ type WriteableLevel = "deep" | "shallow";
15
15
  type ArrayOrObject = Record<number | string | symbol, unknown> | unknown[] | readonly unknown[];
16
16
  type Writeable<TObject, TLevel extends WriteableLevel = "shallow"> = TObject extends ArrayOrObject ? { -readonly [Key in keyof TObject]: TLevel extends "deep" ? NonNullable<TObject[Key]> extends ArrayOrObject ? Writeable<TObject[Key], "deep"> : TObject[Key] : TObject[Key] } : TObject;
17
17
  type UnionToIntersection<TUnion> = (TUnion extends unknown ? (param: TUnion) => void : never) extends ((param: infer TParam) => void) ? TParam : never;
18
- type UnmaskType<TValue$1> = {
19
- _: TValue$1;
18
+ type UnmaskType<TValue> = {
19
+ _: TValue;
20
20
  }["_"];
21
21
  type RemovePrefix<TPrefix extends "dedupe" | "retry", TKey extends string> = TKey extends `${TPrefix}${infer TRest}` ? Uncapitalize<TRest> : TKey;
22
- type Awaitable<TValue$1> = Promise<TValue$1> | TValue$1;
22
+ type Awaitable<TValue> = Promise<TValue> | TValue;
23
23
  type Satisfies<TActualObject extends TExpectedObject, TExpectedObject> = { [Key in keyof TActualObject]: Key extends keyof TExpectedObject ? TActualObject[Key] : never };
24
24
  type DistributiveOmit<TObject, TKeysToOmit extends keyof TObject> = TObject extends unknown ? Omit<TObject, TKeysToOmit> : never;
25
25
  type CommonRequestHeaders = "Access-Control-Allow-Credentials" | "Access-Control-Allow-Headers" | "Access-Control-Allow-Methods" | "Access-Control-Allow-Origin" | "Access-Control-Expose-Headers" | "Access-Control-Max-Age" | "Age" | "Allow" | "Cache-Control" | "Clear-Site-Data" | "Content-Disposition" | "Content-Encoding" | "Content-Language" | "Content-Length" | "Content-Location" | "Content-Range" | "Content-Security-Policy-Report-Only" | "Content-Security-Policy" | "Cookie" | "Cross-Origin-Embedder-Policy" | "Cross-Origin-Opener-Policy" | "Cross-Origin-Resource-Policy" | "Date" | "ETag" | "Expires" | "Last-Modified" | "Location" | "Permissions-Policy" | "Pragma" | "Retry-After" | "Save-Data" | "Sec-CH-Prefers-Color-Scheme" | "Sec-CH-Prefers-Reduced-Motion" | "Sec-CH-UA-Arch" | "Sec-CH-UA-Bitness" | "Sec-CH-UA-Form-Factor" | "Sec-CH-UA-Full-Version-List" | "Sec-CH-UA-Full-Version" | "Sec-CH-UA-Mobile" | "Sec-CH-UA-Model" | "Sec-CH-UA-Platform-Version" | "Sec-CH-UA-Platform" | "Sec-CH-UA-WoW64" | "Sec-CH-UA" | "Sec-Fetch-Dest" | "Sec-Fetch-Mode" | "Sec-Fetch-Site" | "Sec-Fetch-User" | "Sec-GPC" | "Server-Timing" | "Server" | "Service-Worker-Navigation-Preload" | "Set-Cookie" | "Strict-Transport-Security" | "Timing-Allow-Origin" | "Trailer" | "Transfer-Encoding" | "Upgrade" | "Vary" | "Warning" | "WWW-Authenticate" | "X-Content-Type-Options" | "X-DNS-Prefetch-Control" | "X-Frame-Options" | "X-Permitted-Cross-Domain-Policies" | "X-Powered-By" | "X-Robots-Tag" | "X-XSS-Protection" | AnyString;
@@ -65,225 +65,34 @@ type CustomAuth = {
65
65
  };
66
66
  type Auth = PossibleAuthValueOrGetter | BearerOrTokenAuth | BasicAuth | CustomAuth;
67
67
  //#endregion
68
- //#region src/dedupe.d.ts
69
- type DedupeStrategyUnion = UnmaskType<"cancel" | "defer" | "none">;
70
- type DedupeOptionKeys = Exclude<keyof DedupeOptions, "dedupe">;
71
- type InnerDedupeOptions = { [Key in DedupeOptionKeys as RemovePrefix<"dedupe", Key>]?: DedupeOptions[Key] };
72
- type DedupeOptions = {
73
- /**
74
- * All dedupe options in a single object instead of separate properties
75
- */
76
- dedupe?: InnerDedupeOptions;
68
+ //#region src/stream.d.ts
69
+ type StreamProgressEvent = {
77
70
  /**
78
- * Controls the scope of request deduplication caching.
79
- *
80
- * - `"global"`: Shares deduplication cache across all `createFetchClient` instances with the same `dedupeCacheScopeKey`.
81
- * Useful for applications with multiple API clients that should share deduplication state.
82
- * - `"local"`: Limits deduplication to requests within the same `createFetchClient` instance.
83
- * Provides better isolation and is recommended for most use cases.
84
- *
85
- *
86
- * **Real-world Scenarios:**
87
- * - Use `"global"` when you have multiple API clients (user service, auth service, etc.) that might make overlapping requests
88
- * - Use `"local"` (default) for single-purpose clients or when you want strict isolation between different parts of your app
89
- *
90
- * @example
91
- * ```ts
92
- * // Local scope - each client has its own deduplication cache
93
- * const userClient = createFetchClient({ baseURL: "/api/users" });
94
- * const postClient = createFetchClient({ baseURL: "/api/posts" });
95
- * // These clients won't share deduplication state
96
- *
97
- * // Global scope - share cache across related clients
98
- * const userClient = createFetchClient({
99
- * baseURL: "/api/users",
100
- * dedupeCacheScope: "global",
101
- * });
102
- * const postClient = createFetchClient({
103
- * baseURL: "/api/posts",
104
- * dedupeCacheScope: "global",
105
- * });
106
- * // These clients will share deduplication state
107
- * ```
108
- *
109
- * @default "local"
71
+ * Current chunk of data being streamed
110
72
  */
111
- dedupeCacheScope?: "global" | "local";
73
+ chunk: Uint8Array;
112
74
  /**
113
- * Unique namespace for the global deduplication cache when using `dedupeCacheScope: "global"`.
114
- *
115
- * This creates logical groupings of deduplication caches. All instances with the same key
116
- * will share the same cache namespace, allowing fine-grained control over which clients
117
- * share deduplication state.
118
- *
119
- * **Best Practices:**
120
- * - Use descriptive names that reflect the logical grouping (e.g., "user-service", "analytics-api")
121
- * - Keep scope keys consistent across related API clients
122
- * - Consider using different scope keys for different environments (dev, staging, prod)
123
- * - Avoid overly broad scope keys that might cause unintended cache sharing
124
- *
125
- * **Cache Management:**
126
- * - Each scope key maintains its own independent cache
127
- * - Caches are automatically cleaned up when no references remain
128
- * - Consider the memory implications of multiple global scopes
129
- *
130
- * @example
131
- * ```ts
132
- * // Group related API clients together
133
- * const userClient = createFetchClient({
134
- * baseURL: "/api/users",
135
- * dedupeCacheScope: "global",
136
- * dedupeCacheScopeKey: "user-service"
137
- * });
138
- * const profileClient = createFetchClient({
139
- * baseURL: "/api/profiles",
140
- * dedupeCacheScope: "global",
141
- * dedupeCacheScopeKey: "user-service" // Same scope - will share cache
142
- * });
143
- *
144
- * // Separate analytics client with its own cache
145
- * const analyticsClient = createFetchClient({
146
- * baseURL: "/api/analytics",
147
- * dedupeCacheScope: "global",
148
- * dedupeCacheScopeKey: "analytics-service" // Different scope
149
- * });
150
- *
151
- * // Environment-specific scoping
152
- * const apiClient = createFetchClient({
153
- * dedupeCacheScope: "global",
154
- * dedupeCacheScopeKey: `api-${process.env.NODE_ENV}` // "api-development", "api-production", etc.
155
- * });
156
- * ```
157
- *
158
- * @default "default"
75
+ * Progress in percentage
159
76
  */
160
- dedupeCacheScopeKey?: "default" | AnyString | ((context: RequestContext) => string | undefined);
77
+ progress: number;
161
78
  /**
162
- * Custom key generator for request deduplication.
163
- *
164
- * Override the default key generation strategy to control exactly which requests
165
- * are considered duplicates. The default key combines URL, method, body, and
166
- * relevant headers (excluding volatile ones like 'Date', 'Authorization', etc.).
167
- *
168
- * **Default Key Generation:**
169
- * The auto-generated key includes:
170
- * - Full request URL (including query parameters)
171
- * - HTTP method (GET, POST, etc.)
172
- * - Request body (for POST/PUT/PATCH requests)
173
- * - Stable headers (excludes Date, Authorization, User-Agent, etc.)
174
- *
175
- * **Custom Key Best Practices:**
176
- * - Include only the parts of the request that should affect deduplication
177
- * - Avoid including volatile data (timestamps, random IDs, etc.)
178
- * - Consider performance - simpler keys are faster to compute and compare
179
- * - Ensure keys are deterministic for the same logical request
180
- * - Use consistent key formats across your application
181
- *
182
- * **Performance Considerations:**
183
- * - Function-based keys are computed on every request - keep them lightweight
184
- * - String keys are fastest but least flexible
185
- * - Consider caching expensive key computations if needed
186
- *
187
- * @example
188
- * ```ts
189
- * import { callApi } from "@zayne-labs/callapi";
190
- *
191
- * // Simple static key - useful for singleton requests
192
- * const config = callApi("/api/config", {
193
- * dedupeKey: "app-config",
194
- * dedupeStrategy: "defer" // Share the same config across all requests
195
- * });
196
- *
197
- * // URL and method only - ignore headers and body
198
- * const userData = callApi("/api/user/123", {
199
- * dedupeKey: (context) => `${context.options.method}:${context.options.fullURL}`
200
- * });
201
- *
202
- * // Include specific headers in deduplication
203
- * const apiCall = callApi("/api/data", {
204
- * dedupeKey: (context) => {
205
- * const authHeader = context.request.headers.get("Authorization");
206
- * return `${context.options.fullURL}-${authHeader}`;
207
- * }
208
- * });
209
- *
210
- * // User-specific deduplication
211
- * const userSpecificCall = callApi("/api/dashboard", {
212
- * dedupeKey: (context) => {
213
- * const userId = context.options.fullURL.match(/user\/(\d+)/)?.[1];
214
- * return `dashboard-${userId}`;
215
- * }
216
- * });
217
- *
218
- * // Ignore certain query parameters
219
- * const searchCall = callApi("/api/search?q=test&timestamp=123456", {
220
- * dedupeKey: (context) => {
221
- * const url = new URL(context.options.fullURL);
222
- * url.searchParams.delete("timestamp"); // Remove volatile param
223
- * return `search:${url.toString()}`;
224
- * }
225
- * });
226
- * ```
227
- *
228
- * @default Auto-generated from request details
79
+ * Total size of data in bytes
229
80
  */
230
- dedupeKey?: string | ((context: RequestContext) => string | undefined);
81
+ totalBytes: number;
231
82
  /**
232
- * Strategy for handling duplicate requests. Can be a static string or callback function.
233
- *
234
- * **Available Strategies:**
235
- * - `"cancel"`: Cancel previous request when new one starts (good for search)
236
- * - `"defer"`: Share response between duplicate requests (good for config loading)
237
- * - `"none"`: No deduplication, all requests execute independently
238
- *
239
- * @example
240
- * ```ts
241
- * // Static strategies
242
- * const searchClient = createFetchClient({
243
- * dedupeStrategy: "cancel" // Cancel previous searches
244
- * });
245
- *
246
- * const configClient = createFetchClient({
247
- * dedupeStrategy: "defer" // Share config across components
248
- * });
249
- *
250
- * // Dynamic strategy based on request
251
- * const smartClient = createFetchClient({
252
- * dedupeStrategy: (context) => {
253
- * return context.options.method === "GET" ? "defer" : "cancel";
254
- * }
255
- * });
256
- *
257
- * // Search-as-you-type with cancel strategy
258
- * const handleSearch = async (query: string) => {
259
- * try {
260
- * const { data } = await callApi("/api/search", {
261
- * method: "POST",
262
- * body: { query },
263
- * dedupeStrategy: "cancel",
264
- * dedupeKey: "search" // Cancel previous searches, only latest one goes through
265
- * });
266
- *
267
- * updateSearchResults(data);
268
- * } catch (error) {
269
- * if (error.name === "AbortError") {
270
- * // Previous search cancelled - (expected behavior)
271
- * return;
272
- * }
273
- * console.error("Search failed:", error);
274
- * }
275
- * };
276
- *
277
- * ```
278
- *
279
- * @default "cancel"
83
+ * Amount of data transferred so far
280
84
  */
281
- dedupeStrategy?: DedupeStrategyUnion | ((context: RequestContext) => DedupeStrategyUnion);
85
+ transferredBytes: number;
282
86
  };
87
+ declare global {
88
+ interface ReadableStream<R$1 = any> {
89
+ [Symbol.asyncIterator]: () => AsyncIterableIterator<R$1>;
90
+ }
91
+ }
283
92
  //#endregion
284
93
  //#region src/middlewares.d.ts
285
94
  type FetchImpl = UnmaskType<(input: string | Request | URL, init?: RequestInit) => Promise<Response>>;
286
- interface Middlewares<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> {
95
+ interface Middlewares<TCallApiContext extends CallApiContext = DefaultCallApiContext> {
287
96
  /**
288
97
  * Wraps the fetch implementation to intercept requests at the network layer.
289
98
  *
@@ -297,6 +106,7 @@ interface Middlewares<TCallApiContext$1 extends CallApiContext = DefaultCallApiC
297
106
  * ```ts
298
107
  * // Cache responses
299
108
  * const cache = new Map();
109
+ *
300
110
  * fetchMiddleware: (ctx) => async (input, init) => {
301
111
  * const key = input.toString();
302
112
  * if (cache.has(key)) return cache.get(key).clone();
@@ -315,175 +125,55 @@ interface Middlewares<TCallApiContext$1 extends CallApiContext = DefaultCallApiC
315
125
  * }
316
126
  * ```
317
127
  */
318
- fetchMiddleware?: (context: RequestContext<TCallApiContext$1> & {
128
+ fetchMiddleware?: (context: RequestContext<TCallApiContext> & {
319
129
  fetchImpl: FetchImpl;
320
130
  }) => FetchImpl;
321
131
  }
322
132
  //#endregion
323
- //#region src/url.d.ts
324
- type AllowedQueryParamValues = UnmaskType<boolean | number | string>;
325
- type RecordStyleParams = UnmaskType<Record<string, AllowedQueryParamValues>>;
326
- type TupleStyleParams = UnmaskType<AllowedQueryParamValues[]>;
327
- type Params = UnmaskType<RecordStyleParams | TupleStyleParams>;
328
- type Query = UnmaskType<Record<string, AllowedQueryParamValues>>;
329
- type InitURLOrURLObject = AnyString | RouteKeyMethodsURLUnion | URL;
330
- interface URLOptions {
331
- /**
332
- * Base URL for all API requests. Will only be prepended to relative URLs.
333
- *
334
- * Absolute URLs (starting with http/https) will not be prepended by the baseURL.
335
- *
336
- * @example
337
- * ```ts
338
- * // Set base URL for all requests
339
- * baseURL: "https://api.example.com/v1"
340
- *
341
- * // Then use relative URLs in requests
342
- * callApi("/users") // → https://api.example.com/v1/users
343
- * callApi("/posts/123") // → https://api.example.com/v1/posts/123
344
- *
345
- * // Environment-specific base URLs
346
- * baseURL: process.env.NODE_ENV === "production"
347
- * ? "https://api.example.com"
348
- * : "http://localhost:3000/api"
349
- * ```
350
- */
351
- baseURL?: string;
352
- /**
353
- * Resolved request URL after processing baseURL, parameters, and query strings (readonly)
354
- *
355
- * This is the final URL that will be used for the HTTP request, computed from
356
- * baseURL, initURL, params, and query parameters.
357
- *
358
- */
359
- readonly fullURL?: string;
360
- /**
361
- * The original URL string passed to the callApi instance (readonly)
362
- *
363
- * This preserves the original URL as provided, including any method modifiers like "@get/" or "@post/".
364
- *
365
- */
366
- readonly initURL?: string;
367
- /**
368
- * The URL string after normalization, with method modifiers removed(readonly)
369
- *
370
- * Method modifiers like "@get/", "@post/" are stripped to create a clean URL
371
- * for parameter substitution and final URL construction.
372
- *
373
- */
374
- readonly initURLNormalized?: string;
375
- /**
376
- * Parameters to be substituted into URL path segments.
377
- *
378
- * Supports both object-style (named parameters) and array-style (positional parameters)
379
- * for flexible URL parameter substitution.
380
- *
381
- * @example
382
- * ```typescript
383
- * // Object-style parameters (recommended)
384
- * const namedParams: URLOptions = {
385
- * initURL: "/users/:userId/posts/:postId",
386
- * params: { userId: "123", postId: "456" }
387
- * };
388
- * // Results in: /users/123/posts/456
389
- *
390
- * // Array-style parameters (positional)
391
- * const positionalParams: URLOptions = {
392
- * initURL: "/users/:userId/posts/:postId",
393
- * params: ["123", "456"] // Maps in order: userId=123, postId=456
394
- * };
395
- * // Results in: /users/123/posts/456
396
- *
397
- * // Single parameter
398
- * const singleParam: URLOptions = {
399
- * initURL: "/users/:id",
400
- * params: { id: "user-123" }
401
- * };
402
- * // Results in: /users/user-123
403
- * ```
404
- */
405
- params?: Params;
406
- /**
407
- * Query parameters to append to the URL as search parameters.
408
- *
409
- * These will be serialized into the URL query string using standard
410
- * URL encoding practices.
411
- *
412
- * @example
413
- * ```typescript
414
- * // Basic query parameters
415
- * const queryOptions: URLOptions = {
416
- * initURL: "/users",
417
- * query: {
418
- * page: 1,
419
- * limit: 10,
420
- * search: "john doe",
421
- * active: true
422
- * }
423
- * };
424
- * // Results in: /users?page=1&limit=10&search=john%20doe&active=true
425
- *
426
- * // Filtering and sorting
427
- * const filterOptions: URLOptions = {
428
- * initURL: "/products",
429
- * query: {
430
- * category: "electronics",
431
- * minPrice: 100,
432
- * maxPrice: 500,
433
- * sortBy: "price",
434
- * order: "asc"
435
- * }
436
- * };
437
- * // Results in: /products?category=electronics&minPrice=100&maxPrice=500&sortBy=price&order=asc
438
- * ```
439
- */
440
- query?: Query;
441
- }
442
- //#endregion
443
- //#region src/types/conditional-types.d.ts
444
- /**
445
- * @description Makes a type partial if the output type of TSchema is not provided or has undefined in the union, otherwise makes it required
446
- */
447
- type MakeSchemaOptionRequiredIfDefined<TSchemaOption extends CallApiSchema[keyof CallApiSchema], TObject> = undefined extends InferSchemaOutput<TSchemaOption, undefined> ? TObject : Required<TObject>;
448
- type ApplyURLBasedConfig<TSchemaConfig$1 extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = TSchemaConfig$1["prefix"] extends string ? `${TSchemaConfig$1["prefix"]}${TSchemaRouteKeys}` : TSchemaConfig$1["baseURL"] extends string ? `${TSchemaConfig$1["baseURL"]}${TSchemaRouteKeys}` : TSchemaRouteKeys;
449
- type ApplyStrictConfig<TSchemaConfig$1 extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = TSchemaConfig$1["strict"] extends true ? TSchemaRouteKeys :
450
- // eslint-disable-next-line perfectionist/sort-union-types -- Don't sort union types
451
- TSchemaRouteKeys | Exclude<InitURLOrURLObject, RouteKeyMethodsURLUnion>;
452
- type ApplySchemaConfiguration<TSchemaConfig$1 extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = ApplyStrictConfig<TSchemaConfig$1, ApplyURLBasedConfig<TSchemaConfig$1, TSchemaRouteKeys>>;
453
- type InferAllRouteKeys<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TSchemaConfig$1 extends CallApiSchemaConfig> = ApplySchemaConfiguration<TSchemaConfig$1, Exclude<Extract<keyof TBaseSchemaRoutes$1, string>, FallBackRouteSchemaKey>>;
454
- type InferInitURL<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TSchemaConfig$1 extends CallApiSchemaConfig> = keyof TBaseSchemaRoutes$1 extends never ? InitURLOrURLObject : InferAllRouteKeys<TBaseSchemaRoutes$1, TSchemaConfig$1>;
455
- type GetCurrentRouteSchemaKey<TSchemaConfig$1 extends CallApiSchemaConfig, TPath> = TPath extends URL ? string : TSchemaConfig$1["baseURL"] extends string ? TPath extends `${TSchemaConfig$1["baseURL"]}${infer TCurrentRoute}` ? TCurrentRoute extends string ? TCurrentRoute : string : TPath extends `${TSchemaConfig$1["prefix"]}${infer TCurrentRoute}` ? TCurrentRoute extends string ? TCurrentRoute : string : string : TPath;
456
- type GetCurrentRouteSchema<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey$1 extends string, TComputedFallBackRouteSchema = TBaseSchemaRoutes$1[FallBackRouteSchemaKey], TComputedCurrentRouteSchema = TBaseSchemaRoutes$1[TCurrentRouteSchemaKey$1], TComputedRouteSchema extends CallApiSchema = NonNullable<Omit<TComputedFallBackRouteSchema, keyof TComputedCurrentRouteSchema> & TComputedCurrentRouteSchema>> = TComputedRouteSchema extends CallApiSchema ? Writeable<TComputedRouteSchema, "deep"> : CallApiSchema;
457
- type JsonPrimitive = boolean | number | string | null | undefined;
458
- type SerializableObject = Record<PropertyKey, unknown>;
459
- type SerializableArray = Array<JsonPrimitive | SerializableObject> | ReadonlyArray<JsonPrimitive | SerializableObject>;
460
- type Body = UnmaskType<Exclude<RequestInit["body"], undefined> | SerializableArray | SerializableObject>;
461
- type InferBodyOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["body"], {
133
+ //#region src/types/conditional-types.d.ts
134
+ /**
135
+ * @description Makes a type partial if the output type of TSchema is not provided or has undefined in the union, otherwise makes it required
136
+ */
137
+ type MakeSchemaOptionRequiredIfDefined<TSchemaOption extends CallApiSchema[keyof CallApiSchema], TObject> = undefined extends InferSchemaOutput<TSchemaOption, undefined> ? TObject : Required<TObject>;
138
+ type ApplyURLBasedConfig<TSchemaConfig extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = TSchemaConfig["prefix"] extends string ? `${TSchemaConfig["prefix"]}${TSchemaRouteKeys}` : TSchemaConfig["baseURL"] extends string ? `${TSchemaConfig["baseURL"]}${TSchemaRouteKeys}` : TSchemaRouteKeys;
139
+ type ApplyStrictConfig<TSchemaConfig extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = TSchemaConfig["strict"] extends true ? TSchemaRouteKeys :
140
+ // eslint-disable-next-line perfectionist/sort-union-types -- Don't sort union types
141
+ TSchemaRouteKeys | Exclude<InitURLOrURLObject, RouteKeyMethodsURLUnion>;
142
+ type ApplySchemaConfiguration<TSchemaConfig extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = ApplyStrictConfig<TSchemaConfig, ApplyURLBasedConfig<TSchemaConfig, TSchemaRouteKeys>>;
143
+ type InferAllRouteKeys<TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, TSchemaConfig extends CallApiSchemaConfig> = ApplySchemaConfiguration<TSchemaConfig, Exclude<Extract<keyof TBaseSchemaRoutes, string>, FallBackRouteSchemaKey>>;
144
+ type InferInitURL<TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, TSchemaConfig extends CallApiSchemaConfig> = keyof TBaseSchemaRoutes extends never ? InitURLOrURLObject : InferAllRouteKeys<TBaseSchemaRoutes, TSchemaConfig>;
145
+ type GetCurrentRouteSchemaKey<TSchemaConfig extends CallApiSchemaConfig, TPath> = TPath extends URL ? string : TSchemaConfig["baseURL"] extends string ? TPath extends `${TSchemaConfig["baseURL"]}${infer TCurrentRoute}` ? TCurrentRoute extends string ? TCurrentRoute : string : TPath extends `${TSchemaConfig["prefix"]}${infer TCurrentRoute}` ? TCurrentRoute extends string ? TCurrentRoute : string : string : TPath;
146
+ type GetCurrentRouteSchema<TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey extends string, TComputedFallBackRouteSchema = TBaseSchemaRoutes[FallBackRouteSchemaKey], TComputedCurrentRouteSchema = TBaseSchemaRoutes[TCurrentRouteSchemaKey], TComputedRouteSchema extends CallApiSchema = NonNullable<Omit<TComputedFallBackRouteSchema, keyof TComputedCurrentRouteSchema> & TComputedCurrentRouteSchema>> = TComputedRouteSchema extends CallApiSchema ? Writeable<TComputedRouteSchema, "deep"> : CallApiSchema;
147
+ type JsonPrimitive = boolean | number | string | null | undefined;
148
+ type SerializableObject = Record<PropertyKey, unknown>;
149
+ type SerializableArray = Array<JsonPrimitive | SerializableObject> | ReadonlyArray<JsonPrimitive | SerializableObject>;
150
+ type Body = UnmaskType<Exclude<RequestInit["body"], undefined> | SerializableArray | SerializableObject>;
151
+ type InferBodyOption<TSchema extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema["body"], {
462
152
  /**
463
153
  * Body of the request, can be a object or any other supported body type.
464
154
  */
465
- body?: InferSchemaOutput<TSchema$1["body"], Body>;
155
+ body?: InferSchemaOutput<TSchema["body"], Body>;
466
156
  }>;
467
157
  type MethodUnion = UnmaskType<"CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE" | AnyString>;
468
- type InferMethodFromURL<TInitURL$1> = string extends TInitURL$1 ? MethodUnion : TInitURL$1 extends `@${infer TMethod extends RouteKeyMethods}/${string}` ? Uppercase<TMethod> : MethodUnion;
469
- type InferMethodOption<TSchema$1 extends CallApiSchema, TInitURL$1> = MakeSchemaOptionRequiredIfDefined<TSchema$1["method"], {
158
+ type InferMethodFromURL<TInitURL> = string extends TInitURL ? MethodUnion : TInitURL extends `@${infer TMethod extends RouteKeyMethods}/${string}` ? Uppercase<TMethod> : MethodUnion;
159
+ type InferMethodOption<TSchema extends CallApiSchema, TInitURL> = MakeSchemaOptionRequiredIfDefined<TSchema["method"], {
470
160
  /**
471
161
  * HTTP method for the request.
472
162
  * @default "GET"
473
163
  */
474
- method?: InferSchemaOutput<TSchema$1["method"], InferMethodFromURL<TInitURL$1>>;
164
+ method?: InferSchemaOutput<TSchema["method"], InferMethodFromURL<TInitURL>>;
475
165
  }>;
476
166
  type HeadersOption = UnmaskType<Record<"Authorization", CommonAuthorizationHeaders | undefined> | Record<"Content-Type", CommonContentTypes | undefined> | Record<CommonRequestHeaders, string | undefined> | Record<string, string | undefined> | Array<[string, string]>>;
477
- type InferHeadersOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["headers"], {
167
+ type InferHeadersOption<TSchema extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema["headers"], {
478
168
  /**
479
169
  * Headers to be used in the request.
480
170
  */
481
- headers?: InferSchemaOutput<TSchema$1["headers"], HeadersOption> | ((context: {
171
+ headers?: InferSchemaOutput<TSchema["headers"], HeadersOption> | ((context: {
482
172
  baseHeaders: NonNullable<HeadersOption>;
483
- }) => InferSchemaOutput<TSchema$1["headers"], HeadersOption>);
173
+ }) => InferSchemaOutput<TSchema["headers"], HeadersOption>);
484
174
  }>;
485
- type InferRequestOptions<TSchema$1 extends CallApiSchema, TInitURL$1 extends InferInitURL<BaseCallApiSchemaRoutes, CallApiSchemaConfig>> = InferBodyOption<TSchema$1> & InferHeadersOption<TSchema$1> & InferMethodOption<TSchema$1, TInitURL$1>;
486
- type InferMetaOption<TSchema$1 extends CallApiSchema, TCallApiContext$1 extends CallApiContext> = MakeSchemaOptionRequiredIfDefined<TSchema$1["meta"], {
175
+ type InferRequestOptions<TSchema extends CallApiSchema, TInitURL extends InferInitURL<BaseCallApiSchemaRoutes, CallApiSchemaConfig>> = InferBodyOption<TSchema> & InferHeadersOption<TSchema> & InferMethodOption<TSchema, TInitURL>;
176
+ type InferMetaOption<TSchema extends CallApiSchema, TCallApiContext extends CallApiContext> = MakeSchemaOptionRequiredIfDefined<TSchema["meta"], {
487
177
  /**
488
178
  * - An optional field you can fill with additional information,
489
179
  * to associate with the request, typically used for logging or tracing.
@@ -507,13 +197,13 @@ type InferMetaOption<TSchema$1 extends CallApiSchema, TCallApiContext$1 extends
507
197
  * });
508
198
  * ```
509
199
  */
510
- meta?: InferSchemaOutput<TSchema$1["meta"], TCallApiContext$1["Meta"]>;
200
+ meta?: InferSchemaOutput<TSchema["meta"], TCallApiContext["Meta"]>;
511
201
  }>;
512
- type InferQueryOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["query"], {
202
+ type InferQueryOption<TSchema extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema["query"], {
513
203
  /**
514
204
  * Parameters to be appended to the URL (i.e: /:id)
515
205
  */
516
- query?: InferSchemaOutput<TSchema$1["query"], Query>;
206
+ query?: InferSchemaOutput<TSchema["query"], Query>;
517
207
  }>;
518
208
  type EmptyString = "";
519
209
  type EmptyTuple = readonly [];
@@ -523,32 +213,32 @@ type ExtractRouteParamNames<TCurrentRoute$1, TParamNamesAccumulator extends Stri
523
213
  type ConvertParamNamesToRecord<TParamNames extends StringTuple> = Prettify<TParamNames extends (readonly [infer TFirstParamName extends string, ...infer TRemainingParamNames extends StringTuple]) ? Record<TFirstParamName, AllowedQueryParamValues> & ConvertParamNamesToRecord<TRemainingParamNames> : NonNullable<unknown>>;
524
214
  type ConvertParamNamesToTuple<TParamNames extends StringTuple> = TParamNames extends readonly [string, ...infer TRemainingParamNames extends StringTuple] ? [AllowedQueryParamValues, ...ConvertParamNamesToTuple<TRemainingParamNames>] : [];
525
215
  type InferParamsFromRoute<TCurrentRoute$1> = ExtractRouteParamNames<TCurrentRoute$1> extends StringTuple ? ExtractRouteParamNames<TCurrentRoute$1> extends EmptyTuple ? Params : ConvertParamNamesToRecord<ExtractRouteParamNames<TCurrentRoute$1>> | ConvertParamNamesToTuple<ExtractRouteParamNames<TCurrentRoute$1>> : Params;
526
- type MakeParamsOptionRequired<TParamsSchemaOption extends CallApiSchema["params"], TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey$1 extends string, TObject> = MakeSchemaOptionRequiredIfDefined<TParamsSchemaOption, Params extends InferParamsFromRoute<TCurrentRouteSchemaKey$1> ? TObject : TCurrentRouteSchemaKey$1 extends Extract<keyof TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1> ? undefined extends InferSchemaOutput<TParamsSchemaOption, null> ? TObject : Required<TObject> : TObject>;
527
- type InferParamsOption<TSchema$1 extends CallApiSchema, TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey$1 extends string> = MakeParamsOptionRequired<TSchema$1["params"], TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1, {
216
+ type MakeParamsOptionRequired<TParamsSchemaOption extends CallApiSchema["params"], TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey extends string, TObject> = MakeSchemaOptionRequiredIfDefined<TParamsSchemaOption, Params extends InferParamsFromRoute<TCurrentRouteSchemaKey> ? TObject : TCurrentRouteSchemaKey extends Extract<keyof TBaseSchemaRoutes, TCurrentRouteSchemaKey> ? undefined extends InferSchemaOutput<TParamsSchemaOption, null> ? TObject : Required<TObject> : TObject>;
217
+ type InferParamsOption<TSchema extends CallApiSchema, TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey extends string> = MakeParamsOptionRequired<TSchema["params"], TBaseSchemaRoutes, TCurrentRouteSchemaKey, {
528
218
  /**
529
219
  * Parameters to be appended to the URL (i.e: /:id)
530
220
  */
531
- params?: InferSchemaOutput<TSchema$1["params"], InferParamsFromRoute<TCurrentRouteSchemaKey$1>>;
221
+ params?: InferSchemaOutput<TSchema["params"], InferParamsFromRoute<TCurrentRouteSchemaKey>>;
532
222
  }>;
533
- type InferExtraOptions<TSchema$1 extends CallApiSchema, TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey$1 extends string, TCallApiContext$1 extends CallApiContext> = InferMetaOption<TSchema$1, TCallApiContext$1> & InferParamsOption<TSchema$1, TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1> & InferQueryOption<TSchema$1>;
534
- type InferPluginOptions<TPluginArray$1 extends CallApiPlugin[]> = UnionToIntersection<TPluginArray$1 extends Array<infer TPlugin> ? TPlugin extends CallApiPlugin ? TPlugin["defineExtraOptions"] extends AnyFunction<infer TReturnedSchema> ? InferSchemaOutput<TReturnedSchema> : never : never : never>;
535
- type ResultModeOption<TErrorData$1, TResultMode$1 extends ResultModeType> = TErrorData$1 extends false ? {
223
+ type InferExtraOptions<TSchema extends CallApiSchema, TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey extends string, TCallApiContext extends CallApiContext> = InferMetaOption<TSchema, TCallApiContext> & InferParamsOption<TSchema, TBaseSchemaRoutes, TCurrentRouteSchemaKey> & InferQueryOption<TSchema>;
224
+ type InferPluginExtraOptions<TPluginArray extends CallApiPlugin[]> = UnionToIntersection<TPluginArray extends Array<infer TPlugin> ? TPlugin extends CallApiPlugin ? TPlugin["defineExtraOptions"] extends AnyFunction<infer TReturnedSchema> ? InferSchemaOutput<TReturnedSchema> : never : never : never>;
225
+ type ResultModeOption<TErrorData, TResultMode extends ResultModeType> = TErrorData extends false ? {
536
226
  resultMode: "onlyData";
537
- } : TErrorData$1 extends false | undefined ? {
227
+ } : TErrorData extends false | undefined ? {
538
228
  resultMode?: "onlyData";
539
229
  } : {
540
- resultMode?: TResultMode$1;
230
+ resultMode?: TResultMode;
541
231
  };
542
232
  type ThrowOnErrorUnion = boolean;
543
- type ThrowOnErrorType<TErrorData$1, TThrowOnError$1 extends ThrowOnErrorUnion> = TThrowOnError$1 | ((context: ErrorContext<{
544
- ErrorData: TErrorData$1;
545
- }>) => TThrowOnError$1);
546
- type ThrowOnErrorOption<TErrorData$1, TThrowOnError$1 extends ThrowOnErrorUnion> = TErrorData$1 extends false ? {
233
+ type ThrowOnErrorType<TErrorData, TThrowOnError extends ThrowOnErrorUnion> = TThrowOnError | ((context: ErrorContext<{
234
+ ErrorData: TErrorData;
235
+ }>) => TThrowOnError);
236
+ type ThrowOnErrorOption<TErrorData, TThrowOnError extends ThrowOnErrorUnion> = TErrorData extends false ? {
547
237
  throwOnError: true;
548
- } : TErrorData$1 extends false | undefined ? {
238
+ } : TErrorData extends false | undefined ? {
549
239
  throwOnError?: true;
550
240
  } : {
551
- throwOnError?: ThrowOnErrorType<TErrorData$1, TThrowOnError$1>;
241
+ throwOnError?: ThrowOnErrorType<TErrorData, TThrowOnError>;
552
242
  };
553
243
  //#endregion
554
244
  //#region src/types/standard-schema.d.ts
@@ -556,11 +246,11 @@ type ThrowOnErrorOption<TErrorData$1, TThrowOnError$1 extends ThrowOnErrorUnion>
556
246
  * The Standard Schema interface.
557
247
  * @see https://github.com/standard-schema/standard-schema
558
248
  */
559
- interface StandardSchemaV1<Input$1 = unknown, Output$1 = Input$1> {
249
+ interface StandardSchemaV1<Input = unknown, Output = Input> {
560
250
  /**
561
251
  * The Standard Schema properties.
562
252
  */
563
- readonly "~standard": StandardSchemaV1.Props<Input$1, Output$1>;
253
+ readonly "~standard": StandardSchemaV1.Props<Input, Output>;
564
254
  }
565
255
  declare namespace StandardSchemaV1 {
566
256
  /**
@@ -651,1232 +341,1452 @@ declare namespace StandardSchemaV1 {
651
341
  type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
652
342
  }
653
343
  //#endregion
654
- //#region src/utils/external/error.d.ts
655
- type HTTPErrorDetails<TErrorData$1> = Pick<CallApiExtraOptions, "defaultHTTPErrorMessage"> & {
656
- errorData: TErrorData$1;
657
- response: Response;
658
- };
659
- declare class HTTPError<TErrorData$1 = Record<string, unknown>> extends Error {
660
- errorData: HTTPErrorDetails<TErrorData$1>["errorData"];
661
- readonly httpErrorSymbol: symbol;
662
- name: "HTTPError";
663
- response: HTTPErrorDetails<TErrorData$1>["response"];
664
- constructor(errorDetails: HTTPErrorDetails<TErrorData$1>, errorOptions?: ErrorOptions);
344
+ //#region src/validation.d.ts
345
+ type ResultVariant = "infer-input" | "infer-output";
346
+ type InferSchemaResult<TSchema, TFallbackResult, TResultVariant extends ResultVariant> = undefined extends TSchema ? TFallbackResult : TSchema extends StandardSchemaV1 ? TResultVariant extends "infer-input" ? StandardSchemaV1.InferInput<TSchema> : StandardSchemaV1.InferOutput<TSchema> : TSchema extends AnyFunction<infer TResult> ? Awaited<TResult> : TFallbackResult;
347
+ type InferSchemaOutput<TSchema, TFallbackResult = unknown> = InferSchemaResult<TSchema, TFallbackResult, "infer-output">;
348
+ type InferSchemaInput<TSchema, TFallbackResult = unknown> = InferSchemaResult<TSchema, TFallbackResult, "infer-input">;
349
+ interface CallApiSchemaConfig {
665
350
  /**
666
- * @description Checks if the given error is an instance of HTTPError
667
- * @param error - The error to check
668
- * @returns true if the error is an instance of HTTPError, false otherwise
351
+ * The base url of the schema. By default it's the baseURL of the callApi instance.
669
352
  */
670
- static isError<TErrorData>(error: unknown): error is HTTPError<TErrorData$1>;
671
- }
672
- type SafeExtract<TUnion, TKey extends TUnion> = Extract<TUnion, TKey>;
673
- type ValidationErrorDetails = {
353
+ baseURL?: string;
674
354
  /**
675
- * The cause of the validation error.
676
- *
677
- * 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.
355
+ * Disables runtime validation for the schema.
678
356
  */
679
- issueCause: "unknown" | `schemaConfig-(${SafeExtract<keyof CallApiSchemaConfig, "strict">})` | keyof CallApiSchema;
357
+ disableRuntimeValidation?: boolean;
680
358
  /**
681
- * The issues that caused the validation error.
359
+ * If `true`, the original input value will be used instead of the transformed/validated output.
360
+ *
361
+ * This is useful when you want to validate the input but don't want any transformations
362
+ * applied by the validation schema (e.g., type coercion, default values, etc).
682
363
  */
683
- issues: readonly StandardSchemaV1.Issue[];
364
+ disableValidationOutputApplication?: boolean;
684
365
  /**
685
- * The response from server, if any.
366
+ * Optional url prefix that will be substituted for the `baseURL` of the schemaConfig at runtime.
367
+ *
368
+ * This allows you to reuse the same schema against different base URLs (for example,
369
+ * swapping between `/api/v1` and `/api/v2`) without redefining the entire schema.
686
370
  */
687
- response: Response | null;
688
- };
689
- declare class ValidationError extends Error {
690
- errorData: ValidationErrorDetails["issues"];
691
- issueCause: ValidationErrorDetails["issueCause"];
692
- name: "ValidationError";
693
- response: ValidationErrorDetails["response"];
694
- readonly validationErrorSymbol: symbol;
695
- constructor(details: ValidationErrorDetails, errorOptions?: ErrorOptions);
371
+ prefix?: string;
696
372
  /**
697
- * @description Checks if the given error is an instance of ValidationError
698
- * @param error - The error to check
699
- * @returns true if the error is an instance of ValidationError, false otherwise
373
+ * Controls the strictness of API route validation.
374
+ *
375
+ * When true:
376
+ * - Only routes explicitly defined in the schema will be considered valid to typescript and the runtime.
377
+ * - Attempting to call routes not defined in the schema will result in both type errors and runtime validation errors.
378
+ * - Useful for ensuring API calls conform exactly to your schema definition
379
+ *
380
+ * When false or undefined (default):
381
+ * - All routes will be allowed, whether they are defined in the schema or not
700
382
  */
701
- static isError(error: unknown): error is ValidationError;
383
+ strict?: boolean;
702
384
  }
703
- //#endregion
704
- //#region src/result.d.ts
705
- type Parser<TData$1> = (responseString: string) => Awaitable<TData$1>;
706
- declare const getResponseType: <TResponse>(response: Response, parser: Parser<TResponse>) => {
707
- arrayBuffer: () => Promise<ArrayBuffer>;
708
- blob: () => Promise<Blob>;
709
- formData: () => Promise<FormData>;
710
- json: () => Promise<TResponse>;
711
- stream: () => ReadableStream<Uint8Array<ArrayBuffer>> | null;
712
- text: () => Promise<string>;
713
- };
714
- type InitResponseTypeMap<TResponse$1 = unknown> = ReturnType<typeof getResponseType<TResponse$1>>;
715
- type ResponseTypeUnion = keyof InitResponseTypeMap;
716
- type ResponseTypePlaceholder = null;
717
- type ResponseTypeType = ResponseTypePlaceholder | ResponseTypeUnion;
718
- type ResponseTypeMap<TResponse$1> = { [Key in keyof InitResponseTypeMap<TResponse$1>]: Awaited<ReturnType<InitResponseTypeMap<TResponse$1>[Key]>> };
719
- type GetResponseType<TResponse$1, TResponseType$1 extends ResponseTypeType, TComputedResponseTypeMap extends ResponseTypeMap<TResponse$1> = ResponseTypeMap<TResponse$1>> = null extends TResponseType$1 ? TComputedResponseTypeMap["json"] : TResponseType$1 extends NonNullable<ResponseTypeType> ? TComputedResponseTypeMap[TResponseType$1] : never;
720
- type CallApiResultSuccessVariant<TData$1> = {
721
- data: NoInfer<TData$1>;
722
- error: null;
723
- response: Response;
724
- };
725
- type PossibleJavaScriptError = UnmaskType<{
726
- errorData: false;
727
- message: string;
728
- name: "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | AnyString;
729
- originalError: DOMException | Error | SyntaxError | TypeError;
730
- }>;
731
- type PossibleHTTPError<TErrorData$1> = UnmaskType<{
732
- errorData: NoInfer<TErrorData$1>;
733
- message: string;
734
- name: "HTTPError";
735
- originalError: HTTPError;
736
- }>;
737
- type PossibleValidationError = UnmaskType<{
738
- errorData: ValidationError["errorData"];
739
- issueCause: ValidationError["issueCause"];
740
- message: string;
741
- name: "ValidationError";
742
- originalError: ValidationError;
743
- }>;
744
- type PossibleJavaScriptOrValidationError = UnmaskType<PossibleJavaScriptError | PossibleValidationError>;
745
- type CallApiResultErrorVariant<TErrorData$1> = {
746
- data: null;
747
- error: PossibleHTTPError<TErrorData$1>;
748
- response: Response;
749
- } | {
750
- data: null;
751
- error: PossibleJavaScriptOrValidationError;
752
- response: Response | null;
753
- };
754
- type CallApiSuccessOrErrorVariant<TData$1, TError> = CallApiResultErrorVariant<TError> | CallApiResultSuccessVariant<TData$1>;
755
- type ResultModeMapWithoutException<TData$1, TErrorData$1, TResponseType$1 extends ResponseTypeType, TComputedData = GetResponseType<TData$1, TResponseType$1>, TComputedErrorData = GetResponseType<TErrorData$1, TResponseType$1>, TComputedResult$1 extends CallApiSuccessOrErrorVariant<TComputedData, TComputedErrorData> = CallApiSuccessOrErrorVariant<TComputedData, TComputedErrorData>> = UnmaskType<{
756
- all: TComputedResult$1;
757
- onlyData: TComputedResult$1["data"];
758
- onlyResponse: TComputedResult$1["response"];
759
- withoutResponse: DistributiveOmit<TComputedResult$1, "response">;
760
- }>;
761
- type ResultModeMapWithException<TData$1, TResponseType$1 extends ResponseTypeType, TComputedData = GetResponseType<TData$1, TResponseType$1>, TComputedResult$1 extends CallApiResultSuccessVariant<TComputedData> = CallApiResultSuccessVariant<TComputedData>> = {
762
- all: TComputedResult$1;
763
- onlyData: TComputedResult$1["data"];
764
- onlyResponse: TComputedResult$1["response"];
765
- withoutResponse: DistributiveOmit<TComputedResult$1, "response">;
766
- };
767
- type ResultModeMap<TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TResponseType$1 extends ResponseTypeType = ResponseTypeType, TThrowOnError$1 extends ThrowOnErrorUnion = DefaultThrowOnError> = TThrowOnError$1 extends true ? ResultModeMapWithException<TData$1, TResponseType$1> : ResultModeMapWithoutException<TData$1, TErrorData$1, TResponseType$1>;
768
- type ResultModePlaceholder = null;
769
- type ResultModeUnion = keyof ResultModeMap;
770
- type ResultModeType = ResultModePlaceholder | ResultModeUnion;
771
- type GetCallApiResult<TData$1, TErrorData$1, TResultMode$1 extends ResultModeType, TThrowOnError$1 extends ThrowOnErrorUnion, TResponseType$1 extends ResponseTypeType, TComputedResultModeMapWithException extends ResultModeMapWithException<TData$1, TResponseType$1> = ResultModeMapWithException<TData$1, TResponseType$1>, TComputedResultModeMap extends ResultModeMap<TData$1, TErrorData$1, TResponseType$1, TThrowOnError$1> = ResultModeMap<TData$1, TErrorData$1, TResponseType$1, TThrowOnError$1>> = TErrorData$1 extends false ? TComputedResultModeMapWithException["onlyData"] : TErrorData$1 extends false | undefined ? TComputedResultModeMapWithException["onlyData"] : ResultModePlaceholder extends TResultMode$1 ? TComputedResultModeMap["all"] : TResultMode$1 extends ResultModeUnion ? TComputedResultModeMap[TResultMode$1] : never;
772
- //#endregion
773
- //#region src/retry.d.ts
774
- declare const defaultRetryStatusCodesLookup: () => Readonly<{
775
- 408: "Request Timeout";
776
- 409: "Conflict";
777
- 425: "Too Early";
778
- 429: "Too Many Requests";
779
- 500: "Internal Server Error";
780
- 502: "Bad Gateway";
781
- 503: "Service Unavailable";
782
- 504: "Gateway Timeout";
783
- }>;
784
- type RetryStatusCodes = UnmaskType<AnyNumber | keyof ReturnType<typeof defaultRetryStatusCodesLookup>>;
785
- type RetryCondition<TErrorData$1> = (context: ErrorContext<{
786
- ErrorData: TErrorData$1;
787
- }>) => Awaitable<boolean>;
788
- type RetryOptionKeys<TErrorData$1> = Exclude<keyof RetryOptions<TErrorData$1>, "~retryAttemptCount" | "retry">;
789
- type InnerRetryOptions<TErrorData$1> = { [Key in RetryOptionKeys<TErrorData$1> as RemovePrefix<"retry", Key>]?: RetryOptions<TErrorData$1>[Key] };
790
- interface RetryOptions<TErrorData$1> {
385
+ interface CallApiSchema {
791
386
  /**
792
- * Keeps track of the number of times the request has already been retried
793
- * @internal
794
- * @deprecated **NOTE**: This property is used internally to track retries. Please abstain from modifying it.
387
+ * The schema to use for validating the request body.
795
388
  */
796
- readonly ["~retryAttemptCount"]?: number;
389
+ body?: StandardSchemaV1<Body | undefined> | ((body: Body) => Awaitable<Body | undefined>);
797
390
  /**
798
- * All retry options in a single object instead of separate properties
391
+ * The schema to use for validating the response data.
799
392
  */
800
- retry?: InnerRetryOptions<TErrorData$1>;
393
+ data?: StandardSchemaV1 | ((data: unknown) => unknown);
801
394
  /**
802
- * Number of allowed retry attempts on HTTP errors
803
- * @default 0
395
+ * The schema to use for validating the response error data.
804
396
  */
805
- retryAttempts?: number;
397
+ errorData?: StandardSchemaV1 | ((errorData: unknown) => unknown);
806
398
  /**
807
- * Callback whose return value determines if a request should be retried or not
399
+ * The schema to use for validating the request headers.
808
400
  */
809
- retryCondition?: RetryCondition<TErrorData$1>;
401
+ headers?: StandardSchemaV1<HeadersOption | undefined> | ((headers: HeadersOption) => Awaitable<HeadersOption | undefined>);
810
402
  /**
811
- * Delay between retries in milliseconds
812
- * @default 1000
403
+ * The schema to use for validating the meta option.
813
404
  */
814
- retryDelay?: number | ((currentAttemptCount: number) => number);
405
+ meta?: StandardSchemaV1<GlobalMeta | undefined> | ((meta: GlobalMeta) => Awaitable<GlobalMeta | undefined>);
815
406
  /**
816
- * Maximum delay in milliseconds. Only applies to exponential strategy
817
- * @default 10000
407
+ * The schema to use for validating the request method.
818
408
  */
819
- retryMaxDelay?: number;
409
+ method?: StandardSchemaV1<MethodUnion | undefined> | ((method: MethodUnion) => Awaitable<MethodUnion | undefined>);
820
410
  /**
821
- * HTTP methods that are allowed to retry
822
- * @default ["GET", "POST"]
411
+ * The schema to use for validating the request url parameters.
823
412
  */
824
- retryMethods?: MethodUnion[];
825
- /**
826
- * HTTP status codes that trigger a retry
827
- */
828
- retryStatusCodes?: RetryStatusCodes[];
413
+ params?: StandardSchemaV1<Params | undefined> | ((params: Params) => Awaitable<Params | undefined>);
829
414
  /**
830
- * Strategy to use when retrying
831
- * @default "linear"
415
+ * The schema to use for validating the request url queries.
832
416
  */
833
- retryStrategy?: "exponential" | "linear";
417
+ query?: StandardSchemaV1<Query | undefined> | ((query: Query) => Awaitable<Query | undefined>);
834
418
  }
835
- //#endregion
836
- //#region src/types/common.d.ts
837
- interface Register {}
838
- type GlobalMeta = Register extends {
839
- meta?: infer TMeta extends DefaultMetaObject;
840
- } ? TMeta : DefaultMetaObject;
841
- type CallApiContext = {
842
- Data?: DefaultDataType;
843
- ErrorData?: DefaultDataType;
844
- InferredPluginOptions?: unknown;
845
- Meta?: DefaultMetaObject;
846
- ResultMode?: ResultModeType;
847
- };
848
- type GetMergedCallApiContext<TFullCallApiContext extends CallApiContext, TOverrideCallApiContext extends CallApiContext> = Omit<TFullCallApiContext, keyof TOverrideCallApiContext> & TOverrideCallApiContext;
849
- type FetchSpecificKeysUnion = Exclude<(typeof fetchSpecificKeys)[number], "body" | "headers" | "method">;
850
- type ModifiedRequestInit = RequestInit & {
851
- duplex?: "half";
852
- };
853
- type CallApiRequestOptions = Prettify<{
854
- /**
855
- * Body of the request, can be a object or any other supported body type.
856
- */
857
- body?: Body;
858
- /**
859
- * Headers to be used in the request.
860
- */
861
- headers?: HeadersOption;
862
- /**
863
- * HTTP method for the request.
864
- * @default "GET"
865
- */
866
- method?: MethodUnion;
867
- } & Pick<ModifiedRequestInit, FetchSpecificKeysUnion>>;
868
- type CallApiRequestOptionsForHooks = Omit<CallApiRequestOptions, "headers"> & {
869
- headers: Record<string, string | undefined>;
419
+ declare const routeKeyMethods: readonly ["delete", "get", "patch", "post", "put"];
420
+ type RouteKeyMethods = (typeof routeKeyMethods)[number];
421
+ type RouteKeyMethodsURLUnion = `@${RouteKeyMethods}/`;
422
+ type BaseSchemaRouteKeyPrefixes = FallBackRouteSchemaKey | RouteKeyMethodsURLUnion;
423
+ type BaseCallApiSchemaRoutes = Partial<Record<AnyString | BaseSchemaRouteKeyPrefixes, CallApiSchema>>;
424
+ type BaseCallApiSchemaAndConfig = {
425
+ config?: CallApiSchemaConfig;
426
+ routes: BaseCallApiSchemaRoutes;
870
427
  };
871
- type SharedExtraOptions<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext, TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TResultMode$1 extends ResultModeType = ResultModeType, TThrowOnError$1 extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType$1 extends ResponseTypeType = ResponseTypeType, TPluginArray$1 extends CallApiPlugin[] = DefaultPluginArray, TComputedMergedPluginOptions = Partial<InferPluginOptions<TPluginArray$1> & TCallApiContext$1["InferredPluginOptions"]>> = DedupeOptions & HookConfigOptions & HooksOrHooksArray<GetMergedCallApiContext<TCallApiContext$1, {
872
- InferredPluginOptions: TComputedMergedPluginOptions;
873
- }>> & Middlewares & ResultModeOption<TErrorData$1, TResultMode$1> & RetryOptions<TErrorData$1> & TComputedMergedPluginOptions & ThrowOnErrorOption<TErrorData$1, TThrowOnError$1> & URLOptions & {
428
+ //#endregion
429
+ //#region src/url.d.ts
430
+ type AllowedQueryParamValues = UnmaskType<boolean | number | string>;
431
+ type RecordStyleParams = UnmaskType<Record<string, AllowedQueryParamValues>>;
432
+ type TupleStyleParams = UnmaskType<AllowedQueryParamValues[]>;
433
+ type Params = UnmaskType<RecordStyleParams | TupleStyleParams>;
434
+ type Query = UnmaskType<Record<string, AllowedQueryParamValues>>;
435
+ type InitURLOrURLObject = AnyString | RouteKeyMethodsURLUnion | URL;
436
+ interface URLOptions {
874
437
  /**
875
- * Automatically add an Authorization header value.
438
+ * Base URL for all API requests. Will only be prepended to relative URLs.
876
439
  *
877
- * Supports multiple authentication patterns:
878
- * - String: Direct authorization header value
879
- * - Auth object: Structured authentication configuration
440
+ * Absolute URLs (starting with http/https) will not be prepended by the baseURL.
441
+ *
442
+ * @example
443
+ * ```ts
444
+ * // Set base URL for all requests
445
+ * baseURL: "https://api.example.com/v1"
880
446
  *
447
+ * // Then use relative URLs in requests
448
+ * callApi("/users") // → https://api.example.com/v1/users
449
+ * callApi("/posts/123") // → https://api.example.com/v1/posts/123
450
+ *
451
+ * // Environment-specific base URLs
452
+ * baseURL: process.env.NODE_ENV === "production"
453
+ * ? "https://api.example.com"
454
+ * : "http://localhost:3000/api"
881
455
  * ```
882
456
  */
883
- auth?: Auth;
457
+ baseURL?: string;
884
458
  /**
885
- * Custom function to serialize request body objects into strings.
459
+ * Resolved request URL after processing baseURL, parameters, and query strings (readonly)
886
460
  *
887
- * Useful for custom serialization formats or when the default JSON
888
- * serialization doesn't meet your needs.
461
+ * This is the final URL that will be used for the HTTP request, computed from
462
+ * baseURL, initURL, params, and query parameters.
889
463
  *
890
- * @example
891
- * ```ts
892
- * // Custom form data serialization
893
- * bodySerializer: (data) => {
894
- * const formData = new URLSearchParams();
895
- * Object.entries(data).forEach(([key, value]) => {
896
- * formData.append(key, String(value));
897
- * });
898
- * return formData.toString();
899
- * }
464
+ */
465
+ readonly fullURL?: string;
466
+ /**
467
+ * The original URL string passed to the callApi instance (readonly)
900
468
  *
901
- * // XML serialization
902
- * bodySerializer: (data) => {
903
- * return `<request>${Object.entries(data)
904
- * .map(([key, value]) => `<${key}>${value}</${key}>`)
905
- * .join('')}</request>`;
906
- * }
469
+ * This preserves the original URL as provided, including any method modifiers like "@get/" or "@post/".
907
470
  *
908
- * // Custom JSON with specific formatting
909
- * bodySerializer: (data) => JSON.stringify(data, null, 2)
910
- * ```
911
471
  */
912
- bodySerializer?: (bodyData: Record<string, unknown>) => string;
472
+ readonly initURL?: string;
913
473
  /**
914
- * Whether to clone the response so it can be read multiple times.
474
+ * The URL string after normalization, with method modifiers removed(readonly)
915
475
  *
916
- * By default, response streams can only be consumed once. Enable this when you need
917
- * to read the response in multiple places (e.g., in hooks and main code).
476
+ * Method modifiers like "@get/", "@post/" are stripped to create a clean URL
477
+ * for parameter substitution and final URL construction.
918
478
  *
919
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/clone
920
- * @default false
921
479
  */
922
- cloneResponse?: boolean;
480
+ readonly initURLNormalized?: string;
923
481
  /**
924
- * Custom fetch implementation to replace the default fetch function.
482
+ * Parameters to be substituted into URL path segments.
925
483
  *
926
- * Useful for testing, adding custom behavior, or using alternative HTTP clients
927
- * that implement the fetch API interface.
484
+ * Supports both object-style (named parameters) and array-style (positional parameters)
485
+ * for flexible URL parameter substitution.
928
486
  *
929
487
  * @example
930
- * ```ts
931
- * // Use node-fetch in Node.js environments
932
- * import fetch from 'node-fetch';
933
- *
934
- * // Mock fetch for testing
935
- * customFetchImpl: async (url, init) => {
936
- * return new Response(JSON.stringify({ mocked: true }), {
937
- * status: 200,
938
- * headers: { 'Content-Type': 'application/json' }
939
- * });
940
- * }
488
+ * ```typescript
489
+ * // Object-style parameters (recommended)
490
+ * const namedParams: URLOptions = {
491
+ * initURL: "/users/:userId/posts/:postId",
492
+ * params: { userId: "123", postId: "456" }
493
+ * };
494
+ * // Results in: /users/123/posts/456
941
495
  *
942
- * // Add custom logging to all requests
943
- * customFetchImpl: async (url, init) => {
944
- * console.log(`Fetching: ${url}`);
945
- * const response = await fetch(url, init);
946
- * console.log(`Response: ${response.status}`);
947
- * return response;
948
- * }
496
+ * // Array-style parameters (positional)
497
+ * const positionalParams: URLOptions = {
498
+ * initURL: "/users/:userId/posts/:postId",
499
+ * params: ["123", "456"] // Maps in order: userId=123, postId=456
500
+ * };
501
+ * // Results in: /users/123/posts/456
949
502
  *
950
- * // Use with custom HTTP client
951
- * customFetchImpl: async (url, init) => {
952
- * // Convert to your preferred HTTP client format
953
- * return await customHttpClient.request({
954
- * url: url.toString(),
955
- * method: init?.method || 'GET',
956
- * headers: init?.headers,
957
- * body: init?.body
958
- * });
959
- * }
503
+ * // Single parameter
504
+ * const singleParam: URLOptions = {
505
+ * initURL: "/users/:id",
506
+ * params: { id: "user-123" }
507
+ * };
508
+ * // Results in: /users/user-123
960
509
  * ```
961
510
  */
962
- customFetchImpl?: FetchImpl;
511
+ params?: Params;
963
512
  /**
964
- * Default HTTP error message when server doesn't provide one.
965
- *
966
- * Can be a static string or a function that receives error context
967
- * to generate dynamic error messages based on the response.
513
+ * Query parameters to append to the URL as search parameters.
968
514
  *
969
- * @default "Failed to fetch data from server!"
515
+ * These will be serialized into the URL query string using standard
516
+ * URL encoding practices.
970
517
  *
971
518
  * @example
972
- * ```ts
973
- * // Static error message
974
- * defaultHTTPErrorMessage: "API request failed. Please try again."
975
- *
976
- * // Dynamic error message based on status code
977
- * defaultHTTPErrorMessage: ({ response }) => {
978
- * switch (response.status) {
979
- * case 401: return "Authentication required. Please log in.";
980
- * case 403: return "Access denied. Insufficient permissions.";
981
- * case 404: return "Resource not found.";
982
- * case 429: return "Too many requests. Please wait and try again.";
983
- * case 500: return "Server error. Please contact support.";
984
- * default: return `Request failed with status ${response.status}`;
519
+ * ```typescript
520
+ * // Basic query parameters
521
+ * const queryOptions: URLOptions = {
522
+ * initURL: "/users",
523
+ * query: {
524
+ * page: 1,
525
+ * limit: 10,
526
+ * search: "john doe",
527
+ * active: true
985
528
  * }
986
- * }
529
+ * };
530
+ * // Results in: /users?page=1&limit=10&search=john%20doe&active=true
987
531
  *
988
- * // Include error data in message
989
- * defaultHTTPErrorMessage: ({ errorData, response }) => {
990
- * const userMessage = errorData?.message || "Unknown error occurred";
991
- * return `${userMessage} (Status: ${response.status})`;
992
- * }
532
+ * // Filtering and sorting
533
+ * const filterOptions: URLOptions = {
534
+ * initURL: "/products",
535
+ * query: {
536
+ * category: "electronics",
537
+ * minPrice: 100,
538
+ * maxPrice: 500,
539
+ * sortBy: "price",
540
+ * order: "asc"
541
+ * }
542
+ * };
543
+ * // Results in: /products?category=electronics&minPrice=100&maxPrice=500&sortBy=price&order=asc
993
544
  * ```
994
545
  */
995
- defaultHTTPErrorMessage?: string | ((context: Pick<HTTPError<TErrorData$1>, "errorData" | "response">) => string);
546
+ query?: Query;
547
+ }
548
+ //#endregion
549
+ //#region src/plugins.d.ts
550
+ type PluginSetupContext<TCallApiContext extends CallApiContext = DefaultCallApiContext> = RequestContext<TCallApiContext> & {
551
+ initURL: string;
552
+ };
553
+ type PluginInitResult<TCallApiContext extends CallApiContext = DefaultCallApiContext> = Partial<Omit<PluginSetupContext<TCallApiContext>, "initURL" | "request"> & {
554
+ initURL: InitURLOrURLObject;
555
+ request: CallApiRequestOptions;
556
+ }>;
557
+ type PluginHooks<TCallApiContext extends CallApiContext = DefaultCallApiContext> = HooksOrHooksArray<OverrideCallApiContext<TCallApiContext, {
558
+ Data: DefaultDataType extends TCallApiContext["Data"] ? never : TCallApiContext["Data"];
559
+ ErrorData: DefaultDataType extends TCallApiContext["ErrorData"] ? never : TCallApiContext["ErrorData"];
560
+ }>>;
561
+ interface CallApiPlugin<TCallApiContext extends CallApiContext = DefaultCallApiContext> {
996
562
  /**
997
- * Forces calculation of total byte size from request/response body streams.
998
- *
999
- * Useful when the Content-Length header is missing or incorrect, and you need
1000
- * accurate size information for progress tracking or bandwidth monitoring.
1001
- *
1002
- * @default false
1003
- *
563
+ * Defines additional options that can be passed to callApi
1004
564
  */
1005
- forcefullyCalculateStreamSize?: boolean | {
1006
- request?: boolean;
1007
- response?: boolean;
1008
- };
565
+ defineExtraOptions?: (...params: never[]) => unknown;
1009
566
  /**
1010
- * Optional metadata field for associating additional information with requests.
1011
- *
1012
- * Useful for logging, tracing, or handling specific cases in shared interceptors.
1013
- * The meta object is passed through to all hooks and can be accessed in error handlers.
1014
- *
1015
- * @example
1016
- * ```ts
1017
- * const callMainApi = callApi.create({
1018
- * baseURL: "https://main-api.com",
1019
- * onResponseError: ({ response, options }) => {
1020
- * if (options.meta?.userId) {
1021
- * console.error(`User ${options.meta.userId} made an error`);
1022
- * }
1023
- * },
1024
- * });
1025
- *
1026
- * const response = await callMainApi({
1027
- * url: "https://example.com/api/data",
1028
- * meta: { userId: "123" },
1029
- * });
567
+ * A description for the plugin
568
+ */
569
+ description?: string;
570
+ /**
571
+ * Hooks for the plugin
572
+ */
573
+ hooks?: PluginHooks<TCallApiContext> | ((context: PluginSetupContext<TCallApiContext>) => Awaitable<PluginHooks<TCallApiContext>>);
574
+ /**
575
+ * A unique id for the plugin
576
+ */
577
+ id: string;
578
+ /**
579
+ * Middlewares that for the plugin
580
+ */
581
+ middlewares?: Middlewares<TCallApiContext> | ((context: PluginSetupContext<TCallApiContext>) => Awaitable<Middlewares<TCallApiContext>>);
582
+ /**
583
+ * A name for the plugin
584
+ */
585
+ name: string;
586
+ /**
587
+ * Base schema for the client.
588
+ */
589
+ schema?: BaseCallApiSchemaAndConfig;
590
+ /**
591
+ * A function that will be called when the plugin is initialized. This will be called before the any of the other internal functions.
592
+ */
593
+ setup?: (context: PluginSetupContext<TCallApiContext>) => Awaitable<PluginInitResult<TCallApiContext>> | Awaitable<void>;
594
+ /**
595
+ * A version for the plugin
596
+ */
597
+ version?: string;
598
+ }
599
+ //#endregion
600
+ //#region src/types/default-types.d.ts
601
+ type DefaultDataType = unknown;
602
+ type DefaultPluginArray = CallApiPlugin[];
603
+ type DefaultThrowOnError = boolean;
604
+ type DefaultMetaObject = Record<string, unknown>;
605
+ type DefaultCallApiContext = Omit<Required<CallApiContext>, "Meta"> & {
606
+ Meta: GlobalMeta;
607
+ };
608
+ //#endregion
609
+ //#region src/hooks.d.ts
610
+ interface Hooks<TCallApiContext extends CallApiContext = DefaultCallApiContext> {
611
+ /**
612
+ * Hook called when any error occurs within the request/response lifecycle.
1030
613
  *
1031
- * // Use case: Request tracking
1032
- * const result = await callMainApi({
1033
- * url: "https://example.com/api/data",
1034
- * meta: {
1035
- * requestId: generateId(),
1036
- * source: "user-dashboard",
1037
- * priority: "high"
1038
- * }
1039
- * });
614
+ * This is a unified error handler that catches both request errors (network failures,
615
+ * timeouts, etc.) and response errors (HTTP error status codes). It's essentially
616
+ * a combination of `onRequestError` and `onResponseError` hooks.
1040
617
  *
1041
- * // Use case: Feature flags
1042
- * const client = callApi.create({
1043
- * baseURL: "https://api.example.com",
1044
- * meta: {
1045
- * features: ["newUI", "betaFeature"],
1046
- * experiment: "variantA"
1047
- * }
1048
- * });
1049
- * ```
618
+ * @param context - Error context containing error details, request info, and response (if available)
619
+ * @returns Promise or void - Hook can be async or sync
1050
620
  */
1051
- meta?: TCallApiContext$1["Meta"] extends DefaultMetaObject ? TCallApiContext$1["Meta"] : DefaultCallApiContext["Meta"];
621
+ onError?: (context: ErrorContext<TCallApiContext>) => Awaitable<unknown>;
1052
622
  /**
1053
- * Custom function to parse response strings into actual value instead of the default response.json().
623
+ * Hook called before the HTTP request is sent and before any internal processing of the request object begins.
1054
624
  *
1055
- * Useful when you need custom parsing logic for specific response formats.
625
+ * This is the ideal place to modify request headers, add authentication,
626
+ * implement request logging, or perform any setup before the network call.
1056
627
  *
1057
- * @example
1058
- * ```ts
1059
- * responseParser: (responseString) => {
1060
- * return JSON.parse(responseString);
1061
- * }
628
+ * @param context - Request context with mutable request object and configuration
629
+ * @returns Promise or void - Hook can be async or sync
1062
630
  *
1063
- * // Parse XML responses
1064
- * responseParser: (responseString) => {
1065
- * const parser = new DOMParser();
1066
- * const doc = parser.parseFromString(responseString, "text/xml");
1067
- * return xmlToObject(doc);
1068
- * }
631
+ */
632
+ onRequest?: (context: RequestContext<TCallApiContext>) => Awaitable<unknown>;
633
+ /**
634
+ * Hook called when an error occurs during the fetch request itself.
1069
635
  *
1070
- * // Parse CSV responses
1071
- * responseParser: (responseString) => {
1072
- * const lines = responseString.split('\n');
1073
- * const headers = lines[0].split(',');
1074
- * const data = lines.slice(1).map(line => {
1075
- * const values = line.split(',');
1076
- * return headers.reduce((obj, header, index) => {
1077
- * obj[header] = values[index];
1078
- * return obj;
1079
- * }, {});
1080
- * });
1081
- * return data;
1082
- * }
636
+ * This handles network-level errors like connection failures, timeouts,
637
+ * DNS resolution errors, or other issues that prevent getting an HTTP response.
638
+ * Note that HTTP error status codes (4xx, 5xx) are handled by `onResponseError`.
1083
639
  *
1084
- * ```
640
+ * @param context - Request error context with error details and null response
641
+ * @returns Promise or void - Hook can be async or sync
1085
642
  */
1086
- responseParser?: (responseString: string) => Awaitable<TData$1>;
643
+ onRequestError?: (context: RequestErrorContext<TCallApiContext>) => Awaitable<unknown>;
1087
644
  /**
1088
- * Expected response type, determines how the response body is parsed.
645
+ * Hook called just before the HTTP request is sent and after the request has been processed.
1089
646
  *
1090
- * Different response types trigger different parsing methods:
1091
- * - **"json"**: Parses as JSON using response.json()
1092
- * - **"text"**: Returns as plain text using response.text()
1093
- * - **"blob"**: Returns as Blob using response.blob()
1094
- * - **"arrayBuffer"**: Returns as ArrayBuffer using response.arrayBuffer()
1095
- * - **"stream"**: Returns the response body stream directly
647
+ * @param context - Request context with mutable request object and configuration
648
+ */
649
+ onRequestReady?: (context: RequestContext<TCallApiContext>) => Awaitable<unknown>;
650
+ /**
651
+ * Hook called during upload stream progress tracking.
1096
652
  *
1097
- * @default "json"
653
+ * This hook is triggered when uploading data (like file uploads) and provides
654
+ * progress information about the upload. Useful for implementing progress bars
655
+ * or upload status indicators.
1098
656
  *
1099
- * @example
1100
- * ```ts
1101
- * // JSON API responses (default)
1102
- * responseType: "json"
657
+ * @param context - Request stream context with progress event and request instance
658
+ * @returns Promise or void - Hook can be async or sync
1103
659
  *
1104
- * // Plain text responses
1105
- * responseType: "text"
1106
- * // Usage: const csvData = await callApi("/export.csv", { responseType: "text" });
660
+ */
661
+ onRequestStream?: (context: RequestStreamContext<TCallApiContext>) => Awaitable<unknown>;
662
+ /**
663
+ * Hook called when any HTTP response is received from the API.
1107
664
  *
1108
- * // File downloads
1109
- * responseType: "blob"
1110
- * // Usage: const file = await callApi("/download/file.pdf", { responseType: "blob" });
665
+ * This hook is triggered for both successful (2xx) and error (4xx, 5xx) responses.
666
+ * It's useful for response logging, metrics collection, or any processing that
667
+ * should happen regardless of response status.
1111
668
  *
1112
- * // Binary data
1113
- * responseType: "arrayBuffer"
1114
- * // Usage: const buffer = await callApi("/binary-data", { responseType: "arrayBuffer" });
669
+ * @param context - Response context with either success data or error information
670
+ * @returns Promise or void - Hook can be async or sync
1115
671
  *
1116
- * // Streaming responses
1117
- * responseType: "stream"
1118
- * // Usage: const stream = await callApi("/large-dataset", { responseType: "stream" });
1119
- * ```
1120
672
  */
1121
- responseType?: TResponseType$1;
673
+ onResponse?: (context: ResponseContext<TCallApiContext>) => Awaitable<unknown>;
1122
674
  /**
1123
- * Controls what data is included in the returned result object.
675
+ * Hook called when an HTTP error response (4xx, 5xx) is received from the API.
1124
676
  *
1125
- * Different modes return different combinations of data, error, and response:
1126
- * - **"all"**: Returns { data, error, response } - complete result information
1127
- * - **"onlyData"**: Returns only data (null for errors)
677
+ * This handles server-side errors where an HTTP response was successfully received
678
+ * but indicates an error condition. Different from `onRequestError` which handles
679
+ * network-level failures.
1128
680
  *
1129
- * When combined with throwOnError: true, null/error variants are automatically removed:
1130
- * - **"all" + throwOnError: true**: Returns { data, error: null, response } (error property is null, throws instead)
1131
- * - **"onlyData" + throwOnError: true**: Returns data (never null, throws on error)
681
+ * @param context - Response error context with HTTP error details and response
682
+ * @returns Promise or void - Hook can be async or sync
683
+ */
684
+ onResponseError?: (context: ResponseErrorContext<TCallApiContext>) => Awaitable<unknown>;
685
+ /**
686
+ * Hook called during download stream progress tracking.
1132
687
  *
1133
- * @default "all"
688
+ * This hook is triggered when downloading data (like file downloads) and provides
689
+ * progress information about the download. Useful for implementing progress bars
690
+ * or download status indicators.
1134
691
  *
1135
- * @example
1136
- * ```ts
1137
- * // Complete result with all information (default)
1138
- * const { data, error, response } = await callApi("/users", { resultMode: "all" });
1139
- * if (error) {
1140
- * console.error("Request failed:", error);
1141
- * } else {
1142
- * console.log("Users:", data);
1143
- * }
692
+ * @param context - Response stream context with progress event and response
693
+ * @returns Promise or void - Hook can be async or sync
1144
694
  *
1145
- * // Complete result but throws on errors (throwOnError removes error from type)
1146
- * try {
1147
- * const { data, response } = await callApi("/users", {
1148
- * resultMode: "all",
1149
- * throwOnError: true
1150
- * });
1151
- * console.log("Users:", data); // data is never null here
1152
- * } catch (error) {
1153
- * console.error("Request failed:", error);
1154
- * }
695
+ */
696
+ onResponseStream?: (context: ResponseStreamContext<TCallApiContext>) => Awaitable<unknown>;
697
+ /**
698
+ * Hook called when a request is being retried.
1155
699
  *
1156
- * // Only data, returns null on errors
1157
- * const users = await callApi("/users", { resultMode: "onlyData" });
1158
- * if (users) {
1159
- * console.log("Users:", users);
1160
- * } else {
1161
- * console.log("Request failed");
1162
- * }
700
+ * This hook is triggered before each retry attempt, providing information about
701
+ * the previous failure and the current retry attempt number. Useful for implementing
702
+ * custom retry logic, exponential backoff, or retry logging.
703
+ *
704
+ * @param context - Retry context with error details and retry attempt count
705
+ * @returns Promise or void - Hook can be async or sync
1163
706
  *
1164
- * // Only data, throws on errors (throwOnError removes null from type)
1165
- * try {
1166
- * const users = await callApi("/users", {
1167
- * resultMode: "onlyData",
1168
- * throwOnError: true
1169
- * });
1170
- * console.log("Users:", users); // users is never null here
1171
- * } catch (error) {
1172
- * console.error("Request failed:", error);
1173
- * }
1174
- * ```
1175
707
  */
1176
- resultMode?: TResultMode$1;
708
+ onRetry?: (response: RetryContext<TCallApiContext>) => Awaitable<unknown>;
1177
709
  /**
1178
- * Controls whether errors are thrown as exceptions or returned in the result.
710
+ * Hook called when a successful response (2xx status) is received from the API.
1179
711
  *
1180
- * Can be a boolean or a function that receives the error and decides whether to throw.
1181
- * When true, errors are thrown as exceptions instead of being returned in the result object.
712
+ * This hook is triggered only for successful responses and provides access to
713
+ * the parsed response data. Ideal for success logging, caching, or post-processing
714
+ * of successful API responses.
1182
715
  *
1183
- * @default false
716
+ * @param context - Success context with parsed response data and response object
717
+ * @returns Promise or void - Hook can be async or sync
1184
718
  *
1185
- * @example
1186
- * ```ts
1187
- * // Always throw errors
1188
- * throwOnError: true
1189
- * try {
1190
- * const data = await callApi("/users");
1191
- * console.log("Users:", data);
1192
- * } catch (error) {
1193
- * console.error("Request failed:", error);
1194
- * }
719
+ */
720
+ onSuccess?: (context: SuccessContext<TCallApiContext>) => Awaitable<unknown>;
721
+ /**
722
+ * Hook called when a validation error occurs.
1195
723
  *
1196
- * // Never throw errors (default)
1197
- * throwOnError: false
1198
- * const { data, error } = await callApi("/users");
1199
- * if (error) {
1200
- * console.error("Request failed:", error);
1201
- * }
1202
- *
1203
- * // Conditionally throw based on error type
1204
- * throwOnError: (error) => {
1205
- * // Throw on client errors (4xx) but not server errors (5xx)
1206
- * return error.response?.status >= 400 && error.response?.status < 500;
1207
- * }
724
+ * This hook is triggered when request or response data fails validation against
725
+ * a defined schema. It provides access to the validation error details and can
726
+ * be used for custom error handling, logging, or fallback behavior.
1208
727
  *
1209
- * // Throw only on specific status codes
1210
- * throwOnError: (error) => {
1211
- * const criticalErrors = [401, 403, 404];
1212
- * return criticalErrors.includes(error.response?.status);
1213
- * }
728
+ * @param context - Validation error context with error details and response (if available)
729
+ * @returns Promise or void - Hook can be async or sync
1214
730
  *
1215
- * // Throw on validation errors but not network errors
1216
- * throwOnError: (error) => {
1217
- * return error.type === "validation";
1218
- * }
1219
- * ```
1220
731
  */
1221
- throwOnError?: ThrowOnErrorType<TErrorData$1, TThrowOnError$1>;
732
+ onValidationError?: (context: ValidationErrorContext<TCallApiContext>) => Awaitable<unknown>;
733
+ }
734
+ type HooksOrHooksArray<TCallApiContext extends CallApiContext = DefaultCallApiContext> = { [Key in keyof Hooks<TCallApiContext>]: Hooks<TCallApiContext>[Key] | Array<Hooks<TCallApiContext>[Key]> };
735
+ interface HookConfigOptions {
1222
736
  /**
1223
- * Request timeout in milliseconds. Request will be aborted if it takes longer.
737
+ * Controls the execution mode of all composed hooks (main + plugin hooks).
1224
738
  *
1225
- * Useful for preventing requests from hanging indefinitely and providing
1226
- * better user experience with predictable response times.
739
+ * - **"parallel"**: All hooks execute simultaneously via Promise.all() for better performance
740
+ * - **"sequential"**: All hooks execute one by one in registration order via await in a loop
1227
741
  *
1228
- * @example
1229
- * ```ts
1230
- * // 5 second timeout
1231
- * timeout: 5000
742
+ * This affects how ALL hooks execute together, regardless of their source (main or plugin).
1232
743
  *
1233
- * // Different timeouts for different endpoints
1234
- * const quickApi = createFetchClient({ timeout: 3000 }); // 3s for fast endpoints
1235
- * const slowApi = createFetchClient({ timeout: 30000 }); // 30s for slow operations
744
+ * @default "parallel"
745
+ */
746
+ hooksExecutionMode?: "parallel" | "sequential";
747
+ }
748
+ type RequestContext<TCallApiContext extends Pick<CallApiContext, "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = {
749
+ /**
750
+ * Base configuration object passed to createFetchClient.
1236
751
  *
1237
- * // Per-request timeout override
1238
- * await callApi("/quick-data", { timeout: 1000 });
1239
- * await callApi("/slow-report", { timeout: 60000 });
752
+ * Contains the foundational configuration that applies to all requests
753
+ * made by this client instance, such as baseURL, default headers, and
754
+ * global options.
755
+ */
756
+ baseConfig: Exclude<BaseCallApiConfig, AnyFunction>;
757
+ /**
758
+ * Instance-specific configuration object passed to the callApi instance.
1240
759
  *
1241
- * // No timeout (use with caution)
1242
- * timeout: 0
1243
- * ```
760
+ * Contains configuration specific to this particular API call, which
761
+ * can override or extend the base configuration.
1244
762
  */
1245
- timeout?: number;
763
+ config: CallApiConfig;
764
+ /**
765
+ * Merged options combining base config, instance config, and default options.
766
+ *
767
+ * This is the final resolved configuration that will be used for the request,
768
+ * with proper precedence applied (instance > base > defaults).
769
+ */
770
+ options: CallApiExtraOptionsForHooks<TCallApiContext>;
771
+ /**
772
+ * Merged request object ready to be sent.
773
+ *
774
+ * Contains the final request configuration including URL, method, headers,
775
+ * body, and other fetch options. This object can be modified in onRequest
776
+ * hooks to customize the outgoing request.
777
+ */
778
+ request: CallApiRequestOptionsForHooks;
779
+ };
780
+ type ValidationErrorContext<TCallApiContext extends Pick<CallApiContext, "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext> & {
781
+ error: PossibleValidationError;
782
+ response: Response | null;
783
+ };
784
+ type SuccessContext<TCallApiContext extends Pick<CallApiContext, "Data" | "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext> & {
785
+ data: NoInfer<TCallApiContext["Data"]>;
786
+ response: Response;
787
+ };
788
+ type ResponseContext<TCallApiContext extends Pick<CallApiContext, "Data" | "ErrorData" | "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext> & (Prettify<CallApiResultSuccessVariant<TCallApiContext["Data"]>> | Prettify<Extract<CallApiResultErrorVariant<TCallApiContext["ErrorData"]>, {
789
+ error: PossibleHTTPError<TCallApiContext["ErrorData"]>;
790
+ }>>);
791
+ type RequestErrorContext<TCallApiContext extends Pick<CallApiContext, "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext> & {
792
+ error: PossibleJavaScriptError;
793
+ response: null;
794
+ };
795
+ type ErrorContext<TCallApiContext extends Pick<CallApiContext, "ErrorData" | "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext> & ({
796
+ error: PossibleHTTPError<TCallApiContext["ErrorData"]>;
797
+ response: Response;
798
+ } | {
799
+ error: PossibleJavaScriptOrValidationError;
800
+ response: Response | null;
801
+ });
802
+ type ResponseErrorContext<TCallApiContext extends Pick<CallApiContext, "ErrorData" | "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = Extract<ErrorContext<TCallApiContext>, {
803
+ error: PossibleHTTPError<TCallApiContext["ErrorData"]>;
804
+ }> & RequestContext<TCallApiContext>;
805
+ type RetryContext<TCallApiContext extends Pick<CallApiContext, "ErrorData" | "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = ErrorContext<TCallApiContext> & {
806
+ retryAttemptCount: number;
807
+ };
808
+ type RequestStreamContext<TCallApiContext extends Pick<CallApiContext, "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext> & {
809
+ event: StreamProgressEvent;
810
+ requestInstance: Request;
1246
811
  };
1247
- type BaseCallApiExtraOptions<TBaseCallApiContext$1 extends CallApiContext = DefaultCallApiContext, TBaseData$1 = DefaultDataType, TBaseErrorData$1 = DefaultDataType, TBaseResultMode$1 extends ResultModeType = ResultModeType, TBaseThrowOnError$1 extends ThrowOnErrorUnion = DefaultThrowOnError, TBaseResponseType$1 extends ResponseTypeType = ResponseTypeType, TBasePluginArray$1 extends CallApiPlugin[] = DefaultPluginArray, TBaseSchemaAndConfig$1 extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig> = SharedExtraOptions<TBaseCallApiContext$1, TBaseData$1, TBaseErrorData$1, TBaseResultMode$1, TBaseThrowOnError$1, TBaseResponseType$1, TBasePluginArray$1> & {
812
+ type ResponseStreamContext<TCallApiContext extends Pick<CallApiContext, "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext> & {
813
+ event: StreamProgressEvent;
814
+ response: Response;
815
+ };
816
+ //#endregion
817
+ //#region src/dedupe.d.ts
818
+ type DedupeStrategyUnion = UnmaskType<"cancel" | "defer" | "none">;
819
+ type DedupeOptionKeys = Exclude<keyof DedupeOptions, "dedupe">;
820
+ type InnerDedupeOptions = { [Key in DedupeOptionKeys as RemovePrefix<"dedupe", Key>]?: DedupeOptions[Key] };
821
+ type DedupeOptions = {
1248
822
  /**
1249
- * Array of base CallApi plugins to extend library functionality.
823
+ * All dedupe options in a single object instead of separate properties
824
+ */
825
+ dedupe?: InnerDedupeOptions;
826
+ /**
827
+ * Controls the scope of request deduplication caching.
1250
828
  *
1251
- * Base plugins are applied to all instances created from this base configuration
1252
- * and provide foundational functionality like authentication, logging, or caching.
829
+ * - `"global"`: Shares deduplication cache across all `createFetchClient` instances with the same `dedupeCacheScopeKey`.
830
+ * Useful for applications with multiple API clients that should share deduplication state.
831
+ * - `"local"`: Limits deduplication to requests within the same `createFetchClient` instance.
832
+ * Provides better isolation and is recommended for most use cases.
833
+ *
834
+ *
835
+ * **Real-world Scenarios:**
836
+ * - Use `"global"` when you have multiple API clients (user service, auth service, etc.) that might make overlapping requests
837
+ * - Use `"local"` (default) for single-purpose clients or when you want strict isolation between different parts of your app
1253
838
  *
1254
839
  * @example
1255
840
  * ```ts
1256
- * // Add logging plugin
841
+ * // Local scope - each client has its own deduplication cache
842
+ * const userClient = createFetchClient({ baseURL: "/api/users" });
843
+ * const postClient = createFetchClient({ baseURL: "/api/posts" });
844
+ * // These clients won't share deduplication state
1257
845
  *
1258
- * // Create base client with common plugins
1259
- * const callApi = createFetchClient({
1260
- * baseURL: "https://api.example.com",
1261
- * plugins: [loggerPlugin({ enabled: true })]
846
+ * // Global scope - share cache across related clients
847
+ * const userClient = createFetchClient({
848
+ * baseURL: "/api/users",
849
+ * dedupeCacheScope: "global",
1262
850
  * });
1263
- *
1264
- * // All requests inherit base plugins
1265
- * await callApi("/users");
1266
- * await callApi("/posts");
1267
- *
851
+ * const postClient = createFetchClient({
852
+ * baseURL: "/api/posts",
853
+ * dedupeCacheScope: "global",
854
+ * });
855
+ * // These clients will share deduplication state
1268
856
  * ```
1269
- */
1270
- plugins?: TBasePluginArray$1;
1271
- /**
1272
- * Base validation schemas for the client configuration.
1273
857
  *
1274
- * Defines validation rules for requests and responses that apply to all
1275
- * instances created from this base configuration. Provides type safety
1276
- * and runtime validation for API interactions.
858
+ * @default "local"
1277
859
  */
1278
- schema?: TBaseSchemaAndConfig$1;
860
+ dedupeCacheScope?: "global" | "local";
1279
861
  /**
1280
- * Controls which configuration parts skip automatic merging between base and instance configs.
862
+ * Unique namespace for the global deduplication cache when using `dedupeCacheScope: "global"`.
1281
863
  *
1282
- * By default, CallApi automatically merges base configuration with instance configuration.
1283
- * This option allows you to disable automatic merging for specific parts when you need
1284
- * manual control over how configurations are combined.
864
+ * This creates logical groupings of deduplication caches. All instances with the same key
865
+ * will share the same cache namespace, allowing fine-grained control over which clients
866
+ * share deduplication state.
1285
867
  *
1286
- * @enum
1287
- * - **"all"**: Disables automatic merging for both request options and extra options
1288
- * - **"options"**: Disables automatic merging of extra options only (hooks, plugins, etc.)
1289
- * - **"request"**: Disables automatic merging of request options only (headers, body, etc.)
868
+ * **Best Practices:**
869
+ * - Use descriptive names that reflect the logical grouping (e.g., "user-service", "analytics-api")
870
+ * - Keep scope keys consistent across related API clients
871
+ * - Consider using different scope keys for different environments (dev, staging, prod)
872
+ * - Avoid overly broad scope keys that might cause unintended cache sharing
873
+ *
874
+ * **Cache Management:**
875
+ * - Each scope key maintains its own independent cache
876
+ * - Caches are automatically cleaned up when no references remain
877
+ * - Consider the memory implications of multiple global scopes
1290
878
  *
1291
879
  * @example
1292
880
  * ```ts
1293
- * // Skip all automatic merging - full manual control
1294
- * const client = callApi.create((ctx) => ({
1295
- * skipAutoMergeFor: "all",
881
+ * // Group related API clients together
882
+ * const userClient = createFetchClient({
883
+ * baseURL: "/api/users",
884
+ * dedupeCacheScope: "global",
885
+ * dedupeCacheScopeKey: "user-service"
886
+ * });
887
+ * const profileClient = createFetchClient({
888
+ * baseURL: "/api/profiles",
889
+ * dedupeCacheScope: "global",
890
+ * dedupeCacheScopeKey: "user-service" // Same scope - will share cache
891
+ * });
1296
892
  *
1297
- * // Manually decide what to merge
1298
- * baseURL: ctx.options.baseURL, // Keep base URL
1299
- * timeout: 5000, // Override timeout
1300
- * headers: {
1301
- * ...ctx.request.headers, // Merge headers manually
1302
- * "X-Custom": "value" // Add custom header
1303
- * }
1304
- * }));
893
+ * // Separate analytics client with its own cache
894
+ * const analyticsClient = createFetchClient({
895
+ * baseURL: "/api/analytics",
896
+ * dedupeCacheScope: "global",
897
+ * dedupeCacheScopeKey: "analytics-service" // Different scope
898
+ * });
1305
899
  *
1306
- * // Skip options merging - manual plugin/hook control
1307
- * const client = callApi.create((ctx) => ({
1308
- * skipAutoMergeFor: "options",
900
+ * // Environment-specific scoping
901
+ * const apiClient = createFetchClient({
902
+ * dedupeCacheScope: "global",
903
+ * dedupeCacheScopeKey: `api-${process.env.NODE_ENV}` // "api-development", "api-production", etc.
904
+ * });
905
+ * ```
1309
906
  *
1310
- * // Manually control which plugins to use
1311
- * plugins: [
1312
- * ...ctx.options.plugins?.filter(p => p.name !== "unwanted") || [],
1313
- * customPlugin
1314
- * ],
907
+ * @default "default"
908
+ */
909
+ dedupeCacheScopeKey?: "default" | AnyString | ((context: RequestContext) => string | undefined);
910
+ /**
911
+ * Custom key generator for request deduplication.
1315
912
  *
1316
- * // Request options still auto-merge
1317
- * method: "POST"
1318
- * }));
913
+ * Override the default key generation strategy to control exactly which requests
914
+ * are considered duplicates. The default key combines URL, method, body, and
915
+ * relevant headers (excluding volatile ones like 'Date', 'Authorization', etc.).
1319
916
  *
1320
- * // Skip request merging - manual request control
1321
- * const client = callApi.create((ctx) => ({
1322
- * skipAutoMergeFor: "request",
917
+ * **Default Key Generation:**
918
+ * The auto-generated key includes:
919
+ * - Full request URL (including query parameters)
920
+ * - HTTP method (GET, POST, etc.)
921
+ * - Request body (for POST/PUT/PATCH requests)
922
+ * - Stable headers (excludes Date, Authorization, User-Agent, etc.)
1323
923
  *
1324
- * // Extra options still auto-merge (plugins, hooks, etc.)
924
+ * **Custom Key Best Practices:**
925
+ * - Include only the parts of the request that should affect deduplication
926
+ * - Avoid including volatile data (timestamps, random IDs, etc.)
927
+ * - Consider performance - simpler keys are faster to compute and compare
928
+ * - Ensure keys are deterministic for the same logical request
929
+ * - Use consistent key formats across your application
1325
930
  *
1326
- * // Manually control request options
1327
- * headers: {
1328
- * "Content-Type": "application/json",
1329
- * // Don't merge base headers
1330
- * },
1331
- * method: ctx.request.method || "GET"
1332
- * }));
931
+ * **Performance Considerations:**
932
+ * - Function-based keys are computed on every request - keep them lightweight
933
+ * - String keys are fastest but least flexible
934
+ * - Consider caching expensive key computations if needed
1333
935
  *
1334
- * // Use case: Conditional merging based on request
1335
- * const client = createFetchClient((ctx) => ({
1336
- * skipAutoMergeFor: "options",
936
+ * @example
937
+ * ```ts
938
+ * import { callApi } from "@zayne-labs/callapi";
1337
939
  *
1338
- * // Only use auth plugin for protected routes
1339
- * plugins: ctx.initURL.includes("/protected/")
1340
- * ? [...(ctx.options.plugins || []), authPlugin]
1341
- * : ctx.options.plugins?.filter(p => p.name !== "auth") || []
1342
- * }));
940
+ * // Simple static key - useful for singleton requests
941
+ * const config = callApi("/api/config", {
942
+ * dedupeKey: "app-config",
943
+ * dedupeStrategy: "defer" // Share the same config across all requests
944
+ * });
945
+ *
946
+ * // URL and method only - ignore headers and body
947
+ * const userData = callApi("/api/user/123", {
948
+ * dedupeKey: (context) => `${context.options.method}:${context.options.fullURL}`
949
+ * });
950
+ *
951
+ * // Include specific headers in deduplication
952
+ * const apiCall = callApi("/api/data", {
953
+ * dedupeKey: (context) => {
954
+ * const authHeader = context.request.headers.get("Authorization");
955
+ * return `${context.options.fullURL}-${authHeader}`;
956
+ * }
957
+ * });
958
+ *
959
+ * // User-specific deduplication
960
+ * const userSpecificCall = callApi("/api/dashboard", {
961
+ * dedupeKey: (context) => {
962
+ * const userId = context.options.fullURL.match(/user\/(\d+)/)?.[1];
963
+ * return `dashboard-${userId}`;
964
+ * }
965
+ * });
966
+ *
967
+ * // Ignore certain query parameters
968
+ * const searchCall = callApi("/api/search?q=test&timestamp=123456", {
969
+ * dedupeKey: (context) => {
970
+ * const url = new URL(context.options.fullURL);
971
+ * url.searchParams.delete("timestamp"); // Remove volatile param
972
+ * return `search:${url.toString()}`;
973
+ * }
974
+ * });
1343
975
  * ```
976
+ *
977
+ * @default Auto-generated from request details
1344
978
  */
1345
- skipAutoMergeFor?: "all" | "options" | "request";
1346
- };
1347
- type GetBaseSchemaRoutes<TBaseSchemaAndConfig$1 extends BaseCallApiSchemaAndConfig> = Writeable<TBaseSchemaAndConfig$1["routes"], "deep">;
1348
- type GetBaseSchemaConfig<TBaseSchemaAndConfig$1 extends BaseCallApiSchemaAndConfig> = Writeable<NonNullable<TBaseSchemaAndConfig$1["config"]>, "deep">;
1349
- type InferExtendSchemaContext<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey$1 extends string> = {
1350
- baseSchemaRoutes: TBaseSchemaRoutes$1;
1351
- currentRouteSchema: GetCurrentRouteSchema<TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1>;
1352
- };
1353
- type GetExtendSchemaConfigContext<TBaseSchemaConfig extends CallApiSchemaConfig> = {
1354
- baseSchemaConfig: TBaseSchemaConfig;
1355
- };
1356
- type InferExtendPluginContext<TBasePluginArray$1 extends CallApiPlugin[]> = {
1357
- basePlugins: TBasePluginArray$1;
1358
- };
1359
- type CallApiExtraOptions<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext, TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TResultMode$1 extends ResultModeType = ResultModeType, TThrowOnError$1 extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType$1 extends ResponseTypeType = ResponseTypeType, TBasePluginArray$1 extends CallApiPlugin[] = DefaultPluginArray, TPluginArray$1 extends CallApiPlugin[] = DefaultPluginArray, TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes = BaseCallApiSchemaRoutes, TSchema$1 extends CallApiSchema = CallApiSchema, TBaseSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TSchemaConfig$1 extends CallApiSchemaConfig = CallApiSchemaConfig, TCurrentRouteSchemaKey$1 extends string = string, TComputedPluginContext = InferExtendPluginContext<TBasePluginArray$1>, TComputedSchemaContext = InferExtendSchemaContext<TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1>, TComputedSchemaConfigContext = GetExtendSchemaConfigContext<TBaseSchemaConfig>> = SharedExtraOptions<TCallApiContext$1, TData$1, TErrorData$1, TResultMode$1, TThrowOnError$1, TResponseType$1, TPluginArray$1> & {
979
+ dedupeKey?: string | ((context: RequestContext) => string | undefined);
1360
980
  /**
1361
- * Array of instance-specific CallApi plugins or a function to configure plugins.
981
+ * Strategy for handling duplicate requests. Can be a static string or callback function.
1362
982
  *
1363
- * Instance plugins are added to the base plugins and provide functionality
1364
- * specific to this particular API instance. Can be a static array or a function
1365
- * that receives base plugins and returns the instance plugins.
983
+ * **Available Strategies:**
984
+ * - `"cancel"`: Cancel previous request when new one starts (good for search)
985
+ * - `"defer"`: Share response between duplicate requests (good for config loading)
986
+ * - `"none"`: No deduplication, all requests execute independently
1366
987
  *
1367
- */
1368
- plugins?: TPluginArray$1 | ((context: TComputedPluginContext) => TPluginArray$1);
1369
- /**
1370
- * For instance-specific validation schemas
988
+ * @example
989
+ * ```ts
990
+ * // Static strategies
991
+ * const searchClient = createFetchClient({
992
+ * dedupeStrategy: "cancel" // Cancel previous searches
993
+ * });
1371
994
  *
1372
- * Defines validation rules specific to this API instance, extending or overriding the base schema.
995
+ * const configClient = createFetchClient({
996
+ * dedupeStrategy: "defer" // Share config across components
997
+ * });
1373
998
  *
1374
- * Can be a static schema object or a function that receives base schema context and returns instance schemas.
999
+ * // Dynamic strategy based on request
1000
+ * const smartClient = createFetchClient({
1001
+ * dedupeStrategy: (context) => {
1002
+ * return context.options.method === "GET" ? "defer" : "cancel";
1003
+ * }
1004
+ * });
1375
1005
  *
1376
- */
1377
- schema?: TSchema$1 | ((context: TComputedSchemaContext) => TSchema$1);
1378
- /**
1379
- * Instance-specific schema configuration or a function to configure schema behavior.
1006
+ * // Search-as-you-type with cancel strategy
1007
+ * const handleSearch = async (query: string) => {
1008
+ * try {
1009
+ * const { data } = await callApi("/api/search", {
1010
+ * method: "POST",
1011
+ * body: { query },
1012
+ * dedupeStrategy: "cancel",
1013
+ * dedupeKey: "search" // Cancel previous searches, only latest one goes through
1014
+ * });
1380
1015
  *
1381
- * Controls how validation schemas are applied and behave for this specific API instance.
1382
- * Can override base schema configuration or extend it with instance-specific validation rules.
1016
+ * updateSearchResults(data);
1017
+ * } catch (error) {
1018
+ * if (error.name === "AbortError") {
1019
+ * // Previous search cancelled - (expected behavior)
1020
+ * return;
1021
+ * }
1022
+ * console.error("Search failed:", error);
1023
+ * }
1024
+ * };
1025
+ *
1026
+ * ```
1383
1027
  *
1028
+ * @default "cancel"
1384
1029
  */
1385
- schemaConfig?: TSchemaConfig$1 | ((context: TComputedSchemaConfigContext) => TSchemaConfig$1);
1386
- };
1387
- type CallApiExtraOptionsForHooks<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = Hooks & Omit<CallApiExtraOptions<TCallApiContext$1>, keyof Hooks>;
1388
- type InstanceContext = {
1389
- initURL: string;
1390
- options: CallApiExtraOptions;
1391
- request: CallApiRequestOptions;
1392
- };
1393
- type BaseCallApiConfig<TBaseCallApiContext$1 extends CallApiContext = DefaultCallApiContext, TBaseData$1 = DefaultDataType, TBaseErrorData$1 = DefaultDataType, TBaseResultMode$1 extends ResultModeType = ResultModeType, TBaseThrowOnError$1 extends ThrowOnErrorUnion = DefaultThrowOnError, TBaseResponseType$1 extends ResponseTypeType = ResponseTypeType, TBaseSchemaAndConfig$1 extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig, TBasePluginArray$1 extends CallApiPlugin[] = DefaultPluginArray, TComputedBaseConfig = BaseCallApiExtraOptions<TBaseCallApiContext$1, TBaseData$1, TBaseErrorData$1, TBaseResultMode$1, TBaseThrowOnError$1, TBaseResponseType$1, TBasePluginArray$1, TBaseSchemaAndConfig$1>> = (CallApiRequestOptions & TComputedBaseConfig) | ((context: InstanceContext) => CallApiRequestOptions & TComputedBaseConfig);
1394
- type CallApiConfig<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext, TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TResultMode$1 extends ResultModeType = ResultModeType, TThrowOnError$1 extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType$1 extends ResponseTypeType = ResponseTypeType, TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes = BaseCallApiSchemaRoutes, TSchema$1 extends CallApiSchema = CallApiSchema, TBaseSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TSchemaConfig$1 extends CallApiSchemaConfig = CallApiSchemaConfig, TInitURL$1 extends InitURLOrURLObject = InitURLOrURLObject, TCurrentRouteSchemaKey$1 extends string = string, TBasePluginArray$1 extends CallApiPlugin[] = DefaultPluginArray, TPluginArray$1 extends CallApiPlugin[] = DefaultPluginArray> = InferExtraOptions<TSchema$1, TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1, TCallApiContext$1> & InferRequestOptions<TSchema$1, TInitURL$1> & Omit<CallApiExtraOptions<TCallApiContext$1, TData$1, TErrorData$1, TResultMode$1, TThrowOnError$1, TResponseType$1, TBasePluginArray$1, TPluginArray$1, TBaseSchemaRoutes$1, TSchema$1, TBaseSchemaConfig, TSchemaConfig$1, TCurrentRouteSchemaKey$1>, keyof InferExtraOptions<CallApiSchema, BaseCallApiSchemaRoutes, string, CallApiContext>> & Omit<CallApiRequestOptions, keyof InferRequestOptions<CallApiSchema, string>>;
1395
- type CallApiParameters<TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TResultMode$1 extends ResultModeType = ResultModeType, TCallApiContext$1 extends CallApiContext = DefaultCallApiContext, TThrowOnError$1 extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType$1 extends ResponseTypeType = ResponseTypeType, TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes = BaseCallApiSchemaRoutes, TSchema$1 extends CallApiSchema = CallApiSchema, TBaseSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TSchemaConfig$1 extends CallApiSchemaConfig = CallApiSchemaConfig, TInitURL$1 extends InitURLOrURLObject = InitURLOrURLObject, TCurrentRouteSchemaKey$1 extends string = string, TBasePluginArray$1 extends CallApiPlugin[] = DefaultPluginArray, TPluginArray$1 extends CallApiPlugin[] = DefaultPluginArray> = [initURL: TInitURL$1, config?: CallApiConfig<TCallApiContext$1, TData$1, TErrorData$1, TResultMode$1, TThrowOnError$1, TResponseType$1, TBaseSchemaRoutes$1, TSchema$1, TBaseSchemaConfig, TSchemaConfig$1, TInitURL$1, TCurrentRouteSchemaKey$1, TBasePluginArray$1, TPluginArray$1>];
1396
- type CallApiResult<TData$1, TErrorData$1, TResultMode$1 extends ResultModeType, TThrowOnError$1 extends ThrowOnErrorUnion, TResponseType$1 extends ResponseTypeType> = GetCallApiResult<TData$1, TErrorData$1, TResultMode$1, TThrowOnError$1, TResponseType$1>;
1397
- type CallApiResultLoose<TData$1, TErrorData$1, TResultMode$1 extends ResultModeType = ResultModeType, TThrowOnError$1 extends ThrowOnErrorUnion = ThrowOnErrorUnion, TResponseType$1 extends ResponseTypeType = ResponseTypeType> = GetCallApiResult<TData$1, TErrorData$1, TResultMode$1, TThrowOnError$1, TResponseType$1>;
1398
- //#endregion
1399
- //#region src/utils/external/body.d.ts
1400
- type ToQueryStringFn = {
1401
- (query: CallApiExtraOptions["query"]): string | null;
1402
- (query: Required<CallApiExtraOptions>["query"]): string;
1403
- };
1404
- declare const toQueryString: ToQueryStringFn;
1405
- type AllowedPrimitives = boolean | number | string | Blob | null | undefined;
1406
- type AllowedValues = AllowedPrimitives | AllowedPrimitives[] | Record<string, AllowedPrimitives>;
1407
- /**
1408
- * @description Converts a plain object to FormData.
1409
- *
1410
- * Handles various data types:
1411
- * - **Primitives** (string, number, boolean): Converted to strings
1412
- * - **Blobs/Files**: Added directly to FormData
1413
- * - **Arrays**: Each item is appended (allows multiple values for same key)
1414
- * - **Objects**: JSON stringified before adding to FormData
1415
- *
1416
- * @example
1417
- * ```ts
1418
- * // Basic usage
1419
- * const formData = toFormData({
1420
- * name: "John",
1421
- * age: 30,
1422
- * active: true
1423
- * });
1424
- *
1425
- * // With arrays
1426
- * const formData = toFormData({
1427
- * tags: ["javascript", "typescript"],
1428
- * name: "John"
1429
- * });
1430
- *
1431
- * // With files
1432
- * const formData = toFormData({
1433
- * avatar: fileBlob,
1434
- * name: "John"
1435
- * });
1436
- *
1437
- * // With nested objects (one level only)
1438
- * const formData = toFormData({
1439
- * user: { name: "John", age: 30 },
1440
- * settings: { theme: "dark" }
1441
- * });
1442
- */
1443
- declare const toFormData: (data: Record<string, AllowedValues>) => FormData;
1444
- //#endregion
1445
- //#region src/utils/external/define.d.ts
1446
- declare const defineSchema: <const TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, const TSchemaConfig extends CallApiSchemaConfig>(routes: TBaseSchemaRoutes, config?: Satisfies<TSchemaConfig, CallApiSchemaConfig>) => {
1447
- config: Writeable<Satisfies<TSchemaConfig, CallApiSchemaConfig>, "deep">;
1448
- routes: Writeable<TBaseSchemaRoutes, "deep">;
1449
- };
1450
- declare const defineSchemaRoutes: <const TSchemaRoutes extends BaseCallApiSchemaRoutes>(routes: TSchemaRoutes) => Writeable<typeof routes, "deep">;
1451
- declare const defineMainSchema: <const TSchema extends CallApiSchema>(mainSchema: Satisfies<TSchema, CallApiSchema>) => Writeable<typeof mainSchema, "deep">;
1452
- declare const defineSchemaConfig: <const TSchemaConfig extends CallApiSchemaConfig>(config: Satisfies<TSchemaConfig, CallApiSchemaConfig>) => Writeable<typeof config, "deep">;
1453
- declare const definePlugin: <const TPlugin extends CallApiPlugin>(plugin: TPlugin) => Writeable<typeof plugin, "deep">;
1454
- type BaseConfigObject = Exclude<BaseCallApiConfig, AnyFunction>;
1455
- type BaseConfigFn = Extract<BaseCallApiConfig, AnyFunction>;
1456
- type DefineBaseConfig = {
1457
- <const TBaseConfig extends BaseConfigObject>(baseConfig: Satisfies<TBaseConfig, BaseConfigObject>): Writeable<typeof baseConfig, "deep">;
1458
- <TBaseConfigFn extends BaseConfigFn>(baseConfig: TBaseConfigFn): TBaseConfigFn;
1030
+ dedupeStrategy?: DedupeStrategyUnion | ((context: RequestContext) => DedupeStrategyUnion);
1459
1031
  };
1460
- declare const defineBaseConfig: DefineBaseConfig;
1461
1032
  //#endregion
1462
- //#region src/utils/external/guards.d.ts
1463
- declare const isHTTPError: <TErrorData>(error: CallApiResultErrorVariant<TErrorData>["error"] | null) => error is PossibleHTTPError<TErrorData>;
1464
- declare const isHTTPErrorInstance: <TErrorData>(error: unknown) => error is HTTPError<TErrorData>;
1465
- declare const isValidationError: (error: CallApiResultErrorVariant<unknown>["error"] | null) => error is PossibleValidationError;
1466
- declare const isValidationErrorInstance: (error: unknown) => error is ValidationError;
1467
- declare const isJavascriptError: (error: CallApiResultErrorVariant<unknown>["error"] | null) => error is PossibleJavaScriptError;
1468
- //#endregion
1469
- //#region src/stream.d.ts
1470
- type StreamProgressEvent = {
1033
+ //#region src/retry.d.ts
1034
+ declare const defaultRetryStatusCodesLookup: () => Readonly<{
1035
+ 408: "Request Timeout";
1036
+ 409: "Conflict";
1037
+ 425: "Too Early";
1038
+ 429: "Too Many Requests";
1039
+ 500: "Internal Server Error";
1040
+ 502: "Bad Gateway";
1041
+ 503: "Service Unavailable";
1042
+ 504: "Gateway Timeout";
1043
+ }>;
1044
+ type RetryStatusCodes = UnmaskType<AnyNumber | keyof ReturnType<typeof defaultRetryStatusCodesLookup>>;
1045
+ type RetryCondition<TErrorData> = (context: ErrorContext<{
1046
+ ErrorData: TErrorData;
1047
+ }>) => Awaitable<boolean>;
1048
+ type RetryOptionKeys<TErrorData> = Exclude<keyof RetryOptions<TErrorData>, "~retryAttemptCount" | "retry">;
1049
+ type InnerRetryOptions<TErrorData> = { [Key in RetryOptionKeys<TErrorData> as RemovePrefix<"retry", Key>]?: RetryOptions<TErrorData>[Key] };
1050
+ interface RetryOptions<TErrorData> {
1471
1051
  /**
1472
- * Current chunk of data being streamed
1052
+ * Keeps track of the number of times the request has already been retried
1053
+ * @internal
1054
+ * @deprecated **NOTE**: This property is used internally to track retries. Please abstain from modifying it.
1473
1055
  */
1474
- chunk: Uint8Array;
1056
+ readonly ["~retryAttemptCount"]?: number;
1475
1057
  /**
1476
- * Progress in percentage
1058
+ * All retry options in a single object instead of separate properties
1477
1059
  */
1478
- progress: number;
1060
+ retry?: InnerRetryOptions<TErrorData>;
1479
1061
  /**
1480
- * Total size of data in bytes
1062
+ * Number of allowed retry attempts on HTTP errors
1063
+ * @default 0
1481
1064
  */
1482
- totalBytes: number;
1065
+ retryAttempts?: number;
1483
1066
  /**
1484
- * Amount of data transferred so far
1067
+ * Callback whose return value determines if a request should be retried or not
1485
1068
  */
1486
- transferredBytes: number;
1487
- };
1488
- declare global {
1489
- interface ReadableStream<R> {
1490
- [Symbol.asyncIterator]: () => AsyncIterableIterator<R>;
1491
- }
1492
- }
1493
- //#endregion
1494
- //#region src/hooks.d.ts
1495
- interface Hooks<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> {
1069
+ retryCondition?: RetryCondition<TErrorData>;
1496
1070
  /**
1497
- * Hook called when any error occurs within the request/response lifecycle.
1498
- *
1499
- * This is a unified error handler that catches both request errors (network failures,
1500
- * timeouts, etc.) and response errors (HTTP error status codes). It's essentially
1501
- * a combination of `onRequestError` and `onResponseError` hooks.
1502
- *
1503
- * @param context - Error context containing error details, request info, and response (if available)
1504
- * @returns Promise or void - Hook can be async or sync
1071
+ * Delay between retries in milliseconds
1072
+ * @default 1000
1505
1073
  */
1506
- onError?: (context: ErrorContext<TCallApiContext$1>) => Awaitable<unknown>;
1074
+ retryDelay?: number | ((currentAttemptCount: number) => number);
1507
1075
  /**
1508
- * Hook called before the HTTP request is sent and before any internal processing of the request object begins.
1509
- *
1510
- * This is the ideal place to modify request headers, add authentication,
1511
- * implement request logging, or perform any setup before the network call.
1512
- *
1513
- * @param context - Request context with mutable request object and configuration
1514
- * @returns Promise or void - Hook can be async or sync
1515
- *
1076
+ * Maximum delay in milliseconds. Only applies to exponential strategy
1077
+ * @default 10000
1516
1078
  */
1517
- onRequest?: (context: RequestContext<TCallApiContext$1>) => Awaitable<unknown>;
1079
+ retryMaxDelay?: number;
1518
1080
  /**
1519
- * Hook called when an error occurs during the fetch request itself.
1520
- *
1521
- * This handles network-level errors like connection failures, timeouts,
1522
- * DNS resolution errors, or other issues that prevent getting an HTTP response.
1523
- * Note that HTTP error status codes (4xx, 5xx) are handled by `onResponseError`.
1524
- *
1525
- * @param context - Request error context with error details and null response
1526
- * @returns Promise or void - Hook can be async or sync
1081
+ * HTTP methods that are allowed to retry
1082
+ * @default ["GET", "POST"]
1527
1083
  */
1528
- onRequestError?: (context: RequestErrorContext<TCallApiContext$1>) => Awaitable<unknown>;
1084
+ retryMethods?: MethodUnion[];
1529
1085
  /**
1530
- * Hook called just before the HTTP request is sent and after the request has been processed.
1531
- *
1532
- * @param context - Request context with mutable request object and configuration
1086
+ * HTTP status codes that trigger a retry
1533
1087
  */
1534
- onRequestReady?: (context: RequestContext<TCallApiContext$1>) => Awaitable<unknown>;
1088
+ retryStatusCodes?: RetryStatusCodes[];
1535
1089
  /**
1536
- * Hook called during upload stream progress tracking.
1537
- *
1538
- * This hook is triggered when uploading data (like file uploads) and provides
1539
- * progress information about the upload. Useful for implementing progress bars
1540
- * or upload status indicators.
1541
- *
1542
- * @param context - Request stream context with progress event and request instance
1543
- * @returns Promise or void - Hook can be async or sync
1544
- *
1090
+ * Strategy to use when retrying
1091
+ * @default "linear"
1545
1092
  */
1546
- onRequestStream?: (context: RequestStreamContext<TCallApiContext$1>) => Awaitable<unknown>;
1093
+ retryStrategy?: "exponential" | "linear";
1094
+ }
1095
+ //#endregion
1096
+ //#region src/utils/external/error.d.ts
1097
+ type HTTPErrorDetails<TErrorData> = Pick<CallApiExtraOptions, "defaultHTTPErrorMessage"> & {
1098
+ errorData: TErrorData;
1099
+ response: Response;
1100
+ };
1101
+ declare class HTTPError<TErrorData = Record<string, unknown>> extends Error {
1102
+ errorData: HTTPErrorDetails<TErrorData>["errorData"];
1103
+ readonly httpErrorSymbol: symbol;
1104
+ name: "HTTPError";
1105
+ response: HTTPErrorDetails<TErrorData>["response"];
1106
+ constructor(errorDetails: HTTPErrorDetails<TErrorData>, errorOptions?: ErrorOptions);
1547
1107
  /**
1548
- * Hook called when any HTTP response is received from the API.
1549
- *
1550
- * This hook is triggered for both successful (2xx) and error (4xx, 5xx) responses.
1551
- * It's useful for response logging, metrics collection, or any processing that
1552
- * should happen regardless of response status.
1553
- *
1554
- * @param context - Response context with either success data or error information
1555
- * @returns Promise or void - Hook can be async or sync
1556
- *
1108
+ * @description Checks if the given error is an instance of HTTPError
1109
+ * @param error - The error to check
1110
+ * @returns true if the error is an instance of HTTPError, false otherwise
1557
1111
  */
1558
- onResponse?: (context: ResponseContext<TCallApiContext$1>) => Awaitable<unknown>;
1112
+ static isError<TErrorData>(error: unknown): error is HTTPError<TErrorData>;
1113
+ }
1114
+ type SafeExtract<TUnion, TKey extends TUnion> = Extract<TUnion, TKey>;
1115
+ type ValidationErrorDetails = {
1559
1116
  /**
1560
- * Hook called when an HTTP error response (4xx, 5xx) is received from the API.
1561
- *
1562
- * This handles server-side errors where an HTTP response was successfully received
1563
- * but indicates an error condition. Different from `onRequestError` which handles
1564
- * network-level failures.
1117
+ * The cause of the validation error.
1565
1118
  *
1566
- * @param context - Response error context with HTTP error details and response
1567
- * @returns Promise or void - Hook can be async or sync
1119
+ * 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.
1568
1120
  */
1569
- onResponseError?: (context: ResponseErrorContext<TCallApiContext$1>) => Awaitable<unknown>;
1121
+ issueCause: "unknown" | `schemaConfig-(${SafeExtract<keyof CallApiSchemaConfig, "strict">})` | keyof CallApiSchema;
1570
1122
  /**
1571
- * Hook called during download stream progress tracking.
1572
- *
1573
- * This hook is triggered when downloading data (like file downloads) and provides
1574
- * progress information about the download. Useful for implementing progress bars
1575
- * or download status indicators.
1123
+ * The issues that caused the validation error.
1124
+ */
1125
+ issues: readonly StandardSchemaV1.Issue[];
1126
+ /**
1127
+ * The response from server, if any.
1128
+ */
1129
+ response: Response | null;
1130
+ };
1131
+ declare class ValidationError extends Error {
1132
+ errorData: ValidationErrorDetails["issues"];
1133
+ issueCause: ValidationErrorDetails["issueCause"];
1134
+ name: "ValidationError";
1135
+ response: ValidationErrorDetails["response"];
1136
+ readonly validationErrorSymbol: symbol;
1137
+ constructor(details: ValidationErrorDetails, errorOptions?: ErrorOptions);
1138
+ /**
1139
+ * @description Checks if the given error is an instance of ValidationError
1140
+ * @param error - The error to check
1141
+ * @returns true if the error is an instance of ValidationError, false otherwise
1142
+ */
1143
+ static isError(error: unknown): error is ValidationError;
1144
+ }
1145
+ //#endregion
1146
+ //#region src/types/common.d.ts
1147
+ interface Register {}
1148
+ type GlobalMeta = Register extends {
1149
+ meta?: infer TMeta extends DefaultMetaObject;
1150
+ } ? TMeta : DefaultMetaObject;
1151
+ type CallApiContext = {
1152
+ Data?: DefaultDataType;
1153
+ ErrorData?: DefaultDataType;
1154
+ InferredExtraOptions?: unknown;
1155
+ Meta?: DefaultMetaObject;
1156
+ ResultMode?: ResultModeType;
1157
+ };
1158
+ type OverrideCallApiContext<TFullCallApiContext extends CallApiContext, TOverrideCallApiContext extends CallApiContext> = Omit<TFullCallApiContext, keyof TOverrideCallApiContext> & TOverrideCallApiContext;
1159
+ type FetchSpecificKeysUnion = Exclude<(typeof fetchSpecificKeys)[number], "body" | "headers" | "method">;
1160
+ type ModifiedRequestInit = RequestInit & {
1161
+ duplex?: "half";
1162
+ };
1163
+ type CallApiRequestOptions = Prettify<{
1164
+ /**
1165
+ * Body of the request, can be a object or any other supported body type.
1166
+ */
1167
+ body?: Body;
1168
+ /**
1169
+ * Headers to be used in the request.
1170
+ */
1171
+ headers?: HeadersOption;
1172
+ /**
1173
+ * HTTP method for the request.
1174
+ * @default "GET"
1175
+ */
1176
+ method?: MethodUnion;
1177
+ } & Pick<ModifiedRequestInit, FetchSpecificKeysUnion>>;
1178
+ type CallApiRequestOptionsForHooks = Omit<CallApiRequestOptions, "headers"> & {
1179
+ headers: Record<string, string | undefined>;
1180
+ };
1181
+ type SharedExtraOptions<TCallApiContext extends CallApiContext = DefaultCallApiContext, TData = DefaultDataType, TErrorData = DefaultDataType, TResultMode extends ResultModeType = ResultModeType, TThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType extends ResponseTypeType = ResponseTypeType, TPluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedMergedPluginExtraOptions = Partial<InferPluginExtraOptions<TPluginArray> & TCallApiContext["InferredExtraOptions"]>, TComputedCallApiContext extends CallApiContext = OverrideCallApiContext<TCallApiContext, {
1182
+ Data: TData;
1183
+ ErrorData: TErrorData;
1184
+ InferredExtraOptions: TComputedMergedPluginExtraOptions;
1185
+ ResultMode: TResultMode;
1186
+ }>> = DedupeOptions & HookConfigOptions & HooksOrHooksArray<TComputedCallApiContext> & Middlewares<TComputedCallApiContext> & ResultModeOption<TErrorData, TResultMode> & RetryOptions<TErrorData> & TComputedMergedPluginExtraOptions & ThrowOnErrorOption<TErrorData, TThrowOnError> & URLOptions & {
1187
+ /**
1188
+ * Automatically add an Authorization header value.
1576
1189
  *
1577
- * @param context - Response stream context with progress event and response
1578
- * @returns Promise or void - Hook can be async or sync
1190
+ * Supports multiple authentication patterns:
1191
+ * - String: Direct authorization header value
1192
+ * - Auth object: Structured authentication configuration
1579
1193
  *
1194
+ * ```
1580
1195
  */
1581
- onResponseStream?: (context: ResponseStreamContext<TCallApiContext$1>) => Awaitable<unknown>;
1196
+ auth?: Auth;
1582
1197
  /**
1583
- * Hook called when a request is being retried.
1198
+ * Custom function to serialize request body objects into strings.
1584
1199
  *
1585
- * This hook is triggered before each retry attempt, providing information about
1586
- * the previous failure and the current retry attempt number. Useful for implementing
1587
- * custom retry logic, exponential backoff, or retry logging.
1200
+ * Useful for custom serialization formats or when the default JSON
1201
+ * serialization doesn't meet your needs.
1588
1202
  *
1589
- * @param context - Retry context with error details and retry attempt count
1590
- * @returns Promise or void - Hook can be async or sync
1203
+ * @example
1204
+ * ```ts
1205
+ * // Custom form data serialization
1206
+ * bodySerializer: (data) => {
1207
+ * const formData = new URLSearchParams();
1208
+ * Object.entries(data).forEach(([key, value]) => {
1209
+ * formData.append(key, String(value));
1210
+ * });
1211
+ * return formData.toString();
1212
+ * }
1591
1213
  *
1214
+ * // XML serialization
1215
+ * bodySerializer: (data) => {
1216
+ * return `<request>${Object.entries(data)
1217
+ * .map(([key, value]) => `<${key}>${value}</${key}>`)
1218
+ * .join('')}</request>`;
1219
+ * }
1220
+ *
1221
+ * // Custom JSON with specific formatting
1222
+ * bodySerializer: (data) => JSON.stringify(data, null, 2)
1223
+ * ```
1592
1224
  */
1593
- onRetry?: (response: RetryContext<TCallApiContext$1>) => Awaitable<unknown>;
1225
+ bodySerializer?: (bodyData: Record<string, unknown>) => string;
1594
1226
  /**
1595
- * Hook called when a successful response (2xx status) is received from the API.
1596
- *
1597
- * This hook is triggered only for successful responses and provides access to
1598
- * the parsed response data. Ideal for success logging, caching, or post-processing
1599
- * of successful API responses.
1227
+ * Whether to clone the response so it can be read multiple times.
1600
1228
  *
1601
- * @param context - Success context with parsed response data and response object
1602
- * @returns Promise or void - Hook can be async or sync
1229
+ * By default, response streams can only be consumed once. Enable this when you need
1230
+ * to read the response in multiple places (e.g., in hooks and main code).
1603
1231
  *
1232
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/clone
1233
+ * @default false
1604
1234
  */
1605
- onSuccess?: (context: SuccessContext<TCallApiContext$1>) => Awaitable<unknown>;
1235
+ cloneResponse?: boolean;
1606
1236
  /**
1607
- * Hook called when a validation error occurs.
1237
+ * Custom fetch implementation to replace the default fetch function.
1608
1238
  *
1609
- * This hook is triggered when request or response data fails validation against
1610
- * a defined schema. It provides access to the validation error details and can
1611
- * be used for custom error handling, logging, or fallback behavior.
1239
+ * Useful for testing, adding custom behavior, or using alternative HTTP clients
1240
+ * that implement the fetch API interface.
1612
1241
  *
1613
- * @param context - Validation error context with error details and response (if available)
1614
- * @returns Promise or void - Hook can be async or sync
1242
+ * @example
1243
+ * ```ts
1244
+ * // Use node-fetch in Node.js environments
1245
+ * import fetch from 'node-fetch';
1246
+ *
1247
+ * // Mock fetch for testing
1248
+ * customFetchImpl: async (url, init) => {
1249
+ * return new Response(JSON.stringify({ mocked: true }), {
1250
+ * status: 200,
1251
+ * headers: { 'Content-Type': 'application/json' }
1252
+ * });
1253
+ * }
1254
+ *
1255
+ * // Add custom logging to all requests
1256
+ * customFetchImpl: async (url, init) => {
1257
+ * console.log(`Fetching: ${url}`);
1258
+ * const response = await fetch(url, init);
1259
+ * console.log(`Response: ${response.status}`);
1260
+ * return response;
1261
+ * }
1615
1262
  *
1263
+ * // Use with custom HTTP client
1264
+ * customFetchImpl: async (url, init) => {
1265
+ * // Convert to your preferred HTTP client format
1266
+ * return await customHttpClient.request({
1267
+ * url: url.toString(),
1268
+ * method: init?.method || 'GET',
1269
+ * headers: init?.headers,
1270
+ * body: init?.body
1271
+ * });
1272
+ * }
1273
+ * ```
1616
1274
  */
1617
- onValidationError?: (context: ValidationErrorContext<TCallApiContext$1>) => Awaitable<unknown>;
1618
- }
1619
- type HooksOrHooksArray<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = { [Key in keyof Hooks<TCallApiContext$1>]: Hooks<TCallApiContext$1>[Key] | Array<Hooks<TCallApiContext$1>[Key]> };
1620
- interface HookConfigOptions {
1275
+ customFetchImpl?: FetchImpl;
1621
1276
  /**
1622
- * Controls the execution mode of all composed hooks (main + plugin hooks).
1277
+ * Default HTTP error message when server doesn't provide one.
1623
1278
  *
1624
- * - **"parallel"**: All hooks execute simultaneously via Promise.all() for better performance
1625
- * - **"sequential"**: All hooks execute one by one in registration order via await in a loop
1279
+ * Can be a static string or a function that receives error context
1280
+ * to generate dynamic error messages based on the response.
1626
1281
  *
1627
- * This affects how ALL hooks execute together, regardless of their source (main or plugin).
1282
+ * @default "Failed to fetch data from server!"
1628
1283
  *
1629
- * @default "parallel"
1630
- */
1631
- hooksExecutionMode?: "parallel" | "sequential";
1632
- }
1633
- type RequestContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = {
1634
- /**
1635
- * Base configuration object passed to createFetchClient.
1284
+ * @example
1285
+ * ```ts
1286
+ * // Static error message
1287
+ * defaultHTTPErrorMessage: "API request failed. Please try again."
1636
1288
  *
1637
- * Contains the foundational configuration that applies to all requests
1638
- * made by this client instance, such as baseURL, default headers, and
1639
- * global options.
1289
+ * // Dynamic error message based on status code
1290
+ * defaultHTTPErrorMessage: ({ response }) => {
1291
+ * switch (response.status) {
1292
+ * case 401: return "Authentication required. Please log in.";
1293
+ * case 403: return "Access denied. Insufficient permissions.";
1294
+ * case 404: return "Resource not found.";
1295
+ * case 429: return "Too many requests. Please wait and try again.";
1296
+ * case 500: return "Server error. Please contact support.";
1297
+ * default: return `Request failed with status ${response.status}`;
1298
+ * }
1299
+ * }
1300
+ *
1301
+ * // Include error data in message
1302
+ * defaultHTTPErrorMessage: ({ errorData, response }) => {
1303
+ * const userMessage = errorData?.message || "Unknown error occurred";
1304
+ * return `${userMessage} (Status: ${response.status})`;
1305
+ * }
1306
+ * ```
1640
1307
  */
1641
- baseConfig: Exclude<BaseCallApiConfig, AnyFunction>;
1308
+ defaultHTTPErrorMessage?: string | ((context: Pick<HTTPError<TErrorData>, "errorData" | "response">) => string);
1642
1309
  /**
1643
- * Instance-specific configuration object passed to the callApi instance.
1310
+ * Forces calculation of total byte size from request/response body streams.
1311
+ *
1312
+ * Useful when the Content-Length header is missing or incorrect, and you need
1313
+ * accurate size information for progress tracking or bandwidth monitoring.
1314
+ *
1315
+ * @default false
1644
1316
  *
1645
- * Contains configuration specific to this particular API call, which
1646
- * can override or extend the base configuration.
1647
1317
  */
1648
- config: CallApiConfig;
1318
+ forcefullyCalculateStreamSize?: boolean | {
1319
+ request?: boolean;
1320
+ response?: boolean;
1321
+ };
1649
1322
  /**
1650
- * Merged options combining base config, instance config, and default options.
1323
+ * Optional metadata field for associating additional information with requests.
1651
1324
  *
1652
- * This is the final resolved configuration that will be used for the request,
1653
- * with proper precedence applied (instance > base > defaults).
1325
+ * Useful for logging, tracing, or handling specific cases in shared interceptors.
1326
+ * The meta object is passed through to all hooks and can be accessed in error handlers.
1327
+ *
1328
+ * @example
1329
+ * ```ts
1330
+ * const callMainApi = callApi.create({
1331
+ * baseURL: "https://main-api.com",
1332
+ * onResponseError: ({ response, options }) => {
1333
+ * if (options.meta?.userId) {
1334
+ * console.error(`User ${options.meta.userId} made an error`);
1335
+ * }
1336
+ * },
1337
+ * });
1338
+ *
1339
+ * const response = await callMainApi({
1340
+ * url: "https://example.com/api/data",
1341
+ * meta: { userId: "123" },
1342
+ * });
1343
+ *
1344
+ * // Use case: Request tracking
1345
+ * const result = await callMainApi({
1346
+ * url: "https://example.com/api/data",
1347
+ * meta: {
1348
+ * requestId: generateId(),
1349
+ * source: "user-dashboard",
1350
+ * priority: "high"
1351
+ * }
1352
+ * });
1353
+ *
1354
+ * // Use case: Feature flags
1355
+ * const client = callApi.create({
1356
+ * baseURL: "https://api.example.com",
1357
+ * meta: {
1358
+ * features: ["newUI", "betaFeature"],
1359
+ * experiment: "variantA"
1360
+ * }
1361
+ * });
1362
+ * ```
1654
1363
  */
1655
- options: CallApiExtraOptionsForHooks<TCallApiContext$1>;
1364
+ meta?: TCallApiContext["Meta"] extends DefaultMetaObject ? TCallApiContext["Meta"] : DefaultCallApiContext["Meta"];
1656
1365
  /**
1657
- * Merged request object ready to be sent.
1366
+ * Custom function to parse response strings into actual value instead of the default response.json().
1658
1367
  *
1659
- * Contains the final request configuration including URL, method, headers,
1660
- * body, and other fetch options. This object can be modified in onRequest
1661
- * hooks to customize the outgoing request.
1662
- */
1663
- request: CallApiRequestOptionsForHooks;
1664
- };
1665
- type ValidationErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1666
- error: PossibleValidationError;
1667
- response: Response | null;
1668
- }>;
1669
- type SuccessContext<TCallApiContext$1 extends Pick<CallApiContext, "Data" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1670
- data: NoInfer<TCallApiContext$1["Data"]>;
1671
- response: Response;
1672
- }>;
1673
- type ResponseContext<TCallApiContext$1 extends Pick<CallApiContext, "Data" | "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & (Prettify<CallApiResultSuccessVariant<TCallApiContext$1["Data"]>> | Prettify<Extract<CallApiResultErrorVariant<TCallApiContext$1["ErrorData"]>, {
1674
- error: PossibleHTTPError<TCallApiContext$1["ErrorData"]>;
1675
- }>>)>;
1676
- type RequestErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext$1> & {
1677
- error: PossibleJavaScriptError;
1678
- response: null;
1679
- };
1680
- type ErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & ({
1681
- error: PossibleHTTPError<TCallApiContext$1["ErrorData"]>;
1682
- response: Response;
1683
- } | {
1684
- error: PossibleJavaScriptOrValidationError;
1685
- response: Response | null;
1686
- })>;
1687
- type ResponseErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<Extract<ErrorContext<TCallApiContext$1>, {
1688
- error: PossibleHTTPError<TCallApiContext$1["ErrorData"]>;
1689
- }> & RequestContext<TCallApiContext$1>>;
1690
- type RetryContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<ErrorContext<TCallApiContext$1> & {
1691
- retryAttemptCount: number;
1692
- }>;
1693
- type RequestStreamContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1694
- event: StreamProgressEvent;
1695
- requestInstance: Request;
1696
- }>;
1697
- type ResponseStreamContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1698
- event: StreamProgressEvent;
1699
- response: Response;
1700
- }>;
1701
- //#endregion
1702
- //#region src/plugins.d.ts
1703
- type PluginSetupContext<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = RequestContext<TCallApiContext$1> & {
1704
- initURL: string;
1705
- };
1706
- type PluginInitResult<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = Partial<Omit<PluginSetupContext<TCallApiContext$1>, "initURL" | "request"> & {
1707
- initURL: InitURLOrURLObject;
1708
- request: CallApiRequestOptions;
1709
- }>;
1710
- type PluginHooks<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = HooksOrHooksArray<GetMergedCallApiContext<TCallApiContext$1, {
1711
- Data: DefaultDataType extends TCallApiContext$1["Data"] ? never : TCallApiContext$1["Data"];
1712
- ErrorData: DefaultDataType extends TCallApiContext$1["ErrorData"] ? never : TCallApiContext$1["ErrorData"];
1713
- }>>;
1714
- interface CallApiPlugin<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> {
1715
- /**
1716
- * Defines additional options that can be passed to callApi
1717
- */
1718
- defineExtraOptions?: (...params: never[]) => unknown;
1719
- /**
1720
- * A description for the plugin
1721
- */
1722
- description?: string;
1723
- /**
1724
- * Hooks for the plugin
1725
- */
1726
- hooks?: PluginHooks<TCallApiContext$1> | ((context: PluginSetupContext<TCallApiContext$1>) => Awaitable<PluginHooks<TCallApiContext$1>>);
1727
- /**
1728
- * A unique id for the plugin
1729
- */
1730
- id: string;
1731
- /**
1732
- * Middlewares that for the plugin
1368
+ * Useful when you need custom parsing logic for specific response formats.
1369
+ *
1370
+ * @example
1371
+ * ```ts
1372
+ * responseParser: (responseString) => {
1373
+ * return JSON.parse(responseString);
1374
+ * }
1375
+ *
1376
+ * // Parse XML responses
1377
+ * responseParser: (responseString) => {
1378
+ * const parser = new DOMParser();
1379
+ * const doc = parser.parseFromString(responseString, "text/xml");
1380
+ * return xmlToObject(doc);
1381
+ * }
1382
+ *
1383
+ * // Parse CSV responses
1384
+ * responseParser: (responseString) => {
1385
+ * const lines = responseString.split('\n');
1386
+ * const headers = lines[0].split(',');
1387
+ * const data = lines.slice(1).map(line => {
1388
+ * const values = line.split(',');
1389
+ * return headers.reduce((obj, header, index) => {
1390
+ * obj[header] = values[index];
1391
+ * return obj;
1392
+ * }, {});
1393
+ * });
1394
+ * return data;
1395
+ * }
1396
+ *
1397
+ * ```
1733
1398
  */
1734
- middlewares?: Middlewares<TCallApiContext$1> | ((context: PluginSetupContext<TCallApiContext$1>) => Awaitable<Middlewares<TCallApiContext$1>>);
1399
+ responseParser?: (responseString: string) => Awaitable<TData>;
1735
1400
  /**
1736
- * A name for the plugin
1401
+ * Expected response type, determines how the response body is parsed.
1402
+ *
1403
+ * Different response types trigger different parsing methods:
1404
+ * - **"json"**: Parses as JSON using response.json()
1405
+ * - **"text"**: Returns as plain text using response.text()
1406
+ * - **"blob"**: Returns as Blob using response.blob()
1407
+ * - **"arrayBuffer"**: Returns as ArrayBuffer using response.arrayBuffer()
1408
+ * - **"stream"**: Returns the response body stream directly
1409
+ *
1410
+ * @default "json"
1411
+ *
1412
+ * @example
1413
+ * ```ts
1414
+ * // JSON API responses (default)
1415
+ * responseType: "json"
1416
+ *
1417
+ * // Plain text responses
1418
+ * responseType: "text"
1419
+ * // Usage: const csvData = await callApi("/export.csv", { responseType: "text" });
1420
+ *
1421
+ * // File downloads
1422
+ * responseType: "blob"
1423
+ * // Usage: const file = await callApi("/download/file.pdf", { responseType: "blob" });
1424
+ *
1425
+ * // Binary data
1426
+ * responseType: "arrayBuffer"
1427
+ * // Usage: const buffer = await callApi("/binary-data", { responseType: "arrayBuffer" });
1428
+ *
1429
+ * // Streaming responses
1430
+ * responseType: "stream"
1431
+ * // Usage: const stream = await callApi("/large-dataset", { responseType: "stream" });
1432
+ * ```
1737
1433
  */
1738
- name: string;
1434
+ responseType?: TResponseType;
1739
1435
  /**
1740
- * Base schema for the client.
1436
+ * Controls what data is included in the returned result object.
1437
+ *
1438
+ * Different modes return different combinations of data, error, and response:
1439
+ * - **"all"**: Returns { data, error, response } - complete result information
1440
+ * - **"onlyData"**: Returns only data (null for errors)
1441
+ *
1442
+ * When combined with throwOnError: true, null/error variants are automatically removed:
1443
+ * - **"all" + throwOnError: true**: Returns { data, error: null, response } (error property is null, throws instead)
1444
+ * - **"onlyData" + throwOnError: true**: Returns data (never null, throws on error)
1445
+ *
1446
+ * @default "all"
1447
+ *
1448
+ * @example
1449
+ * ```ts
1450
+ * // Complete result with all information (default)
1451
+ * const { data, error, response } = await callApi("/users", { resultMode: "all" });
1452
+ * if (error) {
1453
+ * console.error("Request failed:", error);
1454
+ * } else {
1455
+ * console.log("Users:", data);
1456
+ * }
1457
+ *
1458
+ * // Complete result but throws on errors (throwOnError removes error from type)
1459
+ * try {
1460
+ * const { data, response } = await callApi("/users", {
1461
+ * resultMode: "all",
1462
+ * throwOnError: true
1463
+ * });
1464
+ * console.log("Users:", data); // data is never null here
1465
+ * } catch (error) {
1466
+ * console.error("Request failed:", error);
1467
+ * }
1468
+ *
1469
+ * // Only data, returns null on errors
1470
+ * const users = await callApi("/users", { resultMode: "onlyData" });
1471
+ * if (users) {
1472
+ * console.log("Users:", users);
1473
+ * } else {
1474
+ * console.log("Request failed");
1475
+ * }
1476
+ *
1477
+ * // Only data, throws on errors (throwOnError removes null from type)
1478
+ * try {
1479
+ * const users = await callApi("/users", {
1480
+ * resultMode: "onlyData",
1481
+ * throwOnError: true
1482
+ * });
1483
+ * console.log("Users:", users); // users is never null here
1484
+ * } catch (error) {
1485
+ * console.error("Request failed:", error);
1486
+ * }
1487
+ * ```
1741
1488
  */
1742
- schema?: BaseCallApiSchemaAndConfig;
1489
+ resultMode?: TResultMode;
1743
1490
  /**
1744
- * A function that will be called when the plugin is initialized. This will be called before the any of the other internal functions.
1491
+ * Controls whether errors are thrown as exceptions or returned in the result.
1492
+ *
1493
+ * Can be a boolean or a function that receives the error and decides whether to throw.
1494
+ * When true, errors are thrown as exceptions instead of being returned in the result object.
1495
+ *
1496
+ * @default false
1497
+ *
1498
+ * @example
1499
+ * ```ts
1500
+ * // Always throw errors
1501
+ * throwOnError: true
1502
+ * try {
1503
+ * const data = await callApi("/users");
1504
+ * console.log("Users:", data);
1505
+ * } catch (error) {
1506
+ * console.error("Request failed:", error);
1507
+ * }
1508
+ *
1509
+ * // Never throw errors (default)
1510
+ * throwOnError: false
1511
+ * const { data, error } = await callApi("/users");
1512
+ * if (error) {
1513
+ * console.error("Request failed:", error);
1514
+ * }
1515
+ *
1516
+ * // Conditionally throw based on error type
1517
+ * throwOnError: (error) => {
1518
+ * // Throw on client errors (4xx) but not server errors (5xx)
1519
+ * return error.response?.status >= 400 && error.response?.status < 500;
1520
+ * }
1521
+ *
1522
+ * // Throw only on specific status codes
1523
+ * throwOnError: (error) => {
1524
+ * const criticalErrors = [401, 403, 404];
1525
+ * return criticalErrors.includes(error.response?.status);
1526
+ * }
1527
+ *
1528
+ * // Throw on validation errors but not network errors
1529
+ * throwOnError: (error) => {
1530
+ * return error.type === "validation";
1531
+ * }
1532
+ * ```
1745
1533
  */
1746
- setup?: (context: PluginSetupContext<TCallApiContext$1>) => Awaitable<PluginInitResult<TCallApiContext$1>> | Awaitable<void>;
1534
+ throwOnError?: ThrowOnErrorType<TErrorData, TThrowOnError>;
1747
1535
  /**
1748
- * A version for the plugin
1536
+ * Request timeout in milliseconds. Request will be aborted if it takes longer.
1537
+ *
1538
+ * Useful for preventing requests from hanging indefinitely and providing
1539
+ * better user experience with predictable response times.
1540
+ *
1541
+ * @example
1542
+ * ```ts
1543
+ * // 5 second timeout
1544
+ * timeout: 5000
1545
+ *
1546
+ * // Different timeouts for different endpoints
1547
+ * const quickApi = createFetchClient({ timeout: 3000 }); // 3s for fast endpoints
1548
+ * const slowApi = createFetchClient({ timeout: 30000 }); // 30s for slow operations
1549
+ *
1550
+ * // Per-request timeout override
1551
+ * await callApi("/quick-data", { timeout: 1000 });
1552
+ * await callApi("/slow-report", { timeout: 60000 });
1553
+ *
1554
+ * // No timeout (use with caution)
1555
+ * timeout: 0
1556
+ * ```
1749
1557
  */
1750
- version?: string;
1751
- }
1752
- //#endregion
1753
- //#region src/types/default-types.d.ts
1754
- type DefaultDataType = unknown;
1755
- type DefaultPluginArray = CallApiPlugin[];
1756
- type DefaultThrowOnError = boolean;
1757
- type DefaultMetaObject = Record<string, unknown>;
1758
- type DefaultCallApiContext = Omit<Required<CallApiContext>, "Meta"> & {
1759
- Meta: GlobalMeta;
1558
+ timeout?: number;
1760
1559
  };
1761
- //#endregion
1762
- //#region src/validation.d.ts
1763
- type ResultVariant = "infer-input" | "infer-output";
1764
- type InferSchemaResult<TSchema$1, TFallbackResult, TResultVariant extends ResultVariant> = undefined extends TSchema$1 ? TFallbackResult : TSchema$1 extends StandardSchemaV1 ? TResultVariant extends "infer-input" ? StandardSchemaV1.InferInput<TSchema$1> : StandardSchemaV1.InferOutput<TSchema$1> : TSchema$1 extends AnyFunction<infer TResult> ? Awaited<TResult> : TFallbackResult;
1765
- type InferSchemaOutput<TSchema$1, TFallbackResult = unknown> = InferSchemaResult<TSchema$1, TFallbackResult, "infer-output">;
1766
- type InferSchemaInput<TSchema$1, TFallbackResult = unknown> = InferSchemaResult<TSchema$1, TFallbackResult, "infer-input">;
1767
- interface CallApiSchemaConfig {
1768
- /**
1769
- * The base url of the schema. By default it's the baseURL of the callApi instance.
1770
- */
1771
- baseURL?: string;
1772
- /**
1773
- * Disables runtime validation for the schema.
1774
- */
1775
- disableRuntimeValidation?: boolean;
1560
+ type BaseCallApiExtraOptions<TBaseCallApiContext extends CallApiContext = DefaultCallApiContext, TBaseData = DefaultDataType, TBaseErrorData = DefaultDataType, TBaseResultMode extends ResultModeType = ResultModeType, TBaseThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TBaseResponseType extends ResponseTypeType = ResponseTypeType, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig> = SharedExtraOptions<TBaseCallApiContext, TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBasePluginArray> & {
1776
1561
  /**
1777
- * If `true`, the original input value will be used instead of the transformed/validated output.
1562
+ * Array of base CallApi plugins to extend library functionality.
1778
1563
  *
1779
- * This is useful when you want to validate the input but don't want any transformations
1780
- * applied by the validation schema (e.g., type coercion, default values, etc).
1781
- */
1782
- disableValidationOutputApplication?: boolean;
1783
- /**
1784
- * Optional url prefix that will be substituted for the `baseURL` of the schemaConfig at runtime.
1564
+ * Base plugins are applied to all instances created from this base configuration
1565
+ * and provide foundational functionality like authentication, logging, or caching.
1785
1566
  *
1786
- * This allows you to reuse the same schema against different base URLs (for example,
1787
- * swapping between `/api/v1` and `/api/v2`) without redefining the entire schema.
1788
- */
1789
- prefix?: string;
1790
- /**
1791
- * Controls the strictness of API route validation.
1567
+ * @example
1568
+ * ```ts
1569
+ * // Add logging plugin
1792
1570
  *
1793
- * When true:
1794
- * - Only routes explicitly defined in the schema will be considered valid to typescript and the runtime.
1795
- * - Attempting to call routes not defined in the schema will result in both type errors and runtime validation errors.
1796
- * - Useful for ensuring API calls conform exactly to your schema definition
1571
+ * // Create base client with common plugins
1572
+ * const callApi = createFetchClient({
1573
+ * baseURL: "https://api.example.com",
1574
+ * plugins: [loggerPlugin({ enabled: true })]
1575
+ * });
1797
1576
  *
1798
- * When false or undefined (default):
1799
- * - All routes will be allowed, whether they are defined in the schema or not
1800
- */
1801
- strict?: boolean;
1802
- }
1803
- interface CallApiSchema {
1804
- /**
1805
- * The schema to use for validating the request body.
1806
- */
1807
- body?: StandardSchemaV1<Body | undefined> | ((body: Body) => Awaitable<Body | undefined>);
1808
- /**
1809
- * The schema to use for validating the response data.
1810
- */
1811
- data?: StandardSchemaV1 | ((data: unknown) => unknown);
1812
- /**
1813
- * The schema to use for validating the response error data.
1577
+ * // All requests inherit base plugins
1578
+ * await callApi("/users");
1579
+ * await callApi("/posts");
1580
+ *
1581
+ * ```
1814
1582
  */
1815
- errorData?: StandardSchemaV1 | ((errorData: unknown) => unknown);
1583
+ plugins?: TBasePluginArray;
1816
1584
  /**
1817
- * The schema to use for validating the request headers.
1585
+ * Base validation schemas for the client configuration.
1586
+ *
1587
+ * Defines validation rules for requests and responses that apply to all
1588
+ * instances created from this base configuration. Provides type safety
1589
+ * and runtime validation for API interactions.
1818
1590
  */
1819
- headers?: StandardSchemaV1<HeadersOption | undefined> | ((headers: HeadersOption) => Awaitable<HeadersOption | undefined>);
1591
+ schema?: TBaseSchemaAndConfig;
1820
1592
  /**
1821
- * The schema to use for validating the meta option.
1593
+ * Controls which configuration parts skip automatic merging between base and instance configs.
1594
+ *
1595
+ * By default, CallApi automatically merges base configuration with instance configuration.
1596
+ * This option allows you to disable automatic merging for specific parts when you need
1597
+ * manual control over how configurations are combined.
1598
+ *
1599
+ * @enum
1600
+ * - **"all"**: Disables automatic merging for both request options and extra options
1601
+ * - **"options"**: Disables automatic merging of extra options only (hooks, plugins, etc.)
1602
+ * - **"request"**: Disables automatic merging of request options only (headers, body, etc.)
1603
+ *
1604
+ * @example
1605
+ * ```ts
1606
+ * // Skip all automatic merging - full manual control
1607
+ * const client = callApi.create((ctx) => ({
1608
+ * skipAutoMergeFor: "all",
1609
+ *
1610
+ * // Manually decide what to merge
1611
+ * baseURL: ctx.options.baseURL, // Keep base URL
1612
+ * timeout: 5000, // Override timeout
1613
+ * headers: {
1614
+ * ...ctx.request.headers, // Merge headers manually
1615
+ * "X-Custom": "value" // Add custom header
1616
+ * }
1617
+ * }));
1618
+ *
1619
+ * // Skip options merging - manual plugin/hook control
1620
+ * const client = callApi.create((ctx) => ({
1621
+ * skipAutoMergeFor: "options",
1622
+ *
1623
+ * // Manually control which plugins to use
1624
+ * plugins: [
1625
+ * ...ctx.options.plugins?.filter(p => p.name !== "unwanted") || [],
1626
+ * customPlugin
1627
+ * ],
1628
+ *
1629
+ * // Request options still auto-merge
1630
+ * method: "POST"
1631
+ * }));
1632
+ *
1633
+ * // Skip request merging - manual request control
1634
+ * const client = callApi.create((ctx) => ({
1635
+ * skipAutoMergeFor: "request",
1636
+ *
1637
+ * // Extra options still auto-merge (plugins, hooks, etc.)
1638
+ *
1639
+ * // Manually control request options
1640
+ * headers: {
1641
+ * "Content-Type": "application/json",
1642
+ * // Don't merge base headers
1643
+ * },
1644
+ * method: ctx.request.method || "GET"
1645
+ * }));
1646
+ *
1647
+ * // Use case: Conditional merging based on request
1648
+ * const client = createFetchClient((ctx) => ({
1649
+ * skipAutoMergeFor: "options",
1650
+ *
1651
+ * // Only use auth plugin for protected routes
1652
+ * plugins: ctx.initURL.includes("/protected/")
1653
+ * ? [...(ctx.options.plugins || []), authPlugin]
1654
+ * : ctx.options.plugins?.filter(p => p.name !== "auth") || []
1655
+ * }));
1656
+ * ```
1822
1657
  */
1823
- meta?: StandardSchemaV1<GlobalMeta | undefined> | ((meta: GlobalMeta) => Awaitable<GlobalMeta | undefined>);
1658
+ skipAutoMergeFor?: "all" | "options" | "request";
1659
+ };
1660
+ type GetBaseSchemaRoutes<TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig> = Writeable<TBaseSchemaAndConfig["routes"], "deep">;
1661
+ type GetBaseSchemaConfig<TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig> = Writeable<NonNullable<TBaseSchemaAndConfig["config"]>, "deep">;
1662
+ type InferExtendSchemaContext<TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey extends string> = {
1663
+ baseSchemaRoutes: TBaseSchemaRoutes;
1664
+ currentRouteSchema: GetCurrentRouteSchema<TBaseSchemaRoutes, TCurrentRouteSchemaKey>;
1665
+ };
1666
+ type GetExtendSchemaConfigContext<TBaseSchemaConfig extends CallApiSchemaConfig> = {
1667
+ baseSchemaConfig: TBaseSchemaConfig;
1668
+ };
1669
+ type InferExtendPluginContext<TBasePluginArray extends CallApiPlugin[]> = {
1670
+ basePlugins: TBasePluginArray;
1671
+ };
1672
+ type CallApiExtraOptions<TCallApiContext extends CallApiContext = DefaultCallApiContext, TData = DefaultDataType, TErrorData = DefaultDataType, TResultMode extends ResultModeType = ResultModeType, TThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType extends ResponseTypeType = ResponseTypeType, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TPluginArray extends CallApiPlugin[] = DefaultPluginArray, TBaseSchemaRoutes extends BaseCallApiSchemaRoutes = BaseCallApiSchemaRoutes, TSchema extends CallApiSchema = CallApiSchema, TBaseSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TCurrentRouteSchemaKey extends string = string, TComputedPluginContext = InferExtendPluginContext<TBasePluginArray>, TComputedSchemaContext = InferExtendSchemaContext<TBaseSchemaRoutes, TCurrentRouteSchemaKey>, TComputedSchemaConfigContext = GetExtendSchemaConfigContext<TBaseSchemaConfig>> = SharedExtraOptions<TCallApiContext, TData, TErrorData, TResultMode, TThrowOnError, TResponseType, TPluginArray> & {
1824
1673
  /**
1825
- * The schema to use for validating the request method.
1674
+ * Array of instance-specific CallApi plugins or a function to configure plugins.
1675
+ *
1676
+ * Instance plugins are added to the base plugins and provide functionality
1677
+ * specific to this particular API instance. Can be a static array or a function
1678
+ * that receives base plugins and returns the instance plugins.
1679
+ *
1826
1680
  */
1827
- method?: StandardSchemaV1<MethodUnion | undefined> | ((method: MethodUnion) => Awaitable<MethodUnion | undefined>);
1681
+ plugins?: TPluginArray | ((context: TComputedPluginContext) => TPluginArray);
1828
1682
  /**
1829
- * The schema to use for validating the request url parameters.
1683
+ * For instance-specific validation schemas
1684
+ *
1685
+ * Defines validation rules specific to this API instance, extending or overriding the base schema.
1686
+ *
1687
+ * Can be a static schema object or a function that receives base schema context and returns instance schemas.
1688
+ *
1830
1689
  */
1831
- params?: StandardSchemaV1<Params | undefined> | ((params: Params) => Awaitable<Params | undefined>);
1690
+ schema?: TSchema | ((context: TComputedSchemaContext) => TSchema);
1832
1691
  /**
1833
- * The schema to use for validating the request url queries.
1692
+ * Instance-specific schema configuration or a function to configure schema behavior.
1693
+ *
1694
+ * Controls how validation schemas are applied and behave for this specific API instance.
1695
+ * Can override base schema configuration or extend it with instance-specific validation rules.
1696
+ *
1834
1697
  */
1835
- query?: StandardSchemaV1<Query | undefined> | ((query: Query) => Awaitable<Query | undefined>);
1836
- }
1837
- declare const routeKeyMethods: readonly ["delete", "get", "patch", "post", "put"];
1838
- type RouteKeyMethods = (typeof routeKeyMethods)[number];
1839
- type RouteKeyMethodsURLUnion = `@${RouteKeyMethods}/`;
1840
- type BaseSchemaRouteKeyPrefixes = FallBackRouteSchemaKey | RouteKeyMethodsURLUnion;
1841
- type BaseCallApiSchemaRoutes = Partial<Record<AnyString | BaseSchemaRouteKeyPrefixes, CallApiSchema>>;
1842
- type BaseCallApiSchemaAndConfig = {
1843
- config?: CallApiSchemaConfig;
1844
- routes: BaseCallApiSchemaRoutes;
1698
+ schemaConfig?: TSchemaConfig | ((context: TComputedSchemaConfigContext) => TSchemaConfig);
1845
1699
  };
1700
+ type CallApiExtraOptionsForHooks<TCallApiContext extends CallApiContext = DefaultCallApiContext> = Hooks & Omit<CallApiExtraOptions<TCallApiContext>, keyof Hooks>;
1701
+ type InstanceContext = {
1702
+ initURL: string;
1703
+ options: CallApiExtraOptions;
1704
+ request: CallApiRequestOptions;
1705
+ };
1706
+ type BaseCallApiConfig<TBaseCallApiContext extends CallApiContext = DefaultCallApiContext, TBaseData = DefaultDataType, TBaseErrorData = DefaultDataType, TBaseResultMode extends ResultModeType = ResultModeType, TBaseThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TBaseResponseType extends ResponseTypeType = ResponseTypeType, TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedBaseConfig = BaseCallApiExtraOptions<TBaseCallApiContext, TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBasePluginArray, TBaseSchemaAndConfig>> = (CallApiRequestOptions & TComputedBaseConfig) | ((context: InstanceContext) => CallApiRequestOptions & TComputedBaseConfig);
1707
+ type CallApiConfig<TCallApiContext extends CallApiContext = DefaultCallApiContext, TData = DefaultDataType, TErrorData = DefaultDataType, TResultMode extends ResultModeType = ResultModeType, TThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType extends ResponseTypeType = ResponseTypeType, 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, TCallApiContext> & InferRequestOptions<TSchema, TInitURL> & Omit<CallApiExtraOptions<TCallApiContext, TData, TErrorData, TResultMode, TThrowOnError, TResponseType, TBasePluginArray, TPluginArray, TBaseSchemaRoutes, TSchema, TBaseSchemaConfig, TSchemaConfig, TCurrentRouteSchemaKey>, keyof InferExtraOptions<CallApiSchema, BaseCallApiSchemaRoutes, string, CallApiContext>> & Omit<CallApiRequestOptions, keyof InferRequestOptions<CallApiSchema, string>>;
1708
+ type CallApiParameters<TData = DefaultDataType, TErrorData = DefaultDataType, TResultMode extends ResultModeType = ResultModeType, TCallApiContext extends CallApiContext = DefaultCallApiContext, TThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TResponseType extends ResponseTypeType = ResponseTypeType, 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<TCallApiContext, TData, TErrorData, TResultMode, TThrowOnError, TResponseType, TBaseSchemaRoutes, TSchema, TBaseSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, TBasePluginArray, TPluginArray>];
1709
+ type CallApiResult<TData, TErrorData, TResultMode extends ResultModeType, TThrowOnError extends ThrowOnErrorUnion> = InferCallApiResult<TData, TErrorData, TResultMode, TThrowOnError>;
1710
+ type CallApiResultLoose<TData, TErrorData, TResultMode extends ResultModeType = ResultModeType, TThrowOnError extends ThrowOnErrorUnion = ThrowOnErrorUnion> = InferCallApiResult<TData, TErrorData, TResultMode, TThrowOnError>;
1711
+ //#endregion
1712
+ //#region src/result.d.ts
1713
+ type Parser<TData> = (responseString: string) => Awaitable<TData>;
1714
+ declare const getResponseType: <TResponse>(response: Response, parser: Parser<TResponse>) => {
1715
+ arrayBuffer: () => Promise<ArrayBuffer>;
1716
+ blob: () => Promise<Blob>;
1717
+ formData: () => Promise<FormData>;
1718
+ json: () => Promise<TResponse>;
1719
+ stream: () => ReadableStream<Uint8Array<ArrayBuffer>> | null;
1720
+ text: () => Promise<string>;
1721
+ };
1722
+ type InitResponseTypeMap<TResponse = unknown> = ReturnType<typeof getResponseType<TResponse>>;
1723
+ type ResponseTypeUnion = keyof InitResponseTypeMap;
1724
+ type ResponseTypePlaceholder = null;
1725
+ type ResponseTypeType = ResponseTypePlaceholder | ResponseTypeUnion;
1726
+ type ResponseTypeMap<TResponse> = { [Key in keyof InitResponseTypeMap<TResponse>]: Awaited<ReturnType<InitResponseTypeMap<TResponse>[Key]>> };
1727
+ type GetResponseType<TResponse, TResponseType extends ResponseTypeType, TComputedResponseTypeMap extends ResponseTypeMap<TResponse> = ResponseTypeMap<TResponse>> = null extends TResponseType ? TComputedResponseTypeMap["json"] : TResponseType extends NonNullable<ResponseTypeType> ? TComputedResponseTypeMap[TResponseType] : never;
1728
+ type CallApiResultSuccessVariant<TData> = {
1729
+ data: NoInfer<TData>;
1730
+ error: null;
1731
+ response: Response;
1732
+ };
1733
+ type PossibleJavaScriptError = UnmaskType<{
1734
+ errorData: false;
1735
+ message: string;
1736
+ name: "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | AnyString;
1737
+ originalError: DOMException | Error | SyntaxError | TypeError;
1738
+ }>;
1739
+ type PossibleHTTPError<TErrorData> = UnmaskType<{
1740
+ errorData: NoInfer<TErrorData>;
1741
+ message: string;
1742
+ name: "HTTPError";
1743
+ originalError: HTTPError;
1744
+ }>;
1745
+ type PossibleValidationError = UnmaskType<{
1746
+ errorData: ValidationError["errorData"];
1747
+ issueCause: ValidationError["issueCause"];
1748
+ message: string;
1749
+ name: "ValidationError";
1750
+ originalError: ValidationError;
1751
+ }>;
1752
+ type PossibleJavaScriptOrValidationError = UnmaskType<PossibleJavaScriptError | PossibleValidationError>;
1753
+ type CallApiResultErrorVariant<TErrorData> = {
1754
+ data: null;
1755
+ error: PossibleHTTPError<TErrorData>;
1756
+ response: Response;
1757
+ } | {
1758
+ data: null;
1759
+ error: PossibleJavaScriptOrValidationError;
1760
+ response: Response | null;
1761
+ };
1762
+ type CallApiSuccessOrErrorVariant<TData, TError> = CallApiResultErrorVariant<TError> | CallApiResultSuccessVariant<TData>;
1763
+ type ResultModeMapWithoutException<TData, TErrorData, TComputedResult extends CallApiSuccessOrErrorVariant<TData, TErrorData> = CallApiSuccessOrErrorVariant<TData, TErrorData>> = UnmaskType<{
1764
+ all: TComputedResult;
1765
+ onlyData: TComputedResult["data"];
1766
+ onlyResponse: TComputedResult["response"];
1767
+ withoutResponse: DistributiveOmit<TComputedResult, "response">;
1768
+ }>;
1769
+ type ResultModeMapWithException<TData, TComputedResult extends CallApiResultSuccessVariant<TData> = CallApiResultSuccessVariant<TData>> = {
1770
+ all: TComputedResult;
1771
+ onlyData: TComputedResult["data"];
1772
+ onlyResponse: TComputedResult["response"];
1773
+ withoutResponse: DistributiveOmit<TComputedResult, "response">;
1774
+ };
1775
+ type ResultModeMap<TData = DefaultDataType, TErrorData = DefaultDataType, TThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError> = TThrowOnError extends true ? ResultModeMapWithException<TData> : ResultModeMapWithoutException<TData, TErrorData>;
1776
+ type ResultModePlaceholder = null;
1777
+ type ResultModeUnion = keyof ResultModeMap;
1778
+ type ResultModeType = ResultModePlaceholder | ResultModeUnion;
1779
+ type InferCallApiResult<TData, TErrorData, TResultMode extends ResultModeType, TThrowOnError extends ThrowOnErrorUnion, TComputedResultModeMapWithException extends ResultModeMapWithException<TData> = ResultModeMapWithException<TData>, TComputedResultModeMap extends ResultModeMap<TData, TErrorData, TThrowOnError> = ResultModeMap<TData, TErrorData, TThrowOnError>> = TErrorData extends false ? TComputedResultModeMapWithException["onlyData"] : TErrorData extends false | undefined ? TComputedResultModeMapWithException["onlyData"] : ResultModePlaceholder extends TResultMode ? TComputedResultModeMap["all"] : TResultMode extends ResultModeUnion ? TComputedResultModeMap[TResultMode] : never;
1846
1780
  //#endregion
1847
1781
  //#region src/createFetchClient.d.ts
1848
- declare const createFetchClientWithContext: <TOuterCallApiContext extends CallApiContext = DefaultCallApiContext>() => <TBaseCallApiContext extends CallApiContext = TOuterCallApiContext, TBaseData = TBaseCallApiContext["Data"], TBaseErrorData = TBaseCallApiContext["ErrorData"], TBaseResultMode extends ResultModeType = (TBaseCallApiContext["ResultMode"] extends ResultModeType ? TBaseCallApiContext["ResultMode"] : ResultModeType), TBaseThrowOnError extends ThrowOnErrorUnion = boolean, TBaseResponseType extends ResponseTypeType = ResponseTypeType, const TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig, const TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedBaseCallApiContext extends CallApiContext = GetMergedCallApiContext<TBaseCallApiContext, {
1849
- Data: TBaseData;
1850
- ErrorData: TBaseErrorData;
1851
- ResultMode: TBaseResultMode;
1852
- }>, TComputedBaseSchemaConfig extends CallApiSchemaConfig = GetBaseSchemaConfig<TBaseSchemaAndConfig>, TComputedBaseSchemaRoutes extends BaseCallApiSchemaRoutes = GetBaseSchemaRoutes<TBaseSchemaAndConfig>>(initBaseConfig?: BaseCallApiConfig<TBaseCallApiContext, TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBaseSchemaAndConfig, TBasePluginArray>) => <TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeType = TBaseResultMode, TCallApiContext extends CallApiContext = GetMergedCallApiContext<TComputedBaseCallApiContext, {
1853
- Data: TData;
1854
- ErrorData: TErrorData;
1855
- ResultMode: TResultMode;
1856
- }>, TThrowOnError extends ThrowOnErrorUnion = TBaseThrowOnError, TResponseType extends ResponseTypeType = TBaseResponseType, const TSchemaConfig extends CallApiSchemaConfig = TComputedBaseSchemaConfig, TInitURL extends InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig> = InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig>, TCurrentRouteSchemaKey extends GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL> = GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL>, const TSchema extends CallApiSchema = GetCurrentRouteSchema<TComputedBaseSchemaRoutes, TCurrentRouteSchemaKey>, const TPluginArray extends CallApiPlugin[] = TBasePluginArray, TComputedResult = CallApiResult<InferSchemaOutput<TSchema["data"], TData>, InferSchemaOutput<TSchema["errorData"], TErrorData>, TResultMode, TThrowOnError, TResponseType>>(initURL: TInitURL, initConfig?: CallApiConfig<TCallApiContext, InferSchemaOutput<TSchema["data"], GetResponseType<TData, TResponseType>>, InferSchemaOutput<TSchema["errorData"], GetResponseType<TErrorData, TResponseType>>, TResultMode, TThrowOnError, TResponseType, TComputedBaseSchemaRoutes, TSchema, TComputedBaseSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, TBasePluginArray, TPluginArray>) => Promise<TComputedResult>;
1857
- declare const createFetchClient: <TBaseCallApiContext extends CallApiContext = DefaultCallApiContext, TBaseData = TBaseCallApiContext["Data"], TBaseErrorData = TBaseCallApiContext["ErrorData"], TBaseResultMode extends ResultModeType = (TBaseCallApiContext["ResultMode"] extends ResultModeType ? TBaseCallApiContext["ResultMode"] : ResultModeType), TBaseThrowOnError extends ThrowOnErrorUnion = boolean, TBaseResponseType extends ResponseTypeType = ResponseTypeType, const TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig, const TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedBaseCallApiContext extends CallApiContext = GetMergedCallApiContext<TBaseCallApiContext, {
1858
- Data: TBaseData;
1859
- ErrorData: TBaseErrorData;
1860
- ResultMode: TBaseResultMode;
1861
- }>, TComputedBaseSchemaConfig extends CallApiSchemaConfig = Writeable<NonNullable<TBaseSchemaAndConfig["config"]>, "deep">, TComputedBaseSchemaRoutes extends BaseCallApiSchemaRoutes = Writeable<TBaseSchemaAndConfig["routes"], "deep">>(initBaseConfig?: BaseCallApiConfig<TBaseCallApiContext, TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBaseSchemaAndConfig, TBasePluginArray>) => <TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeType = TBaseResultMode, TCallApiContext extends CallApiContext = GetMergedCallApiContext<TComputedBaseCallApiContext, {
1862
- Data: TData;
1863
- ErrorData: TErrorData;
1864
- ResultMode: TResultMode;
1865
- }>, TThrowOnError extends ThrowOnErrorUnion = TBaseThrowOnError, TResponseType extends ResponseTypeType = TBaseResponseType, const TSchemaConfig extends CallApiSchemaConfig = TComputedBaseSchemaConfig, TInitURL extends InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig> = InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig>, TCurrentRouteSchemaKey extends GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL> = GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL>, const TSchema extends CallApiSchema = GetCurrentRouteSchema<TComputedBaseSchemaRoutes, TCurrentRouteSchemaKey, TComputedBaseSchemaRoutes["@default"], TComputedBaseSchemaRoutes[TCurrentRouteSchemaKey], NonNullable<Omit<TComputedBaseSchemaRoutes["@default"], keyof TComputedBaseSchemaRoutes[TCurrentRouteSchemaKey]> & TComputedBaseSchemaRoutes[TCurrentRouteSchemaKey]>>, const TPluginArray extends CallApiPlugin[] = TBasePluginArray, TComputedResult = GetCallApiResult<InferSchemaResult<TSchema["data"], TData, "infer-output">, InferSchemaResult<TSchema["errorData"], TErrorData, "infer-output">, TResultMode, TThrowOnError, TResponseType, {
1866
- all: CallApiResultSuccessVariant<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>;
1867
- onlyData: NoInfer<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>;
1782
+ declare const createFetchClientWithContext: <TOuterCallApiContext extends CallApiContext = DefaultCallApiContext>() => <TBaseCallApiContext extends CallApiContext = TOuterCallApiContext, TBaseData = TBaseCallApiContext["Data"], TBaseErrorData = TBaseCallApiContext["ErrorData"], TBaseResultMode extends ResultModeType = (TBaseCallApiContext["ResultMode"] extends ResultModeType ? TBaseCallApiContext["ResultMode"] : ResultModeType), TBaseThrowOnError extends ThrowOnErrorUnion = boolean, TBaseResponseType extends ResponseTypeType = ResponseTypeType, const TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig, const TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedBaseSchemaConfig extends CallApiSchemaConfig = GetBaseSchemaConfig<TBaseSchemaAndConfig>, TComputedBaseSchemaRoutes extends BaseCallApiSchemaRoutes = GetBaseSchemaRoutes<TBaseSchemaAndConfig>>(initBaseConfig?: BaseCallApiConfig<TBaseCallApiContext, TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBaseSchemaAndConfig, TBasePluginArray>) => <TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeType = TBaseResultMode, TCallApiContext extends CallApiContext = TBaseCallApiContext, TThrowOnError extends ThrowOnErrorUnion = TBaseThrowOnError, TResponseType extends ResponseTypeType = TBaseResponseType, const TSchemaConfig extends CallApiSchemaConfig = TComputedBaseSchemaConfig, TInitURL extends InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig> = InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig>, TCurrentRouteSchemaKey extends GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL> = GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL>, const TSchema extends CallApiSchema = GetCurrentRouteSchema<TComputedBaseSchemaRoutes, TCurrentRouteSchemaKey>, const TPluginArray extends CallApiPlugin[] = TBasePluginArray, TComputedData = InferSchemaOutput<TSchema["data"], GetResponseType<TData, TResponseType>>, TComputedErrorData = InferSchemaOutput<TSchema["errorData"], GetResponseType<TErrorData, TResponseType>>, TComputedResult = CallApiResult<TComputedData, TComputedErrorData, TResultMode, TThrowOnError>>(initURL: TInitURL, initConfig?: CallApiConfig<TCallApiContext, TComputedData, TComputedErrorData, TResultMode, TThrowOnError, TResponseType, TComputedBaseSchemaRoutes, TSchema, TComputedBaseSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, TBasePluginArray, TPluginArray>) => Promise<TComputedResult>;
1783
+ declare const createFetchClient: <TBaseCallApiContext extends CallApiContext = DefaultCallApiContext, TBaseData = TBaseCallApiContext["Data"], TBaseErrorData = TBaseCallApiContext["ErrorData"], TBaseResultMode extends ResultModeType = (TBaseCallApiContext["ResultMode"] extends ResultModeType ? TBaseCallApiContext["ResultMode"] : ResultModeType), TBaseThrowOnError extends ThrowOnErrorUnion = boolean, TBaseResponseType extends ResponseTypeType = ResponseTypeType, const TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig, const TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedBaseSchemaConfig extends CallApiSchemaConfig = Writeable<NonNullable<TBaseSchemaAndConfig["config"]>, "deep">, TComputedBaseSchemaRoutes extends BaseCallApiSchemaRoutes = Writeable<TBaseSchemaAndConfig["routes"], "deep">>(initBaseConfig?: BaseCallApiConfig<TBaseCallApiContext, TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBaseSchemaAndConfig, TBasePluginArray>) => <TData = TBaseData, TErrorData = TBaseErrorData, TResultMode extends ResultModeType = TBaseResultMode, TCallApiContext extends CallApiContext = TBaseCallApiContext, TThrowOnError extends ThrowOnErrorUnion = TBaseThrowOnError, TResponseType extends ResponseTypeType = TBaseResponseType, const TSchemaConfig extends CallApiSchemaConfig = TComputedBaseSchemaConfig, TInitURL extends InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig> = InferInitURL<TComputedBaseSchemaRoutes, TSchemaConfig>, TCurrentRouteSchemaKey extends GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL> = GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL>, const TSchema extends CallApiSchema = GetCurrentRouteSchema<TComputedBaseSchemaRoutes, TCurrentRouteSchemaKey, TComputedBaseSchemaRoutes["@default"], TComputedBaseSchemaRoutes[TCurrentRouteSchemaKey], NonNullable<Omit<TComputedBaseSchemaRoutes["@default"], keyof TComputedBaseSchemaRoutes[TCurrentRouteSchemaKey]> & TComputedBaseSchemaRoutes[TCurrentRouteSchemaKey]>>, const TPluginArray extends CallApiPlugin[] = TBasePluginArray, TComputedData = InferSchemaResult<TSchema["data"], GetResponseType<TData, TResponseType, ResponseTypeMap<TData>>, "infer-output">, TComputedErrorData = InferSchemaResult<TSchema["errorData"], GetResponseType<TErrorData, TResponseType, ResponseTypeMap<TErrorData>>, "infer-output">, TComputedResult = InferCallApiResult<TComputedData, TComputedErrorData, TResultMode, TThrowOnError, {
1784
+ all: CallApiResultSuccessVariant<TComputedData>;
1785
+ onlyData: NoInfer<TComputedData>;
1868
1786
  onlyResponse: Response;
1869
- withoutResponse: Omit<CallApiResultSuccessVariant<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>, "response">;
1870
- }, ResultModeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">, InferSchemaResult<TSchema["errorData"], TErrorData, "infer-output">, TResponseType, TThrowOnError>>>(initURL: TInitURL, initConfig?: CallApiConfig<TCallApiContext, InferSchemaResult<TSchema["data"], GetResponseType<TData, TResponseType, ResponseTypeMap<TData>>, "infer-output">, InferSchemaResult<TSchema["errorData"], GetResponseType<TErrorData, TResponseType, ResponseTypeMap<TErrorData>>, "infer-output">, TResultMode, TThrowOnError, TResponseType, TComputedBaseSchemaRoutes, TSchema, TComputedBaseSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, TBasePluginArray, TPluginArray>) => Promise<TComputedResult>;
1871
- declare const callApi: <TData = unknown, TErrorData = unknown, TResultMode extends ResultModeType = ResultModeType, TCallApiContext extends CallApiContext = GetMergedCallApiContext<GetMergedCallApiContext<DefaultCallApiContext, {
1872
- Data: unknown;
1873
- ErrorData: unknown;
1874
- ResultMode: ResultModeType;
1875
- }>, {
1876
- Data: TData;
1877
- ErrorData: TErrorData;
1878
- ResultMode: TResultMode;
1879
- }>, TThrowOnError extends ThrowOnErrorUnion = boolean, TResponseType extends ResponseTypeType = ResponseTypeType, const TSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TInitURL extends ApplyStrictConfig<TSchemaConfig, ApplyURLBasedConfig<TSchemaConfig, AnyString | "@delete/" | "@get/" | "@patch/" | "@post/" | "@put/">> = ApplyStrictConfig<TSchemaConfig, ApplyURLBasedConfig<TSchemaConfig, AnyString | "@delete/" | "@get/" | "@patch/" | "@post/" | "@put/">>, TCurrentRouteSchemaKey extends GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL> = GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL>, const TSchema extends CallApiSchema = GetCurrentRouteSchema<{
1787
+ withoutResponse: Omit<CallApiResultSuccessVariant<TComputedData>, "response">;
1788
+ }, ResultModeMap<TComputedData, TComputedErrorData, TThrowOnError>>>(initURL: TInitURL, initConfig?: CallApiConfig<TCallApiContext, TComputedData, TComputedErrorData, TResultMode, TThrowOnError, TResponseType, TComputedBaseSchemaRoutes, TSchema, TComputedBaseSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, TBasePluginArray, TPluginArray>) => Promise<TComputedResult>;
1789
+ declare const callApi: <TData = unknown, TErrorData = unknown, TResultMode extends ResultModeType = ResultModeType, TCallApiContext extends CallApiContext = DefaultCallApiContext, TThrowOnError extends ThrowOnErrorUnion = boolean, TResponseType extends ResponseTypeType = ResponseTypeType, const TSchemaConfig extends CallApiSchemaConfig = CallApiSchemaConfig, TInitURL extends ApplyStrictConfig<TSchemaConfig, ApplyURLBasedConfig<TSchemaConfig, AnyString | "@delete/" | "@get/" | "@patch/" | "@post/" | "@put/">> = ApplyStrictConfig<TSchemaConfig, ApplyURLBasedConfig<TSchemaConfig, AnyString | "@delete/" | "@get/" | "@patch/" | "@post/" | "@put/">>, TCurrentRouteSchemaKey extends GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL> = GetCurrentRouteSchemaKey<TSchemaConfig, TInitURL>, const TSchema extends CallApiSchema = GetCurrentRouteSchema<{
1880
1790
  [x: AnyString]: CallApiSchema | undefined;
1881
1791
  "@default"?: CallApiSchema | undefined;
1882
1792
  "@delete/"?: CallApiSchema | undefined;
@@ -1908,12 +1818,12 @@ declare const callApi: <TData = unknown, TErrorData = unknown, TResultMode exten
1908
1818
  "@patch/"?: CallApiSchema | undefined;
1909
1819
  "@post/"?: CallApiSchema | undefined;
1910
1820
  "@put/"?: CallApiSchema | undefined;
1911
- }[TCurrentRouteSchemaKey]>>, const TPluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedResult = GetCallApiResult<InferSchemaResult<TSchema["data"], TData, "infer-output">, InferSchemaResult<TSchema["errorData"], TErrorData, "infer-output">, TResultMode, TThrowOnError, TResponseType, {
1912
- all: CallApiResultSuccessVariant<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>;
1913
- onlyData: NoInfer<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>;
1821
+ }[TCurrentRouteSchemaKey]>>, const TPluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedData = InferSchemaResult<TSchema["data"], GetResponseType<TData, TResponseType, ResponseTypeMap<TData>>, "infer-output">, TComputedErrorData = InferSchemaResult<TSchema["errorData"], GetResponseType<TErrorData, TResponseType, ResponseTypeMap<TErrorData>>, "infer-output">, TComputedResult = InferCallApiResult<TComputedData, TComputedErrorData, TResultMode, TThrowOnError, {
1822
+ all: CallApiResultSuccessVariant<TComputedData>;
1823
+ onlyData: NoInfer<TComputedData>;
1914
1824
  onlyResponse: Response;
1915
- withoutResponse: Omit<CallApiResultSuccessVariant<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>, "response">;
1916
- }, ResultModeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">, InferSchemaResult<TSchema["errorData"], TErrorData, "infer-output">, TResponseType, TThrowOnError>>>(initURL: TInitURL, initConfig?: CallApiConfig<TCallApiContext, InferSchemaResult<TSchema["data"], GetResponseType<TData, TResponseType, ResponseTypeMap<TData>>, "infer-output">, InferSchemaResult<TSchema["errorData"], GetResponseType<TErrorData, TResponseType, ResponseTypeMap<TErrorData>>, "infer-output">, TResultMode, TThrowOnError, TResponseType, {
1825
+ withoutResponse: Omit<CallApiResultSuccessVariant<TComputedData>, "response">;
1826
+ }, ResultModeMap<TComputedData, TComputedErrorData, TThrowOnError>>>(initURL: TInitURL, initConfig?: CallApiConfig<TCallApiContext, TComputedData, TComputedErrorData, TResultMode, TThrowOnError, TResponseType, {
1917
1827
  [x: AnyString]: CallApiSchema | undefined;
1918
1828
  "@default"?: CallApiSchema | undefined;
1919
1829
  "@delete/"?: CallApiSchema | undefined;
@@ -1923,5 +1833,5 @@ declare const callApi: <TData = unknown, TErrorData = unknown, TResultMode exten
1923
1833
  "@put/"?: CallApiSchema | undefined;
1924
1834
  }, TSchema, CallApiSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, DefaultPluginArray, TPluginArray>) => Promise<TComputedResult>;
1925
1835
  //#endregion
1926
- export { PossibleHTTPError as $, definePlugin as A, CallApiExtraOptionsForHooks as B, isHTTPError as C, isValidationErrorInstance as D, isValidationError as E, toQueryString as F, GetExtendSchemaConfigContext as G, CallApiRequestOptions as H, BaseCallApiConfig as I, Register as J, InferExtendSchemaContext as K, BaseCallApiExtraOptions as L, defineSchemaConfig as M, defineSchemaRoutes as N, defineBaseConfig as O, toFormData as P, CallApiSuccessOrErrorVariant as Q, CallApiConfig as R, SuccessContext as S, isJavascriptError as T, CallApiRequestOptionsForHooks as U, CallApiParameters as V, CallApiResultLoose as W, CallApiResultErrorVariant as X, RetryOptions as Y, CallApiResultSuccessVariant as Z, RequestContext as _, BaseSchemaRouteKeyPrefixes as a, HTTPError as at, ResponseErrorContext as b, InferSchemaInput as c, URLOptions as ct, CallApiPlugin as d, PossibleJavaScriptError as et, PluginHooks as f, HooksOrHooksArray as g, Hooks as h, BaseCallApiSchemaRoutes as i, ResultModeType as it, defineSchema as j, defineMainSchema as k, InferSchemaOutput as l, DedupeOptions as lt, ErrorContext as m, createFetchClient as n, PossibleValidationError as nt, CallApiSchema as o, ValidationError as ot, PluginSetupContext as p, InstanceContext as q, createFetchClientWithContext as r, ResponseTypeType as rt, CallApiSchemaConfig as s, InferParamsFromRoute as st, callApi as t, PossibleJavaScriptOrValidationError as tt, DefaultCallApiContext as u, RequestStreamContext as v, isHTTPErrorInstance as w, ResponseStreamContext as x, ResponseContext as y, CallApiExtraOptions as z };
1927
- //# sourceMappingURL=index-j55-O6zR.d.ts.map
1836
+ export { Writeable as $, ErrorContext as A, CallApiPlugin as B, InferExtendSchemaContext as C, ValidationError as D, HTTPError as E, ResponseContext as F, BaseSchemaRouteKeyPrefixes as G, PluginSetupContext as H, ResponseErrorContext as I, InferSchemaInput as J, CallApiSchema as K, ResponseStreamContext as L, HooksOrHooksArray as M, RequestContext as N, RetryOptions as O, RequestStreamContext as P, Satisfies as Q, SuccessContext as R, GetExtendSchemaConfigContext as S, Register as T, URLOptions as U, PluginHooks as V, BaseCallApiSchemaRoutes as W, InferParamsFromRoute as X, InferSchemaOutput as Y, AnyFunction as Z, CallApiExtraOptionsForHooks as _, CallApiResultSuccessVariant as a, CallApiRequestOptionsForHooks as b, PossibleJavaScriptError as c, ResponseTypeType as d, ResultModeType as f, CallApiExtraOptions as g, CallApiConfig as h, CallApiResultErrorVariant as i, Hooks as j, DedupeOptions as k, PossibleJavaScriptOrValidationError as l, BaseCallApiExtraOptions as m, createFetchClient as n, CallApiSuccessOrErrorVariant as o, BaseCallApiConfig as p, CallApiSchemaConfig as q, createFetchClientWithContext as r, PossibleHTTPError as s, callApi as t, PossibleValidationError as u, CallApiParameters as v, InstanceContext as w, CallApiResultLoose as x, CallApiRequestOptions as y, DefaultCallApiContext as z };
1837
+ //# sourceMappingURL=index-CrJL7qOL.d.ts.map