@zayne-labs/callapi 1.11.25 → 1.11.27

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