@zayne-labs/callapi 1.11.27 → 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 {
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 {
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 {
315
125
  * }
316
126
  * ```
317
127
  */
318
- fetchMiddleware?: (context: RequestContext & {
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,1216 +341,1451 @@ 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 FetchSpecificKeysUnion = Exclude<(typeof fetchSpecificKeys)[number], "body" | "headers" | "method">;
849
- type ModifiedRequestInit = RequestInit & {
850
- duplex?: "half";
851
- };
852
- type CallApiRequestOptions = Prettify<{
853
- /**
854
- * Body of the request, can be a object or any other supported body type.
855
- */
856
- body?: Body;
857
- /**
858
- * Headers to be used in the request.
859
- */
860
- headers?: HeadersOption;
861
- /**
862
- * HTTP method for the request.
863
- * @default "GET"
864
- */
865
- method?: MethodUnion;
866
- } & Pick<ModifiedRequestInit, FetchSpecificKeysUnion>>;
867
- type CallApiRequestOptionsForHooks = Omit<CallApiRequestOptions, "headers"> & {
868
- 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;
869
427
  };
870
- 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, TComputedPluginOptions = InferPluginOptions<TPluginArray$1> & TCallApiContext$1["InferredPluginOptions"], TComputedInferredPluginOptions extends Pick<Required<CallApiContext>, "InferredPluginOptions"> = {
871
- InferredPluginOptions: TComputedPluginOptions;
872
- }> = DedupeOptions & HookConfigOptions & HooksOrHooksArray<TComputedInferredPluginOptions, TData$1, TErrorData$1> & Middlewares & Partial<TComputedInferredPluginOptions["InferredPluginOptions"]> & ResultModeOption<TErrorData$1, TResultMode$1> & RetryOptions<TErrorData$1> & 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 {
873
437
  /**
874
- * Automatically add an Authorization header value.
438
+ * Base URL for all API requests. Will only be prepended to relative URLs.
875
439
  *
876
- * Supports multiple authentication patterns:
877
- * - String: Direct authorization header value
878
- * - 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"
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
879
450
  *
451
+ * // Environment-specific base URLs
452
+ * baseURL: process.env.NODE_ENV === "production"
453
+ * ? "https://api.example.com"
454
+ * : "http://localhost:3000/api"
880
455
  * ```
881
456
  */
882
- auth?: Auth;
457
+ baseURL?: string;
883
458
  /**
884
- * Custom function to serialize request body objects into strings.
459
+ * Resolved request URL after processing baseURL, parameters, and query strings (readonly)
885
460
  *
886
- * Useful for custom serialization formats or when the default JSON
887
- * 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.
888
463
  *
889
- * @example
890
- * ```ts
891
- * // Custom form data serialization
892
- * bodySerializer: (data) => {
893
- * const formData = new URLSearchParams();
894
- * Object.entries(data).forEach(([key, value]) => {
895
- * formData.append(key, String(value));
896
- * });
897
- * return formData.toString();
898
- * }
464
+ */
465
+ readonly fullURL?: string;
466
+ /**
467
+ * The original URL string passed to the callApi instance (readonly)
899
468
  *
900
- * // XML serialization
901
- * bodySerializer: (data) => {
902
- * return `<request>${Object.entries(data)
903
- * .map(([key, value]) => `<${key}>${value}</${key}>`)
904
- * .join('')}</request>`;
905
- * }
469
+ * This preserves the original URL as provided, including any method modifiers like "@get/" or "@post/".
906
470
  *
907
- * // Custom JSON with specific formatting
908
- * bodySerializer: (data) => JSON.stringify(data, null, 2)
909
- * ```
910
471
  */
911
- bodySerializer?: (bodyData: Record<string, unknown>) => string;
472
+ readonly initURL?: string;
912
473
  /**
913
- * Whether to clone the response so it can be read multiple times.
474
+ * The URL string after normalization, with method modifiers removed(readonly)
914
475
  *
915
- * By default, response streams can only be consumed once. Enable this when you need
916
- * 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.
917
478
  *
918
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/clone
919
- * @default false
920
479
  */
921
- cloneResponse?: boolean;
480
+ readonly initURLNormalized?: string;
922
481
  /**
923
- * Custom fetch implementation to replace the default fetch function.
482
+ * Parameters to be substituted into URL path segments.
924
483
  *
925
- * Useful for testing, adding custom behavior, or using alternative HTTP clients
926
- * that implement the fetch API interface.
484
+ * Supports both object-style (named parameters) and array-style (positional parameters)
485
+ * for flexible URL parameter substitution.
927
486
  *
928
487
  * @example
929
- * ```ts
930
- * // Use node-fetch in Node.js environments
931
- * import fetch from 'node-fetch';
932
- *
933
- * // Mock fetch for testing
934
- * customFetchImpl: async (url, init) => {
935
- * return new Response(JSON.stringify({ mocked: true }), {
936
- * status: 200,
937
- * headers: { 'Content-Type': 'application/json' }
938
- * });
939
- * }
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
940
495
  *
941
- * // Add custom logging to all requests
942
- * customFetchImpl: async (url, init) => {
943
- * console.log(`Fetching: ${url}`);
944
- * const response = await fetch(url, init);
945
- * console.log(`Response: ${response.status}`);
946
- * return response;
947
- * }
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
948
502
  *
949
- * // Use with custom HTTP client
950
- * customFetchImpl: async (url, init) => {
951
- * // Convert to your preferred HTTP client format
952
- * return await customHttpClient.request({
953
- * url: url.toString(),
954
- * method: init?.method || 'GET',
955
- * headers: init?.headers,
956
- * body: init?.body
957
- * });
958
- * }
503
+ * // Single parameter
504
+ * const singleParam: URLOptions = {
505
+ * initURL: "/users/:id",
506
+ * params: { id: "user-123" }
507
+ * };
508
+ * // Results in: /users/user-123
959
509
  * ```
960
510
  */
961
- customFetchImpl?: FetchImpl;
511
+ params?: Params;
962
512
  /**
963
- * Default HTTP error message when server doesn't provide one.
964
- *
965
- * Can be a static string or a function that receives error context
966
- * to generate dynamic error messages based on the response.
513
+ * Query parameters to append to the URL as search parameters.
967
514
  *
968
- * @default "Failed to fetch data from server!"
515
+ * These will be serialized into the URL query string using standard
516
+ * URL encoding practices.
969
517
  *
970
518
  * @example
971
- * ```ts
972
- * // Static error message
973
- * defaultHTTPErrorMessage: "API request failed. Please try again."
974
- *
975
- * // Dynamic error message based on status code
976
- * defaultHTTPErrorMessage: ({ response }) => {
977
- * switch (response.status) {
978
- * case 401: return "Authentication required. Please log in.";
979
- * case 403: return "Access denied. Insufficient permissions.";
980
- * case 404: return "Resource not found.";
981
- * case 429: return "Too many requests. Please wait and try again.";
982
- * case 500: return "Server error. Please contact support.";
983
- * 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
984
528
  * }
985
- * }
529
+ * };
530
+ * // Results in: /users?page=1&limit=10&search=john%20doe&active=true
986
531
  *
987
- * // Include error data in message
988
- * defaultHTTPErrorMessage: ({ errorData, response }) => {
989
- * const userMessage = errorData?.message || "Unknown error occurred";
990
- * return `${userMessage} (Status: ${response.status})`;
991
- * }
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
992
544
  * ```
993
545
  */
994
- 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> {
995
562
  /**
996
- * Forces calculation of total byte size from request/response body streams.
997
- *
998
- * Useful when the Content-Length header is missing or incorrect, and you need
999
- * accurate size information for progress tracking or bandwidth monitoring.
1000
- *
1001
- * @default false
1002
- *
563
+ * Defines additional options that can be passed to callApi
1003
564
  */
1004
- forcefullyCalculateStreamSize?: boolean | {
1005
- request?: boolean;
1006
- response?: boolean;
1007
- };
565
+ defineExtraOptions?: (...params: never[]) => unknown;
1008
566
  /**
1009
- * Optional metadata field for associating additional information with requests.
1010
- *
1011
- * Useful for logging, tracing, or handling specific cases in shared interceptors.
1012
- * The meta object is passed through to all hooks and can be accessed in error handlers.
1013
- *
1014
- * @example
1015
- * ```ts
1016
- * const callMainApi = callApi.create({
1017
- * baseURL: "https://main-api.com",
1018
- * onResponseError: ({ response, options }) => {
1019
- * if (options.meta?.userId) {
1020
- * console.error(`User ${options.meta.userId} made an error`);
1021
- * }
1022
- * },
1023
- * });
1024
- *
1025
- * const response = await callMainApi({
1026
- * url: "https://example.com/api/data",
1027
- * meta: { userId: "123" },
1028
- * });
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.
1029
613
  *
1030
- * // Use case: Request tracking
1031
- * const result = await callMainApi({
1032
- * url: "https://example.com/api/data",
1033
- * meta: {
1034
- * requestId: generateId(),
1035
- * source: "user-dashboard",
1036
- * priority: "high"
1037
- * }
1038
- * });
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.
1039
617
  *
1040
- * // Use case: Feature flags
1041
- * const client = callApi.create({
1042
- * baseURL: "https://api.example.com",
1043
- * meta: {
1044
- * features: ["newUI", "betaFeature"],
1045
- * experiment: "variantA"
1046
- * }
1047
- * });
1048
- * ```
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
1049
620
  */
1050
- meta?: TCallApiContext$1["Meta"] extends DefaultMetaObject ? TCallApiContext$1["Meta"] : DefaultCallApiContext["Meta"];
621
+ onError?: (context: ErrorContext<TCallApiContext>) => Awaitable<unknown>;
1051
622
  /**
1052
- * 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.
1053
624
  *
1054
- * 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.
1055
627
  *
1056
- * @example
1057
- * ```ts
1058
- * responseParser: (responseString) => {
1059
- * return JSON.parse(responseString);
1060
- * }
628
+ * @param context - Request context with mutable request object and configuration
629
+ * @returns Promise or void - Hook can be async or sync
1061
630
  *
1062
- * // Parse XML responses
1063
- * responseParser: (responseString) => {
1064
- * const parser = new DOMParser();
1065
- * const doc = parser.parseFromString(responseString, "text/xml");
1066
- * return xmlToObject(doc);
1067
- * }
631
+ */
632
+ onRequest?: (context: RequestContext<TCallApiContext>) => Awaitable<unknown>;
633
+ /**
634
+ * Hook called when an error occurs during the fetch request itself.
1068
635
  *
1069
- * // Parse CSV responses
1070
- * responseParser: (responseString) => {
1071
- * const lines = responseString.split('\n');
1072
- * const headers = lines[0].split(',');
1073
- * const data = lines.slice(1).map(line => {
1074
- * const values = line.split(',');
1075
- * return headers.reduce((obj, header, index) => {
1076
- * obj[header] = values[index];
1077
- * return obj;
1078
- * }, {});
1079
- * });
1080
- * return data;
1081
- * }
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`.
1082
639
  *
1083
- * ```
640
+ * @param context - Request error context with error details and null response
641
+ * @returns Promise or void - Hook can be async or sync
1084
642
  */
1085
- responseParser?: (responseString: string) => Awaitable<TData$1>;
643
+ onRequestError?: (context: RequestErrorContext<TCallApiContext>) => Awaitable<unknown>;
1086
644
  /**
1087
- * 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.
1088
646
  *
1089
- * Different response types trigger different parsing methods:
1090
- * - **"json"**: Parses as JSON using response.json()
1091
- * - **"text"**: Returns as plain text using response.text()
1092
- * - **"blob"**: Returns as Blob using response.blob()
1093
- * - **"arrayBuffer"**: Returns as ArrayBuffer using response.arrayBuffer()
1094
- * - **"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.
1095
652
  *
1096
- * @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.
1097
656
  *
1098
- * @example
1099
- * ```ts
1100
- * // JSON API responses (default)
1101
- * 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
1102
659
  *
1103
- * // Plain text responses
1104
- * responseType: "text"
1105
- * // 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.
1106
664
  *
1107
- * // File downloads
1108
- * responseType: "blob"
1109
- * // 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.
1110
668
  *
1111
- * // Binary data
1112
- * responseType: "arrayBuffer"
1113
- * // 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
1114
671
  *
1115
- * // Streaming responses
1116
- * responseType: "stream"
1117
- * // Usage: const stream = await callApi("/large-dataset", { responseType: "stream" });
1118
- * ```
1119
672
  */
1120
- responseType?: TResponseType$1;
673
+ onResponse?: (context: ResponseContext<TCallApiContext>) => Awaitable<unknown>;
1121
674
  /**
1122
- * 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.
1123
676
  *
1124
- * Different modes return different combinations of data, error, and response:
1125
- * - **"all"**: Returns { data, error, response } - complete result information
1126
- * - **"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.
1127
680
  *
1128
- * When combined with throwOnError: true, null/error variants are automatically removed:
1129
- * - **"all" + throwOnError: true**: Returns { data, error: null, response } (error property is null, throws instead)
1130
- * - **"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.
1131
687
  *
1132
- * @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.
1133
691
  *
1134
- * @example
1135
- * ```ts
1136
- * // Complete result with all information (default)
1137
- * const { data, error, response } = await callApi("/users", { resultMode: "all" });
1138
- * if (error) {
1139
- * console.error("Request failed:", error);
1140
- * } else {
1141
- * console.log("Users:", data);
1142
- * }
692
+ * @param context - Response stream context with progress event and response
693
+ * @returns Promise or void - Hook can be async or sync
1143
694
  *
1144
- * // Complete result but throws on errors (throwOnError removes error from type)
1145
- * try {
1146
- * const { data, response } = await callApi("/users", {
1147
- * resultMode: "all",
1148
- * throwOnError: true
1149
- * });
1150
- * console.log("Users:", data); // data is never null here
1151
- * } catch (error) {
1152
- * console.error("Request failed:", error);
1153
- * }
695
+ */
696
+ onResponseStream?: (context: ResponseStreamContext<TCallApiContext>) => Awaitable<unknown>;
697
+ /**
698
+ * Hook called when a request is being retried.
1154
699
  *
1155
- * // Only data, returns null on errors
1156
- * const users = await callApi("/users", { resultMode: "onlyData" });
1157
- * if (users) {
1158
- * console.log("Users:", users);
1159
- * } else {
1160
- * console.log("Request failed");
1161
- * }
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
1162
706
  *
1163
- * // Only data, throws on errors (throwOnError removes null from type)
1164
- * try {
1165
- * const users = await callApi("/users", {
1166
- * resultMode: "onlyData",
1167
- * throwOnError: true
1168
- * });
1169
- * console.log("Users:", users); // users is never null here
1170
- * } catch (error) {
1171
- * console.error("Request failed:", error);
1172
- * }
1173
- * ```
1174
707
  */
1175
- resultMode?: TResultMode$1;
708
+ onRetry?: (response: RetryContext<TCallApiContext>) => Awaitable<unknown>;
1176
709
  /**
1177
- * 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.
1178
711
  *
1179
- * Can be a boolean or a function that receives the error and decides whether to throw.
1180
- * 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.
1181
715
  *
1182
- * @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
1183
718
  *
1184
- * @example
1185
- * ```ts
1186
- * // Always throw errors
1187
- * throwOnError: true
1188
- * try {
1189
- * const data = await callApi("/users");
1190
- * console.log("Users:", data);
1191
- * } catch (error) {
1192
- * console.error("Request failed:", error);
1193
- * }
719
+ */
720
+ onSuccess?: (context: SuccessContext<TCallApiContext>) => Awaitable<unknown>;
721
+ /**
722
+ * Hook called when a validation error occurs.
1194
723
  *
1195
- * // Never throw errors (default)
1196
- * throwOnError: false
1197
- * const { data, error } = await callApi("/users");
1198
- * if (error) {
1199
- * console.error("Request failed:", error);
1200
- * }
1201
- *
1202
- * // Conditionally throw based on error type
1203
- * throwOnError: (error) => {
1204
- * // Throw on client errors (4xx) but not server errors (5xx)
1205
- * return error.response?.status >= 400 && error.response?.status < 500;
1206
- * }
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.
1207
727
  *
1208
- * // Throw only on specific status codes
1209
- * throwOnError: (error) => {
1210
- * const criticalErrors = [401, 403, 404];
1211
- * return criticalErrors.includes(error.response?.status);
1212
- * }
728
+ * @param context - Validation error context with error details and response (if available)
729
+ * @returns Promise or void - Hook can be async or sync
1213
730
  *
1214
- * // Throw on validation errors but not network errors
1215
- * throwOnError: (error) => {
1216
- * return error.type === "validation";
1217
- * }
1218
- * ```
1219
731
  */
1220
- 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 {
1221
736
  /**
1222
- * Request timeout in milliseconds. Request will be aborted if it takes longer.
737
+ * Controls the execution mode of all composed hooks (main + plugin hooks).
1223
738
  *
1224
- * Useful for preventing requests from hanging indefinitely and providing
1225
- * 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
1226
741
  *
1227
- * @example
1228
- * ```ts
1229
- * // 5 second timeout
1230
- * timeout: 5000
742
+ * This affects how ALL hooks execute together, regardless of their source (main or plugin).
1231
743
  *
1232
- * // Different timeouts for different endpoints
1233
- * const quickApi = createFetchClient({ timeout: 3000 }); // 3s for fast endpoints
1234
- * 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.
1235
751
  *
1236
- * // Per-request timeout override
1237
- * await callApi("/quick-data", { timeout: 1000 });
1238
- * 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.
1239
759
  *
1240
- * // No timeout (use with caution)
1241
- * timeout: 0
1242
- * ```
760
+ * Contains configuration specific to this particular API call, which
761
+ * can override or extend the base configuration.
1243
762
  */
1244
- 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;
811
+ };
812
+ type ResponseStreamContext<TCallApiContext extends Pick<CallApiContext, "InferredExtraOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext> & {
813
+ event: StreamProgressEvent;
814
+ response: Response;
1245
815
  };
1246
- 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> & {
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 = {
1247
822
  /**
1248
- * 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.
1249
828
  *
1250
- * Base plugins are applied to all instances created from this base configuration
1251
- * 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
1252
838
  *
1253
839
  * @example
1254
840
  * ```ts
1255
- * // 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
1256
845
  *
1257
- * // Create base client with common plugins
1258
- * const callApi = createFetchClient({
1259
- * baseURL: "https://api.example.com",
1260
- * plugins: [loggerPlugin({ enabled: true })]
846
+ * // Global scope - share cache across related clients
847
+ * const userClient = createFetchClient({
848
+ * baseURL: "/api/users",
849
+ * dedupeCacheScope: "global",
1261
850
  * });
1262
- *
1263
- * // All requests inherit base plugins
1264
- * await callApi("/users");
1265
- * await callApi("/posts");
1266
- *
851
+ * const postClient = createFetchClient({
852
+ * baseURL: "/api/posts",
853
+ * dedupeCacheScope: "global",
854
+ * });
855
+ * // These clients will share deduplication state
1267
856
  * ```
1268
- */
1269
- plugins?: TBasePluginArray$1;
1270
- /**
1271
- * Base validation schemas for the client configuration.
1272
857
  *
1273
- * Defines validation rules for requests and responses that apply to all
1274
- * instances created from this base configuration. Provides type safety
1275
- * and runtime validation for API interactions.
858
+ * @default "local"
1276
859
  */
1277
- schema?: TBaseSchemaAndConfig$1;
860
+ dedupeCacheScope?: "global" | "local";
1278
861
  /**
1279
- * Controls which configuration parts skip automatic merging between base and instance configs.
862
+ * Unique namespace for the global deduplication cache when using `dedupeCacheScope: "global"`.
1280
863
  *
1281
- * By default, CallApi automatically merges base configuration with instance configuration.
1282
- * This option allows you to disable automatic merging for specific parts when you need
1283
- * 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.
1284
867
  *
1285
- * @enum
1286
- * - **"all"**: Disables automatic merging for both request options and extra options
1287
- * - **"options"**: Disables automatic merging of extra options only (hooks, plugins, etc.)
1288
- * - **"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
1289
878
  *
1290
879
  * @example
1291
880
  * ```ts
1292
- * // Skip all automatic merging - full manual control
1293
- * const client = callApi.create((ctx) => ({
1294
- * 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
+ * });
1295
892
  *
1296
- * // Manually decide what to merge
1297
- * baseURL: ctx.options.baseURL, // Keep base URL
1298
- * timeout: 5000, // Override timeout
1299
- * headers: {
1300
- * ...ctx.request.headers, // Merge headers manually
1301
- * "X-Custom": "value" // Add custom header
1302
- * }
1303
- * }));
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
+ * });
1304
899
  *
1305
- * // Skip options merging - manual plugin/hook control
1306
- * const client = callApi.create((ctx) => ({
1307
- * 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
+ * ```
1308
906
  *
1309
- * // Manually control which plugins to use
1310
- * plugins: [
1311
- * ...ctx.options.plugins?.filter(p => p.name !== "unwanted") || [],
1312
- * customPlugin
1313
- * ],
907
+ * @default "default"
908
+ */
909
+ dedupeCacheScopeKey?: "default" | AnyString | ((context: RequestContext) => string | undefined);
910
+ /**
911
+ * Custom key generator for request deduplication.
1314
912
  *
1315
- * // Request options still auto-merge
1316
- * method: "POST"
1317
- * }));
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.).
1318
916
  *
1319
- * // Skip request merging - manual request control
1320
- * const client = callApi.create((ctx) => ({
1321
- * 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.)
1322
923
  *
1323
- * // 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
1324
930
  *
1325
- * // Manually control request options
1326
- * headers: {
1327
- * "Content-Type": "application/json",
1328
- * // Don't merge base headers
1329
- * },
1330
- * method: ctx.request.method || "GET"
1331
- * }));
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
1332
935
  *
1333
- * // Use case: Conditional merging based on request
1334
- * const client = createFetchClient((ctx) => ({
1335
- * skipAutoMergeFor: "options",
936
+ * @example
937
+ * ```ts
938
+ * import { callApi } from "@zayne-labs/callapi";
1336
939
  *
1337
- * // Only use auth plugin for protected routes
1338
- * plugins: ctx.initURL.includes("/protected/")
1339
- * ? [...(ctx.options.plugins || []), authPlugin]
1340
- * : ctx.options.plugins?.filter(p => p.name !== "auth") || []
1341
- * }));
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
+ * });
1342
975
  * ```
976
+ *
977
+ * @default Auto-generated from request details
1343
978
  */
1344
- skipAutoMergeFor?: "all" | "options" | "request";
1345
- };
1346
- type GetBaseSchemaRoutes<TBaseSchemaAndConfig$1 extends BaseCallApiSchemaAndConfig> = Writeable<TBaseSchemaAndConfig$1["routes"], "deep">;
1347
- type GetBaseSchemaConfig<TBaseSchemaAndConfig$1 extends BaseCallApiSchemaAndConfig> = Writeable<NonNullable<TBaseSchemaAndConfig$1["config"]>, "deep">;
1348
- type InferExtendSchemaContext<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey$1 extends string> = {
1349
- baseSchemaRoutes: TBaseSchemaRoutes$1;
1350
- currentRouteSchema: GetCurrentRouteSchema<TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1>;
1351
- };
1352
- type GetExtendSchemaConfigContext<TBaseSchemaConfig extends CallApiSchemaConfig> = {
1353
- baseSchemaConfig: TBaseSchemaConfig;
1354
- };
1355
- type InferExtendPluginContext<TBasePluginArray$1 extends CallApiPlugin[]> = {
1356
- basePlugins: TBasePluginArray$1;
1357
- };
1358
- 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);
1359
980
  /**
1360
- * 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.
1361
982
  *
1362
- * Instance plugins are added to the base plugins and provide functionality
1363
- * specific to this particular API instance. Can be a static array or a function
1364
- * 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
1365
987
  *
1366
- */
1367
- plugins?: TPluginArray$1 | ((context: TComputedPluginContext) => TPluginArray$1);
1368
- /**
1369
- * For instance-specific validation schemas
988
+ * @example
989
+ * ```ts
990
+ * // Static strategies
991
+ * const searchClient = createFetchClient({
992
+ * dedupeStrategy: "cancel" // Cancel previous searches
993
+ * });
1370
994
  *
1371
- * 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
+ * });
1372
998
  *
1373
- * 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
+ * });
1374
1005
  *
1375
- */
1376
- schema?: TSchema$1 | ((context: TComputedSchemaContext) => TSchema$1);
1377
- /**
1378
- * 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
+ * });
1379
1015
  *
1380
- * Controls how validation schemas are applied and behave for this specific API instance.
1381
- * 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
+ * ```
1382
1027
  *
1028
+ * @default "cancel"
1383
1029
  */
1384
- schemaConfig?: TSchemaConfig$1 | ((context: TComputedSchemaConfigContext) => TSchemaConfig$1);
1385
- };
1386
- type CallApiExtraOptionsForHooks<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = Hooks & Omit<CallApiExtraOptions<TCallApiContext$1>, keyof Hooks>;
1387
- type InstanceContext = {
1388
- initURL: string;
1389
- options: CallApiExtraOptions;
1390
- request: CallApiRequestOptions;
1391
- };
1392
- 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);
1393
- 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>>;
1394
- 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>];
1395
- 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>;
1396
- 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>;
1397
- //#endregion
1398
- //#region src/utils/external/body.d.ts
1399
- type ToQueryStringFn = {
1400
- (query: CallApiExtraOptions["query"]): string | null;
1401
- (query: Required<CallApiExtraOptions>["query"]): string;
1402
- };
1403
- declare const toQueryString: ToQueryStringFn;
1404
- type AllowedPrimitives = boolean | number | string | Blob | null | undefined;
1405
- type AllowedValues = AllowedPrimitives | AllowedPrimitives[] | Record<string, AllowedPrimitives>;
1406
- type ToFormDataFn = {
1407
- (data: Record<string, AllowedValues>): FormData;
1408
- <TData extends Record<string, AllowedValues>>(data: TData, options: {
1409
- returnType: "inputType";
1410
- }): TData;
1411
- };
1412
- /**
1413
- * @description Converts a plain object to FormData.
1414
- *
1415
- * Handles various data types:
1416
- * - **Primitives** (string, number, boolean): Converted to strings
1417
- * - **Blobs/Files**: Added directly to FormData
1418
- * - **Arrays**: Each item is appended (allows multiple values for same key)
1419
- * - **Objects**: JSON stringified before adding to FormData
1420
- *
1421
- * @example
1422
- * ```ts
1423
- * // Basic usage
1424
- * const formData = toFormData({
1425
- * name: "John",
1426
- * age: 30,
1427
- * active: true
1428
- * });
1429
- *
1430
- * // With arrays
1431
- * const formData = toFormData({
1432
- * tags: ["javascript", "typescript"],
1433
- * name: "John"
1434
- * });
1435
- *
1436
- * // With files
1437
- * const formData = toFormData({
1438
- * avatar: fileBlob,
1439
- * name: "John"
1440
- * });
1441
- *
1442
- * // With nested objects (one level only)
1443
- * const formData = toFormData({
1444
- * user: { name: "John", age: 30 },
1445
- * settings: { theme: "dark" }
1446
- * });
1447
- *
1448
- * // Type-preserving usage with Zod
1449
- * const schema = z.object({ name: z.string(), file: z.instanceof(Blob) });
1450
- * const data = schema.parse({ name: "John", file: blob });
1451
- * const typedFormData = toFormData(data, { returnType: "inputType" });
1452
- * // Type is { name: string; file: Blob }, runtime is FormData
1453
- * ```
1454
- */
1455
- declare const toFormData: ToFormDataFn;
1456
- //#endregion
1457
- //#region src/utils/external/define.d.ts
1458
- declare const defineSchema: <const TBaseSchemaRoutes extends BaseCallApiSchemaRoutes, const TSchemaConfig extends CallApiSchemaConfig>(routes: TBaseSchemaRoutes, config?: Satisfies<TSchemaConfig, CallApiSchemaConfig>) => {
1459
- config: Writeable<Satisfies<TSchemaConfig, CallApiSchemaConfig>, "deep">;
1460
- routes: Writeable<TBaseSchemaRoutes, "deep">;
1461
- };
1462
- declare const defineSchemaRoutes: <const TSchemaRoutes extends BaseCallApiSchemaRoutes>(routes: TSchemaRoutes) => Writeable<typeof routes, "deep">;
1463
- declare const defineMainSchema: <const TSchema extends CallApiSchema>(mainSchema: Satisfies<TSchema, CallApiSchema>) => Writeable<typeof mainSchema, "deep">;
1464
- declare const defineSchemaConfig: <const TSchemaConfig extends CallApiSchemaConfig>(config: Satisfies<TSchemaConfig, CallApiSchemaConfig>) => Writeable<typeof config, "deep">;
1465
- declare const definePlugin: <const TPlugin extends CallApiPlugin>(plugin: TPlugin) => Writeable<typeof plugin, "deep">;
1466
- type BaseConfigObject = Exclude<BaseCallApiConfig, AnyFunction>;
1467
- type BaseConfigFn = Extract<BaseCallApiConfig, AnyFunction>;
1468
- type DefineBaseConfig = {
1469
- <const TBaseConfig extends BaseConfigObject>(baseConfig: Satisfies<TBaseConfig, BaseConfigObject>): Writeable<typeof baseConfig, "deep">;
1470
- <TBaseConfigFn extends BaseConfigFn>(baseConfig: TBaseConfigFn): TBaseConfigFn;
1030
+ dedupeStrategy?: DedupeStrategyUnion | ((context: RequestContext) => DedupeStrategyUnion);
1471
1031
  };
1472
- declare const defineBaseConfig: DefineBaseConfig;
1473
- //#endregion
1474
- //#region src/utils/external/guards.d.ts
1475
- declare const isHTTPError: <TErrorData>(error: CallApiResultErrorVariant<TErrorData>["error"] | null) => error is PossibleHTTPError<TErrorData>;
1476
- declare const isHTTPErrorInstance: <TErrorData>(error: unknown) => error is HTTPError<TErrorData>;
1477
- declare const isValidationError: (error: CallApiResultErrorVariant<unknown>["error"] | null) => error is PossibleValidationError;
1478
- declare const isValidationErrorInstance: (error: unknown) => error is ValidationError;
1479
- declare const isJavascriptError: (error: CallApiResultErrorVariant<unknown>["error"] | null) => error is PossibleJavaScriptError;
1480
1032
  //#endregion
1481
- //#region src/stream.d.ts
1482
- 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> {
1483
1051
  /**
1484
- * 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.
1485
1055
  */
1486
- chunk: Uint8Array;
1056
+ readonly ["~retryAttemptCount"]?: number;
1487
1057
  /**
1488
- * Progress in percentage
1058
+ * All retry options in a single object instead of separate properties
1489
1059
  */
1490
- progress: number;
1060
+ retry?: InnerRetryOptions<TErrorData>;
1491
1061
  /**
1492
- * Total size of data in bytes
1062
+ * Number of allowed retry attempts on HTTP errors
1063
+ * @default 0
1493
1064
  */
1494
- totalBytes: number;
1065
+ retryAttempts?: number;
1495
1066
  /**
1496
- * Amount of data transferred so far
1067
+ * Callback whose return value determines if a request should be retried or not
1497
1068
  */
1498
- transferredBytes: number;
1499
- };
1500
- declare global {
1501
- interface ReadableStream<R> {
1502
- [Symbol.asyncIterator]: () => AsyncIterableIterator<R>;
1503
- }
1504
- }
1505
- //#endregion
1506
- //#region src/hooks.d.ts
1507
- interface Hooks<TCallApiContext$1 extends Pick<CallApiContext, "Data" | "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TData$1 = TCallApiContext$1["Data"], TErrorData$1 = TCallApiContext$1["ErrorData"]> {
1069
+ retryCondition?: RetryCondition<TErrorData>;
1508
1070
  /**
1509
- * Hook called when any error occurs within the request/response lifecycle.
1510
- *
1511
- * This is a unified error handler that catches both request errors (network failures,
1512
- * timeouts, etc.) and response errors (HTTP error status codes). It's essentially
1513
- * a combination of `onRequestError` and `onResponseError` hooks.
1514
- *
1515
- * @param context - Error context containing error details, request info, and response (if available)
1516
- * @returns Promise or void - Hook can be async or sync
1071
+ * Delay between retries in milliseconds
1072
+ * @default 1000
1517
1073
  */
1518
- onError?: (context: ErrorContext<TCallApiContext$1, TErrorData$1>) => Awaitable<unknown>;
1074
+ retryDelay?: number | ((currentAttemptCount: number) => number);
1519
1075
  /**
1520
- * Hook called before the HTTP request is sent and before any internal processing of the request object begins.
1521
- *
1522
- * This is the ideal place to modify request headers, add authentication,
1523
- * implement request logging, or perform any setup before the network call.
1524
- *
1525
- * @param context - Request context with mutable request object and configuration
1526
- * @returns Promise or void - Hook can be async or sync
1527
- *
1076
+ * Maximum delay in milliseconds. Only applies to exponential strategy
1077
+ * @default 10000
1528
1078
  */
1529
- onRequest?: (context: RequestContext<TCallApiContext$1>) => Awaitable<unknown>;
1079
+ retryMaxDelay?: number;
1530
1080
  /**
1531
- * Hook called when an error occurs during the fetch request itself.
1532
- *
1533
- * This handles network-level errors like connection failures, timeouts,
1534
- * DNS resolution errors, or other issues that prevent getting an HTTP response.
1535
- * Note that HTTP error status codes (4xx, 5xx) are handled by `onResponseError`.
1536
- *
1537
- * @param context - Request error context with error details and null response
1538
- * @returns Promise or void - Hook can be async or sync
1081
+ * HTTP methods that are allowed to retry
1082
+ * @default ["GET", "POST"]
1539
1083
  */
1540
- onRequestError?: (context: RequestErrorContext<TCallApiContext$1>) => Awaitable<unknown>;
1084
+ retryMethods?: MethodUnion[];
1541
1085
  /**
1542
- * Hook called just before the HTTP request is sent and after the request has been processed.
1543
- *
1544
- * @param context - Request context with mutable request object and configuration
1086
+ * HTTP status codes that trigger a retry
1545
1087
  */
1546
- onRequestReady?: (context: RequestContext<TCallApiContext$1>) => Awaitable<unknown>;
1088
+ retryStatusCodes?: RetryStatusCodes[];
1547
1089
  /**
1548
- * Hook called during upload stream progress tracking.
1549
- *
1550
- * This hook is triggered when uploading data (like file uploads) and provides
1551
- * progress information about the upload. Useful for implementing progress bars
1552
- * or upload status indicators.
1553
- *
1554
- * @param context - Request stream context with progress event and request instance
1555
- * @returns Promise or void - Hook can be async or sync
1556
- *
1090
+ * Strategy to use when retrying
1091
+ * @default "linear"
1557
1092
  */
1558
- 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);
1559
1107
  /**
1560
- * Hook called when any HTTP response is received from the API.
1561
- *
1562
- * This hook is triggered for both successful (2xx) and error (4xx, 5xx) responses.
1563
- * It's useful for response logging, metrics collection, or any processing that
1564
- * should happen regardless of response status.
1565
- *
1566
- * @param context - Response context with either success data or error information
1567
- * @returns Promise or void - Hook can be async or sync
1568
- *
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
1569
1111
  */
1570
- onResponse?: (context: ResponseContext<TCallApiContext$1, TData$1, TErrorData$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 = {
1571
1116
  /**
1572
- * Hook called when an HTTP error response (4xx, 5xx) is received from the API.
1573
- *
1574
- * This handles server-side errors where an HTTP response was successfully received
1575
- * but indicates an error condition. Different from `onRequestError` which handles
1576
- * network-level failures.
1117
+ * The cause of the validation error.
1577
1118
  *
1578
- * @param context - Response error context with HTTP error details and response
1579
- * @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.
1580
1120
  */
1581
- onResponseError?: (context: ResponseErrorContext<TCallApiContext$1, TErrorData$1>) => Awaitable<unknown>;
1121
+ issueCause: "unknown" | `schemaConfig-(${SafeExtract<keyof CallApiSchemaConfig, "strict">})` | keyof CallApiSchema;
1582
1122
  /**
1583
- * Hook called during download stream progress tracking.
1584
- *
1585
- * This hook is triggered when downloading data (like file downloads) and provides
1586
- * progress information about the download. Useful for implementing progress bars
1587
- * 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.
1588
1189
  *
1589
- * @param context - Response stream context with progress event and response
1590
- * @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
1591
1193
  *
1194
+ * ```
1592
1195
  */
1593
- onResponseStream?: (context: ResponseStreamContext<TCallApiContext$1>) => Awaitable<unknown>;
1196
+ auth?: Auth;
1594
1197
  /**
1595
- * Hook called when a request is being retried.
1198
+ * Custom function to serialize request body objects into strings.
1596
1199
  *
1597
- * This hook is triggered before each retry attempt, providing information about
1598
- * the previous failure and the current retry attempt number. Useful for implementing
1599
- * 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.
1600
1202
  *
1601
- * @param context - Retry context with error details and retry attempt count
1602
- * @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
+ * }
1213
+ *
1214
+ * // XML serialization
1215
+ * bodySerializer: (data) => {
1216
+ * return `<request>${Object.entries(data)
1217
+ * .map(([key, value]) => `<${key}>${value}</${key}>`)
1218
+ * .join('')}</request>`;
1219
+ * }
1603
1220
  *
1221
+ * // Custom JSON with specific formatting
1222
+ * bodySerializer: (data) => JSON.stringify(data, null, 2)
1223
+ * ```
1604
1224
  */
1605
- onRetry?: (response: RetryContext<TCallApiContext$1, TErrorData$1>) => Awaitable<unknown>;
1225
+ bodySerializer?: (bodyData: Record<string, unknown>) => string;
1606
1226
  /**
1607
- * Hook called when a successful response (2xx status) is received from the API.
1608
- *
1609
- * This hook is triggered only for successful responses and provides access to
1610
- * the parsed response data. Ideal for success logging, caching, or post-processing
1611
- * of successful API responses.
1227
+ * Whether to clone the response so it can be read multiple times.
1612
1228
  *
1613
- * @param context - Success context with parsed response data and response object
1614
- * @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).
1615
1231
  *
1232
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/clone
1233
+ * @default false
1616
1234
  */
1617
- onSuccess?: (context: SuccessContext<TCallApiContext$1, TData$1>) => Awaitable<unknown>;
1235
+ cloneResponse?: boolean;
1618
1236
  /**
1619
- * Hook called when a validation error occurs.
1237
+ * Custom fetch implementation to replace the default fetch function.
1620
1238
  *
1621
- * This hook is triggered when request or response data fails validation against
1622
- * a defined schema. It provides access to the validation error details and can
1623
- * 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.
1624
1241
  *
1625
- * @param context - Validation error context with error details and response (if available)
1626
- * @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
+ * }
1627
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
+ * ```
1628
1274
  */
1629
- onValidationError?: (context: ValidationErrorContext<TCallApiContext$1>) => Awaitable<unknown>;
1630
- }
1631
- type HooksOrHooksArray<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext, TData$1 = TCallApiContext$1["Data"], TErrorData$1 = TCallApiContext$1["ErrorData"]> = { [Key in keyof Hooks<TCallApiContext$1, TData$1, TErrorData$1>]: Hooks<TCallApiContext$1, TData$1, TErrorData$1>[Key] | Array<Hooks<TCallApiContext$1, TData$1, TErrorData$1>[Key]> };
1632
- interface HookConfigOptions {
1275
+ customFetchImpl?: FetchImpl;
1633
1276
  /**
1634
- * Controls the execution mode of all composed hooks (main + plugin hooks).
1277
+ * Default HTTP error message when server doesn't provide one.
1635
1278
  *
1636
- * - **"parallel"**: All hooks execute simultaneously via Promise.all() for better performance
1637
- * - **"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.
1638
1281
  *
1639
- * This affects how ALL hooks execute together, regardless of their source (main or plugin).
1282
+ * @default "Failed to fetch data from server!"
1640
1283
  *
1641
- * @default "parallel"
1642
- */
1643
- hooksExecutionMode?: "parallel" | "sequential";
1644
- }
1645
- type RequestContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = {
1646
- /**
1647
- * Base configuration object passed to createFetchClient.
1284
+ * @example
1285
+ * ```ts
1286
+ * // Static error message
1287
+ * defaultHTTPErrorMessage: "API request failed. Please try again."
1648
1288
  *
1649
- * Contains the foundational configuration that applies to all requests
1650
- * made by this client instance, such as baseURL, default headers, and
1651
- * 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
+ * ```
1652
1307
  */
1653
- baseConfig: Exclude<BaseCallApiConfig, AnyFunction>;
1308
+ defaultHTTPErrorMessage?: string | ((context: Pick<HTTPError<TErrorData>, "errorData" | "response">) => string);
1654
1309
  /**
1655
- * 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
1656
1316
  *
1657
- * Contains configuration specific to this particular API call, which
1658
- * can override or extend the base configuration.
1659
1317
  */
1660
- config: CallApiConfig;
1318
+ forcefullyCalculateStreamSize?: boolean | {
1319
+ request?: boolean;
1320
+ response?: boolean;
1321
+ };
1661
1322
  /**
1662
- * Merged options combining base config, instance config, and default options.
1323
+ * Optional metadata field for associating additional information with requests.
1663
1324
  *
1664
- * This is the final resolved configuration that will be used for the request,
1665
- * 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
+ * ```
1666
1363
  */
1667
- options: CallApiExtraOptionsForHooks<TCallApiContext$1>;
1364
+ meta?: TCallApiContext["Meta"] extends DefaultMetaObject ? TCallApiContext["Meta"] : DefaultCallApiContext["Meta"];
1668
1365
  /**
1669
- * Merged request object ready to be sent.
1366
+ * Custom function to parse response strings into actual value instead of the default response.json().
1670
1367
  *
1671
- * Contains the final request configuration including URL, method, headers,
1672
- * body, and other fetch options. This object can be modified in onRequest
1673
- * hooks to customize the outgoing request.
1674
- */
1675
- request: CallApiRequestOptionsForHooks;
1676
- };
1677
- type ValidationErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1678
- error: PossibleValidationError;
1679
- response: Response | null;
1680
- }>;
1681
- type SuccessContext<TCallApiContext$1 extends Pick<CallApiContext, "Data" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TData$1 = TCallApiContext$1["Data"]> = UnmaskType<RequestContext<TCallApiContext$1> & {
1682
- data: NoInfer<TData$1>;
1683
- response: Response;
1684
- }>;
1685
- type ResponseContext<TCallApiContext$1 extends Pick<CallApiContext, "Data" | "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TData$1 = TCallApiContext$1["Data"], TErrorData$1 = TCallApiContext$1["ErrorData"]> = UnmaskType<RequestContext<TCallApiContext$1> & (Prettify<CallApiResultSuccessVariant<TData$1>> | Prettify<Extract<CallApiResultErrorVariant<TErrorData$1>, {
1686
- error: PossibleHTTPError<TErrorData$1>;
1687
- }>>)>;
1688
- type RequestErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext$1> & {
1689
- error: PossibleJavaScriptError;
1690
- response: null;
1691
- };
1692
- type ErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TErrorData$1 = TCallApiContext$1["ErrorData"]> = UnmaskType<RequestContext<TCallApiContext$1> & ({
1693
- error: PossibleHTTPError<TErrorData$1>;
1694
- response: Response;
1695
- } | {
1696
- error: PossibleJavaScriptOrValidationError;
1697
- response: Response | null;
1698
- })>;
1699
- type ResponseErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TErrorData$1 = TCallApiContext$1["ErrorData"]> = UnmaskType<Extract<ErrorContext<TCallApiContext$1, TErrorData$1>, {
1700
- error: PossibleHTTPError<TErrorData$1>;
1701
- }> & RequestContext<TCallApiContext$1>>;
1702
- type RetryContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TErrorData$1 = TCallApiContext$1["ErrorData"]> = UnmaskType<ErrorContext<TCallApiContext$1, TErrorData$1> & {
1703
- retryAttemptCount: number;
1704
- }>;
1705
- type RequestStreamContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1706
- event: StreamProgressEvent;
1707
- requestInstance: Request;
1708
- }>;
1709
- type ResponseStreamContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1710
- event: StreamProgressEvent;
1711
- response: Response;
1712
- }>;
1713
- //#endregion
1714
- //#region src/plugins.d.ts
1715
- type PluginSetupContext<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = RequestContext<TCallApiContext$1> & {
1716
- initURL: string;
1717
- };
1718
- type PluginInitResult = Partial<Omit<PluginSetupContext, "initURL" | "request"> & {
1719
- initURL: InitURLOrURLObject;
1720
- request: CallApiRequestOptions;
1721
- }>;
1722
- type PluginHooks<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext, TData$1 = (unknown extends TCallApiContext$1["Data"] ? never : TCallApiContext$1["Data"]), TErrorData$1 = (unknown extends TCallApiContext$1["ErrorData"] ? never : TCallApiContext$1["ErrorData"])> = HooksOrHooksArray<TCallApiContext$1, TData$1, TErrorData$1>;
1723
- interface CallApiPlugin {
1724
- /**
1725
- * Defines additional options that can be passed to callApi
1726
- */
1727
- defineExtraOptions?: (...params: never[]) => unknown;
1728
- /**
1729
- * A description for the plugin
1730
- */
1731
- description?: string;
1732
- /**
1733
- * Hooks for the plugin
1734
- */
1735
- hooks?: PluginHooks | ((context: PluginSetupContext) => Awaitable<PluginHooks>);
1736
- /**
1737
- * A unique id for the plugin
1738
- */
1739
- id: string;
1740
- /**
1741
- * 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
+ * ```
1742
1398
  */
1743
- middlewares?: Middlewares | ((context: PluginSetupContext) => Awaitable<Middlewares>);
1399
+ responseParser?: (responseString: string) => Awaitable<TData>;
1744
1400
  /**
1745
- * 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
+ * ```
1746
1433
  */
1747
- name: string;
1434
+ responseType?: TResponseType;
1748
1435
  /**
1749
- * 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
+ * ```
1750
1488
  */
1751
- schema?: BaseCallApiSchemaAndConfig;
1489
+ resultMode?: TResultMode;
1752
1490
  /**
1753
- * 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
+ * ```
1754
1533
  */
1755
- setup?: (context: PluginSetupContext) => Awaitable<PluginInitResult> | Awaitable<void>;
1534
+ throwOnError?: ThrowOnErrorType<TErrorData, TThrowOnError>;
1756
1535
  /**
1757
- * 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
+ * ```
1758
1557
  */
1759
- version?: string;
1760
- }
1761
- //#endregion
1762
- //#region src/types/default-types.d.ts
1763
- type DefaultDataType = unknown;
1764
- type DefaultPluginArray = CallApiPlugin[];
1765
- type DefaultThrowOnError = boolean;
1766
- type DefaultMetaObject = Record<string, unknown>;
1767
- type DefaultCallApiContext = Omit<Required<CallApiContext>, "Meta"> & {
1768
- Meta: GlobalMeta;
1558
+ timeout?: number;
1769
1559
  };
1770
- //#endregion
1771
- //#region src/validation.d.ts
1772
- type ResultVariant = "infer-input" | "infer-output";
1773
- 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;
1774
- type InferSchemaOutput<TSchema$1, TFallbackResult = unknown> = InferSchemaResult<TSchema$1, TFallbackResult, "infer-output">;
1775
- type InferSchemaInput<TSchema$1, TFallbackResult = unknown> = InferSchemaResult<TSchema$1, TFallbackResult, "infer-input">;
1776
- interface CallApiSchemaConfig {
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> & {
1777
1561
  /**
1778
- * The base url of the schema. By default it's the baseURL of the callApi instance.
1779
- */
1780
- baseURL?: string;
1781
- /**
1782
- * Disables runtime validation for the schema.
1783
- */
1784
- disableRuntimeValidation?: boolean;
1785
- /**
1786
- * 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.
1787
1563
  *
1788
- * This is useful when you want to validate the input but don't want any transformations
1789
- * applied by the validation schema (e.g., type coercion, default values, etc).
1790
- */
1791
- disableValidationOutputApplication?: boolean;
1792
- /**
1793
- * 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.
1794
1566
  *
1795
- * This allows you to reuse the same schema against different base URLs (for example,
1796
- * swapping between `/api/v1` and `/api/v2`) without redefining the entire schema.
1797
- */
1798
- prefix?: string;
1799
- /**
1800
- * Controls the strictness of API route validation.
1567
+ * @example
1568
+ * ```ts
1569
+ * // Add logging plugin
1801
1570
  *
1802
- * When true:
1803
- * - Only routes explicitly defined in the schema will be considered valid to typescript and the runtime.
1804
- * - Attempting to call routes not defined in the schema will result in both type errors and runtime validation errors.
1805
- * - 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
+ * });
1806
1576
  *
1807
- * When false or undefined (default):
1808
- * - All routes will be allowed, whether they are defined in the schema or not
1809
- */
1810
- strict?: boolean;
1811
- }
1812
- interface CallApiSchema {
1813
- /**
1814
- * The schema to use for validating the request body.
1815
- */
1816
- body?: StandardSchemaV1<Body | undefined> | ((body: Body) => Awaitable<Body | undefined>);
1817
- /**
1818
- * The schema to use for validating the response data.
1819
- */
1820
- data?: StandardSchemaV1 | ((data: unknown) => unknown);
1821
- /**
1822
- * 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
+ * ```
1823
1582
  */
1824
- errorData?: StandardSchemaV1 | ((errorData: unknown) => unknown);
1583
+ plugins?: TBasePluginArray;
1825
1584
  /**
1826
- * 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.
1827
1590
  */
1828
- headers?: StandardSchemaV1<HeadersOption | undefined> | ((headers: HeadersOption) => Awaitable<HeadersOption | undefined>);
1591
+ schema?: TBaseSchemaAndConfig;
1829
1592
  /**
1830
- * 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
+ * ```
1831
1657
  */
1832
- 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> & {
1833
1673
  /**
1834
- * 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
+ *
1835
1680
  */
1836
- method?: StandardSchemaV1<MethodUnion | undefined> | ((method: MethodUnion) => Awaitable<MethodUnion | undefined>);
1681
+ plugins?: TPluginArray | ((context: TComputedPluginContext) => TPluginArray);
1837
1682
  /**
1838
- * 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
+ *
1839
1689
  */
1840
- params?: StandardSchemaV1<Params | undefined> | ((params: Params) => Awaitable<Params | undefined>);
1690
+ schema?: TSchema | ((context: TComputedSchemaContext) => TSchema);
1841
1691
  /**
1842
- * 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
+ *
1843
1697
  */
1844
- query?: StandardSchemaV1<Query | undefined> | ((query: Query) => Awaitable<Query | undefined>);
1845
- }
1846
- declare const routeKeyMethods: readonly ["delete", "get", "patch", "post", "put"];
1847
- type RouteKeyMethods = (typeof routeKeyMethods)[number];
1848
- type RouteKeyMethodsURLUnion = `@${RouteKeyMethods}/`;
1849
- type BaseSchemaRouteKeyPrefixes = FallBackRouteSchemaKey | RouteKeyMethodsURLUnion;
1850
- type BaseCallApiSchemaRoutes = Partial<Record<AnyString | BaseSchemaRouteKeyPrefixes, CallApiSchema>>;
1851
- type BaseCallApiSchemaAndConfig = {
1852
- config?: CallApiSchemaConfig;
1853
- routes: BaseCallApiSchemaRoutes;
1698
+ schemaConfig?: TSchemaConfig | ((context: TComputedSchemaConfigContext) => TSchemaConfig);
1854
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;
1855
1780
  //#endregion
1856
1781
  //#region src/createFetchClient.d.ts
1857
- 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, 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>;
1858
- 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, TComputedResult = GetCallApiResult<InferSchemaResult<TSchema["data"], TData, "infer-output">, InferSchemaResult<TSchema["errorData"], TErrorData, "infer-output">, TResultMode, TThrowOnError, TResponseType, {
1859
- all: CallApiResultSuccessVariant<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>;
1860
- 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>;
1861
1786
  onlyResponse: Response;
1862
- withoutResponse: Omit<CallApiResultSuccessVariant<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>, "response">;
1863
- }, 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>;
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>;
1864
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<{
1865
1790
  [x: AnyString]: CallApiSchema | undefined;
1866
1791
  "@default"?: CallApiSchema | undefined;
@@ -1893,12 +1818,12 @@ declare const callApi: <TData = unknown, TErrorData = unknown, TResultMode exten
1893
1818
  "@patch/"?: CallApiSchema | undefined;
1894
1819
  "@post/"?: CallApiSchema | undefined;
1895
1820
  "@put/"?: CallApiSchema | undefined;
1896
- }[TCurrentRouteSchemaKey]>>, const TPluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedResult = GetCallApiResult<InferSchemaResult<TSchema["data"], TData, "infer-output">, InferSchemaResult<TSchema["errorData"], TErrorData, "infer-output">, TResultMode, TThrowOnError, TResponseType, {
1897
- all: CallApiResultSuccessVariant<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>;
1898
- 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>;
1899
1824
  onlyResponse: Response;
1900
- withoutResponse: Omit<CallApiResultSuccessVariant<GetResponseType<InferSchemaResult<TSchema["data"], TData, "infer-output">, TResponseType, ResponseTypeMap<InferSchemaResult<TSchema["data"], TData, "infer-output">>>>, "response">;
1901
- }, 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, {
1902
1827
  [x: AnyString]: CallApiSchema | undefined;
1903
1828
  "@default"?: CallApiSchema | undefined;
1904
1829
  "@delete/"?: CallApiSchema | undefined;
@@ -1908,5 +1833,5 @@ declare const callApi: <TData = unknown, TErrorData = unknown, TResultMode exten
1908
1833
  "@put/"?: CallApiSchema | undefined;
1909
1834
  }, TSchema, CallApiSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, DefaultPluginArray, TPluginArray>) => Promise<TComputedResult>;
1910
1835
  //#endregion
1911
- 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 };
1912
- //# sourceMappingURL=index-HHFgKKcn.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