@zayne-labs/callapi-plugins 4.0.26 → 4.0.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.
Files changed (2) hide show
  1. package/dist/index.d.ts +930 -980
  2. package/package.json +7 -7
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ declare const fallBackRouteSchemaKey = "@default";
10
10
  type FallBackRouteSchemaKey = typeof fallBackRouteSchemaKey;
11
11
  //#endregion
12
12
  //#endregion
13
- //#region ../callapi/dist/validation-BeCBQ6_6.d.ts
13
+ //#region ../callapi/dist/index-HHFgKKcn.d.ts
14
14
  //#region src/types/type-helpers.d.ts
15
15
  type AnyString = string & NonNullable<unknown>;
16
16
  type AnyNumber = number & NonNullable<unknown>;
@@ -75,231 +75,221 @@ type CustomAuth = {
75
75
  };
76
76
  type Auth = PossibleAuthValueOrGetter | BearerOrTokenAuth | BasicAuth | CustomAuth;
77
77
  //#endregion
78
- //#region src/utils/external/body.d.ts
79
-
80
- //#endregion
81
- //#region src/types/default-types.d.ts
82
- type DefaultDataType = unknown;
83
- type DefaultPluginArray = CallApiPlugin[];
84
- type DefaultThrowOnError = boolean;
85
- //#endregion
86
- //#region src/types/standard-schema.d.ts
87
- /**
88
- * The Standard Schema interface.
89
- * @see https://github.com/standard-schema/standard-schema
90
- */
91
- interface StandardSchemaV1<Input$1 = unknown, Output$1 = Input$1> {
92
- /**
93
- * The Standard Schema properties.
94
- */
95
- readonly "~standard": StandardSchemaV1.Props<Input$1, Output$1>;
96
- }
97
- declare namespace StandardSchemaV1 {
98
- /**
99
- * The Standard Schema properties interface.
100
- */
101
- interface Props<Input = unknown, Output = Input> {
102
- /**
103
- * Inferred types associated with the schema.
104
- */
105
- readonly types?: Types<Input, Output> | undefined;
106
- /**
107
- * Validates unknown input values.
108
- */
109
- readonly validate: (value: unknown) => Promise<Result<Output>> | Result<Output>;
110
- /**
111
- * The vendor name of the schema library.
112
- */
113
- readonly vendor: string;
114
- /**
115
- * The version number of the standard.
116
- */
117
- readonly version: 1;
118
- }
119
- /**
120
- * The result interface of the validate function.
121
- */
122
- type Result<Output> = FailureResult | SuccessResult<Output>;
123
- /**
124
- * The result interface if validation succeeds.
125
- */
126
- interface SuccessResult<Output> {
127
- /**
128
- * The non-existent issues.
129
- */
130
- readonly issues?: undefined;
131
- /**
132
- * The typed output value.
133
- */
134
- readonly value: Output;
135
- }
136
- /**
137
- * The result interface if validation fails.
138
- */
139
- interface FailureResult {
140
- /**
141
- * The issues of failed validation.
142
- */
143
- readonly issues: readonly Issue[];
144
- }
145
- /**
146
- * The issue interface of the failure output.
147
- */
148
- interface Issue {
149
- /**
150
- * The error message of the issue.
151
- */
152
- readonly message: string;
153
- /**
154
- * The path of the issue, if any.
155
- */
156
- readonly path?: ReadonlyArray<PathSegment | PropertyKey> | undefined;
157
- }
158
- /**
159
- * The path segment interface of the issue.
160
- */
161
- interface PathSegment {
162
- /**
163
- * The key representing a path segment.
164
- */
165
- readonly key: PropertyKey;
166
- }
167
- /**
168
- * The Standard Schema types interface.
169
- */
170
- interface Types<Input = unknown, Output = Input> {
171
- /** The input type of the schema. */
172
- readonly input: Input;
173
- /** The output type of the schema. */
174
- readonly output: Output;
175
- }
176
- /**
177
- * Infers the input type of a Standard Schema.
178
- */
179
- type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
180
- /**
181
- * Infers the output type of a Standard Schema.
182
- */
183
- type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
184
- }
185
- //#endregion
186
- //#region src/utils/external/error.d.ts
187
- type HTTPErrorDetails<TErrorData$1> = Pick<CallApiExtraOptions, "defaultHTTPErrorMessage"> & {
188
- errorData: TErrorData$1;
189
- response: Response;
190
- };
191
- declare class HTTPError<TErrorData$1 = Record<string, unknown>> extends Error {
192
- errorData: HTTPErrorDetails<TErrorData$1>["errorData"];
193
- readonly httpErrorSymbol: symbol;
194
- name: "HTTPError";
195
- response: HTTPErrorDetails<TErrorData$1>["response"];
196
- constructor(errorDetails: HTTPErrorDetails<TErrorData$1>, errorOptions?: ErrorOptions);
78
+ //#region src/dedupe.d.ts
79
+ type DedupeStrategyUnion = UnmaskType<"cancel" | "defer" | "none">;
80
+ type DedupeOptionKeys = Exclude<keyof DedupeOptions, "dedupe">;
81
+ type InnerDedupeOptions = { [Key in DedupeOptionKeys as RemovePrefix<"dedupe", Key>]?: DedupeOptions[Key] };
82
+ type DedupeOptions = {
197
83
  /**
198
- * @description Checks if the given error is an instance of HTTPError
199
- * @param error - The error to check
200
- * @returns true if the error is an instance of HTTPError, false otherwise
84
+ * All dedupe options in a single object instead of separate properties
201
85
  */
202
- static isError<TErrorData>(error: unknown): error is HTTPError<TErrorData$1>;
203
- }
204
- type SafeExtract<TUnion, TKey extends TUnion> = Extract<TUnion, TKey>;
205
- type ValidationErrorDetails = {
86
+ dedupe?: InnerDedupeOptions;
206
87
  /**
207
- * The cause of the validation error.
88
+ * Controls the scope of request deduplication caching.
208
89
  *
209
- * 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.
90
+ * - `"global"`: Shares deduplication cache across all `createFetchClient` instances with the same `dedupeCacheScopeKey`.
91
+ * Useful for applications with multiple API clients that should share deduplication state.
92
+ * - `"local"`: Limits deduplication to requests within the same `createFetchClient` instance.
93
+ * Provides better isolation and is recommended for most use cases.
94
+ *
95
+ *
96
+ * **Real-world Scenarios:**
97
+ * - Use `"global"` when you have multiple API clients (user service, auth service, etc.) that might make overlapping requests
98
+ * - Use `"local"` (default) for single-purpose clients or when you want strict isolation between different parts of your app
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * // Local scope - each client has its own deduplication cache
103
+ * const userClient = createFetchClient({ baseURL: "/api/users" });
104
+ * const postClient = createFetchClient({ baseURL: "/api/posts" });
105
+ * // These clients won't share deduplication state
106
+ *
107
+ * // Global scope - share cache across related clients
108
+ * const userClient = createFetchClient({
109
+ * baseURL: "/api/users",
110
+ * dedupeCacheScope: "global",
111
+ * });
112
+ * const postClient = createFetchClient({
113
+ * baseURL: "/api/posts",
114
+ * dedupeCacheScope: "global",
115
+ * });
116
+ * // These clients will share deduplication state
117
+ * ```
118
+ *
119
+ * @default "local"
210
120
  */
211
- issueCause: "unknown" | `schemaConfig-(${SafeExtract<keyof CallApiSchemaConfig, "strict">})` | keyof CallApiSchema;
121
+ dedupeCacheScope?: "global" | "local";
212
122
  /**
213
- * The issues that caused the validation error.
123
+ * Unique namespace for the global deduplication cache when using `dedupeCacheScope: "global"`.
124
+ *
125
+ * This creates logical groupings of deduplication caches. All instances with the same key
126
+ * will share the same cache namespace, allowing fine-grained control over which clients
127
+ * share deduplication state.
128
+ *
129
+ * **Best Practices:**
130
+ * - Use descriptive names that reflect the logical grouping (e.g., "user-service", "analytics-api")
131
+ * - Keep scope keys consistent across related API clients
132
+ * - Consider using different scope keys for different environments (dev, staging, prod)
133
+ * - Avoid overly broad scope keys that might cause unintended cache sharing
134
+ *
135
+ * **Cache Management:**
136
+ * - Each scope key maintains its own independent cache
137
+ * - Caches are automatically cleaned up when no references remain
138
+ * - Consider the memory implications of multiple global scopes
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * // Group related API clients together
143
+ * const userClient = createFetchClient({
144
+ * baseURL: "/api/users",
145
+ * dedupeCacheScope: "global",
146
+ * dedupeCacheScopeKey: "user-service"
147
+ * });
148
+ * const profileClient = createFetchClient({
149
+ * baseURL: "/api/profiles",
150
+ * dedupeCacheScope: "global",
151
+ * dedupeCacheScopeKey: "user-service" // Same scope - will share cache
152
+ * });
153
+ *
154
+ * // Separate analytics client with its own cache
155
+ * const analyticsClient = createFetchClient({
156
+ * baseURL: "/api/analytics",
157
+ * dedupeCacheScope: "global",
158
+ * dedupeCacheScopeKey: "analytics-service" // Different scope
159
+ * });
160
+ *
161
+ * // Environment-specific scoping
162
+ * const apiClient = createFetchClient({
163
+ * dedupeCacheScope: "global",
164
+ * dedupeCacheScopeKey: `api-${process.env.NODE_ENV}` // "api-development", "api-production", etc.
165
+ * });
166
+ * ```
167
+ *
168
+ * @default "default"
214
169
  */
215
- issues: readonly StandardSchemaV1.Issue[];
170
+ dedupeCacheScopeKey?: "default" | AnyString | ((context: RequestContext) => string | undefined);
216
171
  /**
217
- * The response from server, if any.
172
+ * Custom key generator for request deduplication.
173
+ *
174
+ * Override the default key generation strategy to control exactly which requests
175
+ * are considered duplicates. The default key combines URL, method, body, and
176
+ * relevant headers (excluding volatile ones like 'Date', 'Authorization', etc.).
177
+ *
178
+ * **Default Key Generation:**
179
+ * The auto-generated key includes:
180
+ * - Full request URL (including query parameters)
181
+ * - HTTP method (GET, POST, etc.)
182
+ * - Request body (for POST/PUT/PATCH requests)
183
+ * - Stable headers (excludes Date, Authorization, User-Agent, etc.)
184
+ *
185
+ * **Custom Key Best Practices:**
186
+ * - Include only the parts of the request that should affect deduplication
187
+ * - Avoid including volatile data (timestamps, random IDs, etc.)
188
+ * - Consider performance - simpler keys are faster to compute and compare
189
+ * - Ensure keys are deterministic for the same logical request
190
+ * - Use consistent key formats across your application
191
+ *
192
+ * **Performance Considerations:**
193
+ * - Function-based keys are computed on every request - keep them lightweight
194
+ * - String keys are fastest but least flexible
195
+ * - Consider caching expensive key computations if needed
196
+ *
197
+ * @example
198
+ * ```ts
199
+ * import { callApi } from "@zayne-labs/callapi";
200
+ *
201
+ * // Simple static key - useful for singleton requests
202
+ * const config = callApi("/api/config", {
203
+ * dedupeKey: "app-config",
204
+ * dedupeStrategy: "defer" // Share the same config across all requests
205
+ * });
206
+ *
207
+ * // URL and method only - ignore headers and body
208
+ * const userData = callApi("/api/user/123", {
209
+ * dedupeKey: (context) => `${context.options.method}:${context.options.fullURL}`
210
+ * });
211
+ *
212
+ * // Include specific headers in deduplication
213
+ * const apiCall = callApi("/api/data", {
214
+ * dedupeKey: (context) => {
215
+ * const authHeader = context.request.headers.get("Authorization");
216
+ * return `${context.options.fullURL}-${authHeader}`;
217
+ * }
218
+ * });
219
+ *
220
+ * // User-specific deduplication
221
+ * const userSpecificCall = callApi("/api/dashboard", {
222
+ * dedupeKey: (context) => {
223
+ * const userId = context.options.fullURL.match(/user\/(\d+)/)?.[1];
224
+ * return `dashboard-${userId}`;
225
+ * }
226
+ * });
227
+ *
228
+ * // Ignore certain query parameters
229
+ * const searchCall = callApi("/api/search?q=test&timestamp=123456", {
230
+ * dedupeKey: (context) => {
231
+ * const url = new URL(context.options.fullURL);
232
+ * url.searchParams.delete("timestamp"); // Remove volatile param
233
+ * return `search:${url.toString()}`;
234
+ * }
235
+ * });
236
+ * ```
237
+ *
238
+ * @default Auto-generated from request details
218
239
  */
219
- response: Response | null;
220
- };
221
- declare class ValidationError extends Error {
222
- errorData: ValidationErrorDetails["issues"];
223
- issueCause: ValidationErrorDetails["issueCause"];
224
- name: "ValidationError";
225
- response: ValidationErrorDetails["response"];
226
- readonly validationErrorSymbol: symbol;
227
- constructor(details: ValidationErrorDetails, errorOptions?: ErrorOptions);
240
+ dedupeKey?: string | ((context: RequestContext) => string | undefined);
228
241
  /**
229
- * @description Checks if the given error is an instance of ValidationError
230
- * @param error - The error to check
231
- * @returns true if the error is an instance of ValidationError, false otherwise
232
- */
233
- static isError(error: unknown): error is ValidationError;
234
- }
235
- //#endregion
236
- //#region src/result.d.ts
237
- type Parser<TData$1> = (responseString: string) => Awaitable<TData$1>;
238
- declare const getResponseType: <TResponse>(response: Response, parser: Parser<TResponse>) => {
239
- arrayBuffer: () => Promise<ArrayBuffer>;
240
- blob: () => Promise<Blob>;
241
- formData: () => Promise<FormData>;
242
- json: () => Promise<TResponse>;
243
- stream: () => ReadableStream<Uint8Array<ArrayBuffer>> | null;
244
- text: () => Promise<string>;
245
- };
246
- type InitResponseTypeMap<TResponse$1 = unknown> = ReturnType<typeof getResponseType<TResponse$1>>;
247
- type ResponseTypeUnion = keyof InitResponseTypeMap;
248
- type ResponseTypePlaceholder = null;
249
- type ResponseTypeType = ResponseTypePlaceholder | ResponseTypeUnion;
250
- type ResponseTypeMap<TResponse$1> = { [Key in keyof InitResponseTypeMap<TResponse$1>]: Awaited<ReturnType<InitResponseTypeMap<TResponse$1>[Key]>> };
251
- 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;
252
- type CallApiResultSuccessVariant<TData$1> = {
253
- data: NoInfer<TData$1>;
254
- error: null;
255
- response: Response;
256
- };
257
- type PossibleJavaScriptError = UnmaskType<{
258
- errorData: false;
259
- message: string;
260
- name: "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | AnyString;
261
- originalError: DOMException | Error | SyntaxError | TypeError;
262
- }>;
263
- type PossibleHTTPError<TErrorData$1> = UnmaskType<{
264
- errorData: NoInfer<TErrorData$1>;
265
- message: string;
266
- name: "HTTPError";
267
- originalError: HTTPError;
268
- }>;
269
- type PossibleValidationError = UnmaskType<{
270
- errorData: ValidationError["errorData"];
271
- issueCause: ValidationError["issueCause"];
272
- message: string;
273
- name: "ValidationError";
274
- originalError: ValidationError;
275
- }>;
276
- type PossibleJavaScriptOrValidationError = UnmaskType<PossibleJavaScriptError | PossibleValidationError>;
277
- type CallApiResultErrorVariant<TErrorData$1> = {
278
- data: null;
279
- error: PossibleHTTPError<TErrorData$1>;
280
- response: Response;
281
- } | {
282
- data: null;
283
- error: PossibleJavaScriptOrValidationError;
284
- response: Response | null;
285
- };
286
- type CallApiSuccessOrErrorVariant<TData$1, TError> = CallApiResultErrorVariant<TError> | CallApiResultSuccessVariant<TData$1>;
287
- 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<{
288
- all: TComputedResult;
289
- onlyData: TComputedResult["data"];
290
- onlyResponse: TComputedResult["response"];
291
- withoutResponse: DistributiveOmit<TComputedResult, "response">;
292
- }>;
293
- type ResultModeMapWithException<TData$1, TResponseType extends ResponseTypeType, TComputedData = GetResponseType<TData$1, TResponseType>, TComputedResult extends CallApiResultSuccessVariant<TComputedData> = CallApiResultSuccessVariant<TComputedData>> = {
294
- all: TComputedResult;
295
- onlyData: TComputedResult["data"];
296
- onlyResponse: TComputedResult["response"];
297
- withoutResponse: DistributiveOmit<TComputedResult, "response">;
242
+ * Strategy for handling duplicate requests. Can be a static string or callback function.
243
+ *
244
+ * **Available Strategies:**
245
+ * - `"cancel"`: Cancel previous request when new one starts (good for search)
246
+ * - `"defer"`: Share response between duplicate requests (good for config loading)
247
+ * - `"none"`: No deduplication, all requests execute independently
248
+ *
249
+ * @example
250
+ * ```ts
251
+ * // Static strategies
252
+ * const searchClient = createFetchClient({
253
+ * dedupeStrategy: "cancel" // Cancel previous searches
254
+ * });
255
+ *
256
+ * const configClient = createFetchClient({
257
+ * dedupeStrategy: "defer" // Share config across components
258
+ * });
259
+ *
260
+ * // Dynamic strategy based on request
261
+ * const smartClient = createFetchClient({
262
+ * dedupeStrategy: (context) => {
263
+ * return context.options.method === "GET" ? "defer" : "cancel";
264
+ * }
265
+ * });
266
+ *
267
+ * // Search-as-you-type with cancel strategy
268
+ * const handleSearch = async (query: string) => {
269
+ * try {
270
+ * const { data } = await callApi("/api/search", {
271
+ * method: "POST",
272
+ * body: { query },
273
+ * dedupeStrategy: "cancel",
274
+ * dedupeKey: "search" // Cancel previous searches, only latest one goes through
275
+ * });
276
+ *
277
+ * updateSearchResults(data);
278
+ * } catch (error) {
279
+ * if (error.name === "AbortError") {
280
+ * // Previous search cancelled - (expected behavior)
281
+ * return;
282
+ * }
283
+ * console.error("Search failed:", error);
284
+ * }
285
+ * };
286
+ *
287
+ * ```
288
+ *
289
+ * @default "cancel"
290
+ */
291
+ dedupeStrategy?: DedupeStrategyUnion | ((context: RequestContext) => DedupeStrategyUnion);
298
292
  };
299
- 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>;
300
- type ResultModePlaceholder = null;
301
- type ResultModeUnion = keyof ResultModeMap;
302
- type ResultModeType = ResultModePlaceholder | ResultModeUnion;
303
293
  //#endregion
304
294
  //#region src/middlewares.d.ts
305
295
  type FetchImpl = UnmaskType<(input: string | Request | URL, init?: RequestInit) => Promise<Response>>;
@@ -460,563 +450,333 @@ interface URLOptions {
460
450
  query?: Query;
461
451
  }
462
452
  //#endregion
463
- //#region src/plugins.d.ts
464
- type PluginSetupContext<TPluginExtraOptions = unknown> = PluginExtraOptions<TPluginExtraOptions> & RequestContext & {
465
- initURL: string;
466
- };
467
- type PluginInitResult = Partial<Omit<PluginSetupContext, "initURL" | "request"> & {
468
- initURL: InitURLOrURLObject;
469
- request: CallApiRequestOptions;
470
- }>;
471
- type PluginHooks<TData$1 = never, TErrorData$1 = never, TMoreOptions = unknown> = HooksOrHooksArray<TData$1, TErrorData$1, TMoreOptions>;
472
- interface CallApiPlugin {
473
- /**
474
- * Defines additional options that can be passed to callApi
475
- */
476
- defineExtraOptions?: (...params: never[]) => unknown;
477
- /**
478
- * A description for the plugin
479
- */
480
- description?: string;
481
- /**
482
- * Hooks for the plugin
483
- */
484
- hooks?: PluginHooks | ((context: PluginSetupContext) => Awaitable<PluginHooks>);
485
- /**
486
- * A unique id for the plugin
487
- */
488
- id: string;
489
- /**
490
- * Middlewares that for the plugin
491
- */
492
- middlewares?: Middlewares | ((context: PluginSetupContext) => Awaitable<Middlewares>);
493
- /**
494
- * A name for the plugin
495
- */
496
- name: string;
497
- /**
498
- * Base schema for the client.
499
- */
500
- schema?: BaseCallApiSchemaAndConfig;
501
- /**
502
- * A function that will be called when the plugin is initialized. This will be called before the any of the other internal functions.
503
- */
504
- setup?: (context: PluginSetupContext) => Awaitable<PluginInitResult> | Awaitable<void>;
505
- /**
506
- * A version for the plugin
507
- */
508
- version?: string;
509
- }
510
- //#endregion
511
- //#region src/utils/external/define.d.ts
512
-
513
- //#endregion
514
- //#region src/stream.d.ts
515
- type StreamProgressEvent = {
516
- /**
517
- * Current chunk of data being streamed
518
- */
519
- chunk: Uint8Array;
520
- /**
521
- * Progress in percentage
522
- */
523
- progress: number;
524
- /**
525
- * Total size of data in bytes
526
- */
527
- totalBytes: number;
528
- /**
529
- * Amount of data transferred so far
530
- */
531
- transferredBytes: number;
532
- };
533
- declare global {
534
- interface ReadableStream<R> {
535
- [Symbol.asyncIterator]: () => AsyncIterableIterator<R>;
536
- }
537
- }
538
- //#endregion
539
- //#region src/hooks.d.ts
540
- type PluginExtraOptions<TPluginOptions = unknown> = {
541
- /** Plugin-specific options passed to the plugin configuration */
542
- options: Partial<TPluginOptions>;
543
- };
544
- interface Hooks<TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TPluginOptions = unknown> {
545
- /**
546
- * Hook called when any error occurs within the request/response lifecycle.
547
- *
548
- * This is a unified error handler that catches both request errors (network failures,
549
- * timeouts, etc.) and response errors (HTTP error status codes). It's essentially
550
- * a combination of `onRequestError` and `onResponseError` hooks.
551
- *
552
- * @param context - Error context containing error details, request info, and response (if available)
553
- * @returns Promise or void - Hook can be async or sync
554
- */
555
- onError?: (context: ErrorContext<TErrorData$1> & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
556
- /**
557
- * Hook called before the HTTP request is sent and before any internal processing of the request object begins.
558
- *
559
- * This is the ideal place to modify request headers, add authentication,
560
- * implement request logging, or perform any setup before the network call.
561
- *
562
- * @param context - Request context with mutable request object and configuration
563
- * @returns Promise or void - Hook can be async or sync
564
- *
565
- */
566
- onRequest?: (context: RequestContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
567
- /**
568
- * Hook called when an error occurs during the fetch request itself.
569
- *
570
- * This handles network-level errors like connection failures, timeouts,
571
- * DNS resolution errors, or other issues that prevent getting an HTTP response.
572
- * Note that HTTP error status codes (4xx, 5xx) are handled by `onResponseError`.
573
- *
574
- * @param context - Request error context with error details and null response
575
- * @returns Promise or void - Hook can be async or sync
576
- */
577
- onRequestError?: (context: RequestErrorContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
578
- /**
579
- * Hook called just before the HTTP request is sent and after the request has been processed.
580
- *
581
- * @param context - Request context with mutable request object and configuration
582
- */
583
- onRequestReady?: (context: RequestContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
453
+ //#region src/types/conditional-types.d.ts
454
+ /**
455
+ * @description Makes a type partial if the output type of TSchema is not provided or has undefined in the union, otherwise makes it required
456
+ */
457
+ type MakeSchemaOptionRequiredIfDefined<TSchemaOption extends CallApiSchema[keyof CallApiSchema], TObject> = undefined extends InferSchemaOutput<TSchemaOption, undefined> ? TObject : Required<TObject>;
458
+ 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;
459
+ type ApplyStrictConfig<TSchemaConfig$1 extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = TSchemaConfig$1["strict"] extends true ? TSchemaRouteKeys :
460
+ // eslint-disable-next-line perfectionist/sort-union-types -- Don't sort union types
461
+ TSchemaRouteKeys | Exclude<InitURLOrURLObject, RouteKeyMethodsURLUnion>;
462
+ type ApplySchemaConfiguration<TSchemaConfig$1 extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = ApplyStrictConfig<TSchemaConfig$1, ApplyURLBasedConfig<TSchemaConfig$1, TSchemaRouteKeys>>;
463
+ type InferAllRouteKeys<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TSchemaConfig$1 extends CallApiSchemaConfig> = ApplySchemaConfiguration<TSchemaConfig$1, Exclude<Extract<keyof TBaseSchemaRoutes$1, string>, FallBackRouteSchemaKey>>;
464
+ type InferInitURL<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TSchemaConfig$1 extends CallApiSchemaConfig> = keyof TBaseSchemaRoutes$1 extends never ? InitURLOrURLObject : InferAllRouteKeys<TBaseSchemaRoutes$1, TSchemaConfig$1>;
465
+ 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;
466
+ type JsonPrimitive = boolean | number | string | null | undefined;
467
+ type SerializableObject = Record<PropertyKey, unknown>;
468
+ type SerializableArray = Array<JsonPrimitive | SerializableObject> | ReadonlyArray<JsonPrimitive | SerializableObject>;
469
+ type Body = UnmaskType<Exclude<RequestInit["body"], undefined> | SerializableArray | SerializableObject>;
470
+ type InferBodyOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["body"], {
584
471
  /**
585
- * Hook called during upload stream progress tracking.
586
- *
587
- * This hook is triggered when uploading data (like file uploads) and provides
588
- * progress information about the upload. Useful for implementing progress bars
589
- * or upload status indicators.
590
- *
591
- * @param context - Request stream context with progress event and request instance
592
- * @returns Promise or void - Hook can be async or sync
593
- *
472
+ * Body of the request, can be a object or any other supported body type.
594
473
  */
595
- onRequestStream?: (context: RequestStreamContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
474
+ body?: InferSchemaOutput<TSchema$1["body"], Body>;
475
+ }>;
476
+ type MethodUnion = UnmaskType<"CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE" | AnyString>;
477
+ type InferMethodFromURL<TInitURL$1> = string extends TInitURL$1 ? MethodUnion : TInitURL$1 extends `@${infer TMethod extends RouteKeyMethods}/${string}` ? Uppercase<TMethod> : MethodUnion;
478
+ type InferMethodOption<TSchema$1 extends CallApiSchema, TInitURL$1> = MakeSchemaOptionRequiredIfDefined<TSchema$1["method"], {
596
479
  /**
597
- * Hook called when any HTTP response is received from the API.
598
- *
599
- * This hook is triggered for both successful (2xx) and error (4xx, 5xx) responses.
600
- * It's useful for response logging, metrics collection, or any processing that
601
- * should happen regardless of response status.
602
- *
603
- * @param context - Response context with either success data or error information
604
- * @returns Promise or void - Hook can be async or sync
605
- *
480
+ * HTTP method for the request.
481
+ * @default "GET"
606
482
  */
607
- onResponse?: (context: ResponseContext<TData$1, TErrorData$1> & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
483
+ method?: InferSchemaOutput<TSchema$1["method"], InferMethodFromURL<TInitURL$1>>;
484
+ }>;
485
+ type HeadersOption = UnmaskType<Record<"Authorization", CommonAuthorizationHeaders | undefined> | Record<"Content-Type", CommonContentTypes | undefined> | Record<CommonRequestHeaders, string | undefined> | Record<string, string | undefined> | Array<[string, string]>>;
486
+ type InferHeadersOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["headers"], {
608
487
  /**
609
- * Hook called when an HTTP error response (4xx, 5xx) is received from the API.
610
- *
611
- * This handles server-side errors where an HTTP response was successfully received
612
- * but indicates an error condition. Different from `onRequestError` which handles
613
- * network-level failures.
614
- *
615
- * @param context - Response error context with HTTP error details and response
616
- * @returns Promise or void - Hook can be async or sync
488
+ * Headers to be used in the request.
617
489
  */
618
- onResponseError?: (context: ResponseErrorContext<TErrorData$1> & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
490
+ headers?: InferSchemaOutput<TSchema$1["headers"], HeadersOption> | ((context: {
491
+ baseHeaders: NonNullable<HeadersOption>;
492
+ }) => InferSchemaOutput<TSchema$1["headers"], HeadersOption>);
493
+ }>;
494
+ type InferRequestOptions<TSchema$1 extends CallApiSchema, TInitURL$1 extends InferInitURL<BaseCallApiSchemaRoutes, CallApiSchemaConfig>> = InferBodyOption<TSchema$1> & InferHeadersOption<TSchema$1> & InferMethodOption<TSchema$1, TInitURL$1>;
495
+ type InferMetaOption<TSchema$1 extends CallApiSchema, TCallApiContext$1 extends CallApiContext> = MakeSchemaOptionRequiredIfDefined<TSchema$1["meta"], {
619
496
  /**
620
- * Hook called during download stream progress tracking.
497
+ * - An optional field you can fill with additional information,
498
+ * to associate with the request, typically used for logging or tracing.
621
499
  *
622
- * This hook is triggered when downloading data (like file downloads) and provides
623
- * progress information about the download. Useful for implementing progress bars
624
- * or download status indicators.
500
+ * - A good use case for this, would be to use the info to handle specific cases in any of the shared interceptors.
625
501
  *
626
- * @param context - Response stream context with progress event and response
627
- * @returns Promise or void - Hook can be async or sync
502
+ * @example
503
+ * ```ts
504
+ * const callMainApi = callApi.create({
505
+ * baseURL: "https://main-api.com",
506
+ * onResponseError: ({ response, options }) => {
507
+ * if (options.meta?.userId) {
508
+ * console.error(`User ${options.meta.userId} made an error`);
509
+ * }
510
+ * },
511
+ * });
628
512
  *
513
+ * const response = await callMainApi({
514
+ * url: "https://example.com/api/data",
515
+ * meta: { userId: "123" },
516
+ * });
517
+ * ```
629
518
  */
630
- onResponseStream?: (context: ResponseStreamContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
519
+ meta?: InferSchemaOutput<TSchema$1["meta"], TCallApiContext$1["Meta"]>;
520
+ }>;
521
+ type InferQueryOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["query"], {
631
522
  /**
632
- * Hook called when a request is being retried.
633
- *
634
- * This hook is triggered before each retry attempt, providing information about
635
- * the previous failure and the current retry attempt number. Useful for implementing
636
- * custom retry logic, exponential backoff, or retry logging.
637
- *
638
- * @param context - Retry context with error details and retry attempt count
639
- * @returns Promise or void - Hook can be async or sync
640
- *
523
+ * Parameters to be appended to the URL (i.e: /:id)
641
524
  */
642
- onRetry?: (response: RetryContext<TErrorData$1> & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
525
+ query?: InferSchemaOutput<TSchema$1["query"], Query>;
526
+ }>;
527
+ type EmptyString = "";
528
+ type EmptyTuple = readonly [];
529
+ type StringTuple = readonly string[];
530
+ type PossibleParamNamePatterns = `${string}:${string}` | `${string}{${string}}${"" | AnyString}`;
531
+ 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;
532
+ type ConvertParamNamesToRecord<TParamNames extends StringTuple> = Prettify<TParamNames extends (readonly [infer TFirstParamName extends string, ...infer TRemainingParamNames extends StringTuple]) ? Record<TFirstParamName, AllowedQueryParamValues> & ConvertParamNamesToRecord<TRemainingParamNames> : NonNullable<unknown>>;
533
+ type ConvertParamNamesToTuple<TParamNames extends StringTuple> = TParamNames extends readonly [string, ...infer TRemainingParamNames extends StringTuple] ? [AllowedQueryParamValues, ...ConvertParamNamesToTuple<TRemainingParamNames>] : [];
534
+ type InferParamsFromRoute<TCurrentRoute$1> = ExtractRouteParamNames<TCurrentRoute$1> extends StringTuple ? ExtractRouteParamNames<TCurrentRoute$1> extends EmptyTuple ? Params : ConvertParamNamesToRecord<ExtractRouteParamNames<TCurrentRoute$1>> | ConvertParamNamesToTuple<ExtractRouteParamNames<TCurrentRoute$1>> : Params;
535
+ 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>;
536
+ type InferParamsOption<TSchema$1 extends CallApiSchema, TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey$1 extends string> = MakeParamsOptionRequired<TSchema$1["params"], TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1, {
643
537
  /**
644
- * Hook called when a successful response (2xx status) is received from the API.
645
- *
646
- * This hook is triggered only for successful responses and provides access to
647
- * the parsed response data. Ideal for success logging, caching, or post-processing
648
- * of successful API responses.
649
- *
650
- * @param context - Success context with parsed response data and response object
651
- * @returns Promise or void - Hook can be async or sync
652
- *
538
+ * Parameters to be appended to the URL (i.e: /:id)
653
539
  */
654
- onSuccess?: (context: SuccessContext<TData$1> & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
540
+ params?: InferSchemaOutput<TSchema$1["params"], InferParamsFromRoute<TCurrentRouteSchemaKey$1>>;
541
+ }>;
542
+ 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>;
543
+ type InferPluginOptions<TPluginArray$1 extends CallApiPlugin[]> = UnionToIntersection<TPluginArray$1 extends Array<infer TPlugin> ? TPlugin extends CallApiPlugin ? TPlugin["defineExtraOptions"] extends AnyFunction$1<infer TReturnedSchema> ? InferSchemaOutput<TReturnedSchema> : never : never : never>;
544
+ type ResultModeOption<TErrorData$1, TResultMode$1 extends ResultModeType> = TErrorData$1 extends false ? {
545
+ resultMode: "onlyData";
546
+ } : TErrorData$1 extends false | undefined ? {
547
+ resultMode?: "onlyData";
548
+ } : {
549
+ resultMode?: TResultMode$1;
550
+ };
551
+ type ThrowOnErrorUnion = boolean;
552
+ type ThrowOnErrorType<TErrorData$1, TThrowOnError$1 extends ThrowOnErrorUnion> = TThrowOnError$1 | ((context: ErrorContext<{
553
+ ErrorData: TErrorData$1;
554
+ }>) => TThrowOnError$1);
555
+ type ThrowOnErrorOption<TErrorData$1, TThrowOnError$1 extends ThrowOnErrorUnion> = TErrorData$1 extends false ? {
556
+ throwOnError: true;
557
+ } : TErrorData$1 extends false | undefined ? {
558
+ throwOnError?: true;
559
+ } : {
560
+ throwOnError?: ThrowOnErrorType<TErrorData$1, TThrowOnError$1>;
561
+ };
562
+ //#endregion
563
+ //#region src/types/standard-schema.d.ts
564
+ /**
565
+ * The Standard Schema interface.
566
+ * @see https://github.com/standard-schema/standard-schema
567
+ */
568
+ interface StandardSchemaV1<Input$1 = unknown, Output$1 = Input$1> {
655
569
  /**
656
- * Hook called when a validation error occurs.
657
- *
658
- * This hook is triggered when request or response data fails validation against
659
- * a defined schema. It provides access to the validation error details and can
660
- * be used for custom error handling, logging, or fallback behavior.
661
- *
662
- * @param context - Validation error context with error details and response (if available)
663
- * @returns Promise or void - Hook can be async or sync
664
- *
570
+ * The Standard Schema properties.
665
571
  */
666
- onValidationError?: (context: ValidationErrorContext & PluginExtraOptions<TPluginOptions>) => Awaitable<unknown>;
572
+ readonly "~standard": StandardSchemaV1.Props<Input$1, Output$1>;
667
573
  }
668
- 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]> };
669
- interface HookConfigOptions {
574
+ declare namespace StandardSchemaV1 {
670
575
  /**
671
- * Controls the execution mode of all composed hooks (main + plugin hooks).
672
- *
673
- * - **"parallel"**: All hooks execute simultaneously via Promise.all() for better performance
674
- * - **"sequential"**: All hooks execute one by one in registration order via await in a loop
675
- *
676
- * This affects how ALL hooks execute together, regardless of their source (main or plugin).
677
- *
678
- * @default "parallel"
679
- *
680
- * @example
681
- * ```ts
682
- * // Parallel execution (default) - all hooks run simultaneously
683
- * hooksExecutionMode: "parallel"
684
- *
685
- * // Sequential execution - hooks run one after another
686
- * hooksExecutionMode: "sequential"
687
- *
688
- * // Use case: Hooks have dependencies and must run in order
689
- * const client = callApi.create({
690
- * hooksExecutionMode: "sequential",
691
- * plugins: [transformPlugin],
692
- * onRequest: (ctx) => {
693
- * // This runs first, then transform plugin runs
694
- * ctx.request.headers["x-request-id"] = generateId();
695
- * }
696
- * });
697
- *
698
- * // Use case: Independent operations can run in parallel for speed
699
- * const client = callApi.create({
700
- * hooksExecutionMode: "parallel", // Default
701
- * plugins: [metricsPlugin, cachePlugin, loggingPlugin],
702
- * onRequest: (ctx) => {
703
- * // All hooks (main + plugins) run simultaneously
704
- * addRequestTimestamp(ctx.request);
705
- * }
706
- * });
707
- *
708
- * // Use case: Error handling hooks that need sequential processing
709
- * const client = callApi.create({
710
- * hooksExecutionMode: "sequential",
711
- * onError: [
712
- * (ctx) => logError(ctx.error), // Log first
713
- * (ctx) => reportError(ctx.error), // Then report
714
- * (ctx) => cleanupResources(ctx) // Finally cleanup
715
- * ]
716
- * });
717
- * ```
576
+ * The Standard Schema properties interface.
718
577
  */
719
- hooksExecutionMode?: "parallel" | "sequential";
720
- }
721
- type RequestContext = {
578
+ interface Props<Input = unknown, Output = Input> {
579
+ /**
580
+ * Inferred types associated with the schema.
581
+ */
582
+ readonly types?: Types<Input, Output> | undefined;
583
+ /**
584
+ * Validates unknown input values.
585
+ */
586
+ readonly validate: (value: unknown) => Promise<Result<Output>> | Result<Output>;
587
+ /**
588
+ * The vendor name of the schema library.
589
+ */
590
+ readonly vendor: string;
591
+ /**
592
+ * The version number of the standard.
593
+ */
594
+ readonly version: 1;
595
+ }
722
596
  /**
723
- * Base configuration object passed to createFetchClient.
724
- *
725
- * Contains the foundational configuration that applies to all requests
726
- * made by this client instance, such as baseURL, default headers, and
727
- * global options.
597
+ * The result interface of the validate function.
728
598
  */
729
- baseConfig: Exclude<BaseCallApiConfig, AnyFunction$1>;
599
+ type Result<Output> = FailureResult | SuccessResult<Output>;
730
600
  /**
731
- * Instance-specific configuration object passed to the callApi instance.
732
- *
733
- * Contains configuration specific to this particular API call, which
734
- * can override or extend the base configuration.
601
+ * The result interface if validation succeeds.
735
602
  */
736
- config: CallApiConfig;
603
+ interface SuccessResult<Output> {
604
+ /**
605
+ * The non-existent issues.
606
+ */
607
+ readonly issues?: undefined;
608
+ /**
609
+ * The typed output value.
610
+ */
611
+ readonly value: Output;
612
+ }
737
613
  /**
738
- * Merged options combining base config, instance config, and default options.
739
- *
740
- * This is the final resolved configuration that will be used for the request,
741
- * with proper precedence applied (instance > base > defaults).
614
+ * The result interface if validation fails.
742
615
  */
743
- options: CallApiExtraOptionsForHooks;
616
+ interface FailureResult {
617
+ /**
618
+ * The issues of failed validation.
619
+ */
620
+ readonly issues: readonly Issue[];
621
+ }
744
622
  /**
745
- * Merged request object ready to be sent.
746
- *
747
- * Contains the final request configuration including URL, method, headers,
748
- * body, and other fetch options. This object can be modified in onRequest
749
- * hooks to customize the outgoing request.
623
+ * The issue interface of the failure output.
750
624
  */
751
- request: CallApiRequestOptionsForHooks;
752
- };
753
- type ValidationErrorContext = UnmaskType<RequestContext & {
754
- /** Validation error containing details about what failed validation */
755
- error: PossibleValidationError;
756
- /** HTTP response object if validation failed on response, null if on request */
757
- response: Response | null;
758
- }>;
759
- type SuccessContext<TData$1> = UnmaskType<RequestContext & {
760
- /** Parsed response data with the expected success type */
761
- data: TData$1;
762
- /** HTTP response object for the successful request */
763
- response: Response;
764
- }>;
765
- type ResponseContext<TData$1, TErrorData$1> = UnmaskType<RequestContext & (Prettify<CallApiResultSuccessVariant<TData$1>> | Prettify<Extract<CallApiResultErrorVariant<TErrorData$1>, {
766
- error: PossibleHTTPError<TErrorData$1>;
767
- }>>)>;
768
- type RequestErrorContext = RequestContext & {
769
- /** Error that occurred during the request (network, timeout, etc.) */
770
- error: PossibleJavaScriptError;
771
- /** Always null for request errors since no response was received */
772
- response: null;
773
- };
774
- type ErrorContext<TErrorData$1> = UnmaskType<RequestContext & ({
775
- /** HTTP error with response data */
776
- error: PossibleHTTPError<TErrorData$1>;
777
- /** HTTP response object containing error status */
778
- response: Response;
779
- } | {
780
- /** Request-level error (network, timeout, validation, etc.) */
781
- error: PossibleJavaScriptOrValidationError;
782
- /** Response object if available, null for request errors */
783
- response: Response | null;
784
- })>;
785
- type ResponseErrorContext<TErrorData$1> = UnmaskType<Extract<ErrorContext<TErrorData$1>, {
786
- error: PossibleHTTPError<TErrorData$1>;
787
- }> & RequestContext>;
788
- type RetryContext<TErrorData$1> = UnmaskType<ErrorContext<TErrorData$1> & {
789
- /** Current retry attempt number (1-based, so 1 = first retry) */
790
- retryAttemptCount: number;
791
- }>;
792
- type RequestStreamContext = UnmaskType<RequestContext & {
793
- /** Progress event containing loaded/total bytes information */
794
- event: StreamProgressEvent;
795
- /** The actual Request instance being uploaded */
796
- requestInstance: Request;
797
- }>;
798
- type ResponseStreamContext = UnmaskType<RequestContext & {
799
- /** Progress event containing loaded/total bytes information */
800
- event: StreamProgressEvent;
801
- /** HTTP response object being downloaded */
802
- response: Response;
803
- }>;
804
- //#endregion
805
- //#region src/dedupe.d.ts
806
- type DedupeStrategyUnion = UnmaskType<"cancel" | "defer" | "none">;
807
- type DedupeOptionKeys = Exclude<keyof DedupeOptions, "dedupe">;
808
- type InnerDedupeOptions = { [Key in DedupeOptionKeys as RemovePrefix<"dedupe", Key>]?: DedupeOptions[Key] };
809
- type DedupeOptions = {
625
+ interface Issue {
626
+ /**
627
+ * The error message of the issue.
628
+ */
629
+ readonly message: string;
630
+ /**
631
+ * The path of the issue, if any.
632
+ */
633
+ readonly path?: ReadonlyArray<PathSegment | PropertyKey> | undefined;
634
+ }
810
635
  /**
811
- * All dedupe options in a single object instead of separate properties
636
+ * The path segment interface of the issue.
812
637
  */
813
- dedupe?: InnerDedupeOptions;
638
+ interface PathSegment {
639
+ /**
640
+ * The key representing a path segment.
641
+ */
642
+ readonly key: PropertyKey;
643
+ }
814
644
  /**
815
- * Controls the scope of request deduplication caching.
816
- *
817
- * - `"global"`: Shares deduplication cache across all `createFetchClient` instances with the same `dedupeCacheScopeKey`.
818
- * Useful for applications with multiple API clients that should share deduplication state.
819
- * - `"local"`: Limits deduplication to requests within the same `createFetchClient` instance.
820
- * Provides better isolation and is recommended for most use cases.
821
- *
822
- *
823
- * **Real-world Scenarios:**
824
- * - Use `"global"` when you have multiple API clients (user service, auth service, etc.) that might make overlapping requests
825
- * - Use `"local"` (default) for single-purpose clients or when you want strict isolation between different parts of your app
826
- *
827
- * @example
828
- * ```ts
829
- * // Local scope - each client has its own deduplication cache
830
- * const userClient = createFetchClient({ baseURL: "/api/users" });
831
- * const postClient = createFetchClient({ baseURL: "/api/posts" });
832
- * // These clients won't share deduplication state
833
- *
834
- * // Global scope - share cache across related clients
835
- * const userClient = createFetchClient({
836
- * baseURL: "/api/users",
837
- * dedupeCacheScope: "global",
838
- * });
839
- * const postClient = createFetchClient({
840
- * baseURL: "/api/posts",
841
- * dedupeCacheScope: "global",
842
- * });
843
- * // These clients will share deduplication state
844
- * ```
845
- *
846
- * @default "local"
645
+ * The Standard Schema types interface.
847
646
  */
848
- dedupeCacheScope?: "global" | "local";
647
+ interface Types<Input = unknown, Output = Input> {
648
+ /** The input type of the schema. */
649
+ readonly input: Input;
650
+ /** The output type of the schema. */
651
+ readonly output: Output;
652
+ }
849
653
  /**
850
- * Unique namespace for the global deduplication cache when using `dedupeCacheScope: "global"`.
851
- *
852
- * This creates logical groupings of deduplication caches. All instances with the same key
853
- * will share the same cache namespace, allowing fine-grained control over which clients
854
- * share deduplication state.
855
- *
856
- * **Best Practices:**
857
- * - Use descriptive names that reflect the logical grouping (e.g., "user-service", "analytics-api")
858
- * - Keep scope keys consistent across related API clients
859
- * - Consider using different scope keys for different environments (dev, staging, prod)
860
- * - Avoid overly broad scope keys that might cause unintended cache sharing
861
- *
862
- * **Cache Management:**
863
- * - Each scope key maintains its own independent cache
864
- * - Caches are automatically cleaned up when no references remain
865
- * - Consider the memory implications of multiple global scopes
866
- *
867
- * @example
868
- * ```ts
869
- * // Group related API clients together
870
- * const userClient = createFetchClient({
871
- * baseURL: "/api/users",
872
- * dedupeCacheScope: "global",
873
- * dedupeCacheScopeKey: "user-service"
874
- * });
875
- * const profileClient = createFetchClient({
876
- * baseURL: "/api/profiles",
877
- * dedupeCacheScope: "global",
878
- * dedupeCacheScopeKey: "user-service" // Same scope - will share cache
879
- * });
880
- *
881
- * // Separate analytics client with its own cache
882
- * const analyticsClient = createFetchClient({
883
- * baseURL: "/api/analytics",
884
- * dedupeCacheScope: "global",
885
- * dedupeCacheScopeKey: "analytics-service" // Different scope
886
- * });
887
- *
888
- * // Environment-specific scoping
889
- * const apiClient = createFetchClient({
890
- * dedupeCacheScope: "global",
891
- * dedupeCacheScopeKey: `api-${process.env.NODE_ENV}` // "api-development", "api-production", etc.
892
- * });
893
- * ```
894
- *
895
- * @default "default"
654
+ * Infers the input type of a Standard Schema.
655
+ */
656
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
657
+ /**
658
+ * Infers the output type of a Standard Schema.
659
+ */
660
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
661
+ }
662
+ //#endregion
663
+ //#region src/utils/external/error.d.ts
664
+ type HTTPErrorDetails<TErrorData$1> = Pick<CallApiExtraOptions, "defaultHTTPErrorMessage"> & {
665
+ errorData: TErrorData$1;
666
+ response: Response;
667
+ };
668
+ declare class HTTPError<TErrorData$1 = Record<string, unknown>> extends Error {
669
+ errorData: HTTPErrorDetails<TErrorData$1>["errorData"];
670
+ readonly httpErrorSymbol: symbol;
671
+ name: "HTTPError";
672
+ response: HTTPErrorDetails<TErrorData$1>["response"];
673
+ constructor(errorDetails: HTTPErrorDetails<TErrorData$1>, errorOptions?: ErrorOptions);
674
+ /**
675
+ * @description Checks if the given error is an instance of HTTPError
676
+ * @param error - The error to check
677
+ * @returns true if the error is an instance of HTTPError, false otherwise
896
678
  */
897
- dedupeCacheScopeKey?: "default" | AnyString | ((context: RequestContext) => string | undefined);
679
+ static isError<TErrorData>(error: unknown): error is HTTPError<TErrorData$1>;
680
+ }
681
+ type SafeExtract<TUnion, TKey extends TUnion> = Extract<TUnion, TKey>;
682
+ type ValidationErrorDetails = {
898
683
  /**
899
- * Custom key generator for request deduplication.
900
- *
901
- * Override the default key generation strategy to control exactly which requests
902
- * are considered duplicates. The default key combines URL, method, body, and
903
- * relevant headers (excluding volatile ones like 'Date', 'Authorization', etc.).
904
- *
905
- * **Default Key Generation:**
906
- * The auto-generated key includes:
907
- * - Full request URL (including query parameters)
908
- * - HTTP method (GET, POST, etc.)
909
- * - Request body (for POST/PUT/PATCH requests)
910
- * - Stable headers (excludes Date, Authorization, User-Agent, etc.)
911
- *
912
- * **Custom Key Best Practices:**
913
- * - Include only the parts of the request that should affect deduplication
914
- * - Avoid including volatile data (timestamps, random IDs, etc.)
915
- * - Consider performance - simpler keys are faster to compute and compare
916
- * - Ensure keys are deterministic for the same logical request
917
- * - Use consistent key formats across your application
918
- *
919
- * **Performance Considerations:**
920
- * - Function-based keys are computed on every request - keep them lightweight
921
- * - String keys are fastest but least flexible
922
- * - Consider caching expensive key computations if needed
923
- *
924
- * @example
925
- * ```ts
926
- * import { callApi } from "@zayne-labs/callapi";
927
- *
928
- * // Simple static key - useful for singleton requests
929
- * const config = callApi("/api/config", {
930
- * dedupeKey: "app-config",
931
- * dedupeStrategy: "defer" // Share the same config across all requests
932
- * });
933
- *
934
- * // URL and method only - ignore headers and body
935
- * const userData = callApi("/api/user/123", {
936
- * dedupeKey: (context) => `${context.options.method}:${context.options.fullURL}`
937
- * });
938
- *
939
- * // Include specific headers in deduplication
940
- * const apiCall = callApi("/api/data", {
941
- * dedupeKey: (context) => {
942
- * const authHeader = context.request.headers.get("Authorization");
943
- * return `${context.options.fullURL}-${authHeader}`;
944
- * }
945
- * });
946
- *
947
- * // User-specific deduplication
948
- * const userSpecificCall = callApi("/api/dashboard", {
949
- * dedupeKey: (context) => {
950
- * const userId = context.options.fullURL.match(/user\/(\d+)/)?.[1];
951
- * return `dashboard-${userId}`;
952
- * }
953
- * });
954
- *
955
- * // Ignore certain query parameters
956
- * const searchCall = callApi("/api/search?q=test&timestamp=123456", {
957
- * dedupeKey: (context) => {
958
- * const url = new URL(context.options.fullURL);
959
- * url.searchParams.delete("timestamp"); // Remove volatile param
960
- * return `search:${url.toString()}`;
961
- * }
962
- * });
963
- * ```
684
+ * The cause of the validation error.
964
685
  *
965
- * @default Auto-generated from request details
686
+ * 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.
966
687
  */
967
- dedupeKey?: string | ((context: RequestContext) => string | undefined);
688
+ issueCause: "unknown" | `schemaConfig-(${SafeExtract<keyof CallApiSchemaConfig, "strict">})` | keyof CallApiSchema;
968
689
  /**
969
- * Strategy for handling duplicate requests. Can be a static string or callback function.
970
- *
971
- * **Available Strategies:**
972
- * - `"cancel"`: Cancel previous request when new one starts (good for search)
973
- * - `"defer"`: Share response between duplicate requests (good for config loading)
974
- * - `"none"`: No deduplication, all requests execute independently
975
- *
976
- * @example
977
- * ```ts
978
- * // Static strategies
979
- * const searchClient = createFetchClient({
980
- * dedupeStrategy: "cancel" // Cancel previous searches
981
- * });
982
- *
983
- * const configClient = createFetchClient({
984
- * dedupeStrategy: "defer" // Share config across components
985
- * });
986
- *
987
- * // Dynamic strategy based on request
988
- * const smartClient = createFetchClient({
989
- * dedupeStrategy: (context) => {
990
- * return context.options.method === "GET" ? "defer" : "cancel";
991
- * }
992
- * });
993
- *
994
- * // Search-as-you-type with cancel strategy
995
- * const handleSearch = async (query: string) => {
996
- * try {
997
- * const { data } = await callApi("/api/search", {
998
- * method: "POST",
999
- * body: { query },
1000
- * dedupeStrategy: "cancel",
1001
- * dedupeKey: "search" // Cancel previous searches, only latest one goes through
1002
- * });
1003
- *
1004
- * updateSearchResults(data);
1005
- * } catch (error) {
1006
- * if (error.name === "AbortError") {
1007
- * // Previous search cancelled - (expected behavior)
1008
- * return;
1009
- * }
1010
- * console.error("Search failed:", error);
1011
- * }
1012
- * };
1013
- *
1014
- * ```
1015
- *
1016
- * @default "cancel"
690
+ * The issues that caused the validation error.
1017
691
  */
1018
- dedupeStrategy?: DedupeStrategyUnion | ((context: RequestContext) => DedupeStrategyUnion);
692
+ issues: readonly StandardSchemaV1.Issue[];
693
+ /**
694
+ * The response from server, if any.
695
+ */
696
+ response: Response | null;
697
+ };
698
+ declare class ValidationError extends Error {
699
+ errorData: ValidationErrorDetails["issues"];
700
+ issueCause: ValidationErrorDetails["issueCause"];
701
+ name: "ValidationError";
702
+ response: ValidationErrorDetails["response"];
703
+ readonly validationErrorSymbol: symbol;
704
+ constructor(details: ValidationErrorDetails, errorOptions?: ErrorOptions);
705
+ /**
706
+ * @description Checks if the given error is an instance of ValidationError
707
+ * @param error - The error to check
708
+ * @returns true if the error is an instance of ValidationError, false otherwise
709
+ */
710
+ static isError(error: unknown): error is ValidationError;
711
+ }
712
+ //#endregion
713
+ //#region src/result.d.ts
714
+ type Parser<TData$1> = (responseString: string) => Awaitable<TData$1>;
715
+ declare const getResponseType: <TResponse>(response: Response, parser: Parser<TResponse>) => {
716
+ arrayBuffer: () => Promise<ArrayBuffer>;
717
+ blob: () => Promise<Blob>;
718
+ formData: () => Promise<FormData>;
719
+ json: () => Promise<TResponse>;
720
+ stream: () => ReadableStream<Uint8Array<ArrayBuffer>> | null;
721
+ text: () => Promise<string>;
722
+ };
723
+ type InitResponseTypeMap<TResponse$1 = unknown> = ReturnType<typeof getResponseType<TResponse$1>>;
724
+ type ResponseTypeUnion = keyof InitResponseTypeMap;
725
+ type ResponseTypePlaceholder = null;
726
+ type ResponseTypeType = ResponseTypePlaceholder | ResponseTypeUnion;
727
+ type ResponseTypeMap<TResponse$1> = { [Key in keyof InitResponseTypeMap<TResponse$1>]: Awaited<ReturnType<InitResponseTypeMap<TResponse$1>[Key]>> };
728
+ 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;
729
+ type CallApiResultSuccessVariant<TData$1> = {
730
+ data: NoInfer<TData$1>;
731
+ error: null;
732
+ response: Response;
733
+ };
734
+ type PossibleJavaScriptError = UnmaskType<{
735
+ errorData: false;
736
+ message: string;
737
+ name: "AbortError" | "Error" | "SyntaxError" | "TimeoutError" | "TypeError" | AnyString;
738
+ originalError: DOMException | Error | SyntaxError | TypeError;
739
+ }>;
740
+ type PossibleHTTPError<TErrorData$1> = UnmaskType<{
741
+ errorData: NoInfer<TErrorData$1>;
742
+ message: string;
743
+ name: "HTTPError";
744
+ originalError: HTTPError;
745
+ }>;
746
+ type PossibleValidationError = UnmaskType<{
747
+ errorData: ValidationError["errorData"];
748
+ issueCause: ValidationError["issueCause"];
749
+ message: string;
750
+ name: "ValidationError";
751
+ originalError: ValidationError;
752
+ }>;
753
+ type PossibleJavaScriptOrValidationError = UnmaskType<PossibleJavaScriptError | PossibleValidationError>;
754
+ type CallApiResultErrorVariant<TErrorData$1> = {
755
+ data: null;
756
+ error: PossibleHTTPError<TErrorData$1>;
757
+ response: Response;
758
+ } | {
759
+ data: null;
760
+ error: PossibleJavaScriptOrValidationError;
761
+ response: Response | null;
762
+ };
763
+ type CallApiSuccessOrErrorVariant<TData$1, TError> = CallApiResultErrorVariant<TError> | CallApiResultSuccessVariant<TData$1>;
764
+ 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<{
765
+ all: TComputedResult$1;
766
+ onlyData: TComputedResult$1["data"];
767
+ onlyResponse: TComputedResult$1["response"];
768
+ withoutResponse: DistributiveOmit<TComputedResult$1, "response">;
769
+ }>;
770
+ type ResultModeMapWithException<TData$1, TResponseType$1 extends ResponseTypeType, TComputedData = GetResponseType<TData$1, TResponseType$1>, TComputedResult$1 extends CallApiResultSuccessVariant<TComputedData> = CallApiResultSuccessVariant<TComputedData>> = {
771
+ all: TComputedResult$1;
772
+ onlyData: TComputedResult$1["data"];
773
+ onlyResponse: TComputedResult$1["response"];
774
+ withoutResponse: DistributiveOmit<TComputedResult$1, "response">;
1019
775
  };
776
+ 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>;
777
+ type ResultModePlaceholder = null;
778
+ type ResultModeUnion = keyof ResultModeMap;
779
+ type ResultModeType = ResultModePlaceholder | ResultModeUnion;
1020
780
  //#endregion
1021
781
  //#region src/retry.d.ts
1022
782
  declare const defaultRetryStatusCodesLookup: () => Readonly<{
@@ -1030,7 +790,9 @@ declare const defaultRetryStatusCodesLookup: () => Readonly<{
1030
790
  504: "Gateway Timeout";
1031
791
  }>;
1032
792
  type RetryStatusCodes = UnmaskType<AnyNumber | keyof ReturnType<typeof defaultRetryStatusCodesLookup>>;
1033
- type RetryCondition<TErrorData$1> = (context: ErrorContext<TErrorData$1>) => Awaitable<boolean>;
793
+ type RetryCondition<TErrorData$1> = (context: ErrorContext<{
794
+ ErrorData: TErrorData$1;
795
+ }>) => Awaitable<boolean>;
1034
796
  type RetryOptionKeys<TErrorData$1> = Exclude<keyof RetryOptions<TErrorData$1>, "~retryAttemptCount" | "retry">;
1035
797
  type InnerRetryOptions<TErrorData$1> = { [Key in RetryOptionKeys<TErrorData$1> as RemovePrefix<"retry", Key>]?: RetryOptions<TErrorData$1>[Key] };
1036
798
  interface RetryOptions<TErrorData$1> {
@@ -1060,141 +822,36 @@ interface RetryOptions<TErrorData$1> {
1060
822
  retryDelay?: number | ((currentAttemptCount: number) => number);
1061
823
  /**
1062
824
  * Maximum delay in milliseconds. Only applies to exponential strategy
1063
- * @default 10000
1064
- */
1065
- retryMaxDelay?: number;
1066
- /**
1067
- * HTTP methods that are allowed to retry
1068
- * @default ["GET", "POST"]
1069
- */
1070
- retryMethods?: MethodUnion[];
1071
- /**
1072
- * HTTP status codes that trigger a retry
1073
- */
1074
- retryStatusCodes?: RetryStatusCodes[];
1075
- /**
1076
- * Strategy to use when retrying
1077
- * @default "linear"
1078
- */
1079
- retryStrategy?: "exponential" | "linear";
1080
- }
1081
- //#endregion
1082
- //#region src/types/conditional-types.d.ts
1083
- /**
1084
- * @description Makes a type partial if the output type of TSchema is not provided or has undefined in the union, otherwise makes it required
1085
- */
1086
- type MakeSchemaOptionRequiredIfDefined<TSchemaOption extends CallApiSchema[keyof CallApiSchema], TObject> = undefined extends InferSchemaOutput<TSchemaOption, undefined> ? TObject : Required<TObject>;
1087
- 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;
1088
- type ApplyStrictConfig<TSchemaConfig$1 extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = TSchemaConfig$1["strict"] extends true ? TSchemaRouteKeys :
1089
- // eslint-disable-next-line perfectionist/sort-union-types -- Don't sort union types
1090
- TSchemaRouteKeys | Exclude<InitURLOrURLObject, RouteKeyMethodsURLUnion>;
1091
- type ApplySchemaConfiguration<TSchemaConfig$1 extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = ApplyStrictConfig<TSchemaConfig$1, ApplyURLBasedConfig<TSchemaConfig$1, TSchemaRouteKeys>>;
1092
- type InferAllRouteKeys<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TSchemaConfig$1 extends CallApiSchemaConfig> = ApplySchemaConfiguration<TSchemaConfig$1, Exclude<Extract<keyof TBaseSchemaRoutes$1, string>, FallBackRouteSchemaKey>>;
1093
- type InferInitURL<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TSchemaConfig$1 extends CallApiSchemaConfig> = keyof TBaseSchemaRoutes$1 extends never ? InitURLOrURLObject : InferAllRouteKeys<TBaseSchemaRoutes$1, TSchemaConfig$1>;
1094
- 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;
1095
- type JsonPrimitive = boolean | number | string | null | undefined;
1096
- type SerializableObject = Record<PropertyKey, unknown>;
1097
- type SerializableArray = Array<JsonPrimitive | SerializableObject> | ReadonlyArray<JsonPrimitive | SerializableObject>;
1098
- type Body = UnmaskType<Exclude<RequestInit["body"], undefined> | SerializableArray | SerializableObject>;
1099
- type InferBodyOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["body"], {
1100
- /**
1101
- * Body of the request, can be a object or any other supported body type.
1102
- */
1103
- body?: InferSchemaOutput<TSchema$1["body"], Body>;
1104
- }>;
1105
- type MethodUnion = UnmaskType<"CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE" | AnyString>;
1106
- type InferMethodFromURL<TInitURL> = string extends TInitURL ? MethodUnion : TInitURL extends `@${infer TMethod extends RouteKeyMethods}/${string}` ? Uppercase<TMethod> : MethodUnion;
1107
- type InferMethodOption<TSchema$1 extends CallApiSchema, TInitURL> = MakeSchemaOptionRequiredIfDefined<TSchema$1["method"], {
1108
- /**
1109
- * HTTP method for the request.
1110
- * @default "GET"
1111
- */
1112
- method?: InferSchemaOutput<TSchema$1["method"], InferMethodFromURL<TInitURL>>;
1113
- }>;
1114
- type HeadersOption = UnmaskType<Record<"Authorization", CommonAuthorizationHeaders | undefined> | Record<"Content-Type", CommonContentTypes | undefined> | Record<CommonRequestHeaders, string | undefined> | Record<string, string | undefined> | Array<[string, string]>>;
1115
- type InferHeadersOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["headers"], {
1116
- /**
1117
- * Headers to be used in the request.
825
+ * @default 10000
1118
826
  */
1119
- headers?: InferSchemaOutput<TSchema$1["headers"], HeadersOption> | ((context: {
1120
- baseHeaders: NonNullable<HeadersOption>;
1121
- }) => InferSchemaOutput<TSchema$1["headers"], HeadersOption>);
1122
- }>;
1123
- type InferRequestOptions<TSchema$1 extends CallApiSchema, TInitURL extends InferInitURL<BaseCallApiSchemaRoutes, CallApiSchemaConfig>> = InferBodyOption<TSchema$1> & InferHeadersOption<TSchema$1> & InferMethodOption<TSchema$1, TInitURL>;
1124
- type InferMetaOption<TSchema$1 extends CallApiSchema, TCallApiContext extends CallApiContext> = MakeSchemaOptionRequiredIfDefined<TSchema$1["meta"], {
827
+ retryMaxDelay?: number;
1125
828
  /**
1126
- * - An optional field you can fill with additional information,
1127
- * to associate with the request, typically used for logging or tracing.
1128
- *
1129
- * - A good use case for this, would be to use the info to handle specific cases in any of the shared interceptors.
1130
- *
1131
- * @example
1132
- * ```ts
1133
- * const callMainApi = callApi.create({
1134
- * baseURL: "https://main-api.com",
1135
- * onResponseError: ({ response, options }) => {
1136
- * if (options.meta?.userId) {
1137
- * console.error(`User ${options.meta.userId} made an error`);
1138
- * }
1139
- * },
1140
- * });
1141
- *
1142
- * const response = await callMainApi({
1143
- * url: "https://example.com/api/data",
1144
- * meta: { userId: "123" },
1145
- * });
1146
- * ```
829
+ * HTTP methods that are allowed to retry
830
+ * @default ["GET", "POST"]
1147
831
  */
1148
- meta?: InferSchemaOutput<TSchema$1["meta"], TCallApiContext["Meta"]>;
1149
- }>;
1150
- type InferQueryOption<TSchema$1 extends CallApiSchema> = MakeSchemaOptionRequiredIfDefined<TSchema$1["query"], {
832
+ retryMethods?: MethodUnion[];
1151
833
  /**
1152
- * Parameters to be appended to the URL (i.e: /:id)
834
+ * HTTP status codes that trigger a retry
1153
835
  */
1154
- query?: InferSchemaOutput<TSchema$1["query"], Query>;
1155
- }>;
1156
- type EmptyString = "";
1157
- type EmptyTuple = readonly [];
1158
- type StringTuple = readonly string[];
1159
- type PossibleParamNamePatterns = `${string}:${string}` | `${string}{${string}}${"" | AnyString}`;
1160
- 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;
1161
- type ConvertParamNamesToRecord<TParamNames extends StringTuple> = Prettify<TParamNames extends (readonly [infer TFirstParamName extends string, ...infer TRemainingParamNames extends StringTuple]) ? Record<TFirstParamName, AllowedQueryParamValues> & ConvertParamNamesToRecord<TRemainingParamNames> : NonNullable<unknown>>;
1162
- type ConvertParamNamesToTuple<TParamNames extends StringTuple> = TParamNames extends readonly [string, ...infer TRemainingParamNames extends StringTuple] ? [AllowedQueryParamValues, ...ConvertParamNamesToTuple<TRemainingParamNames>] : [];
1163
- type InferParamsFromRoute<TCurrentRoute$1> = ExtractRouteParamNames<TCurrentRoute$1> extends StringTuple ? ExtractRouteParamNames<TCurrentRoute$1> extends EmptyTuple ? Params : ConvertParamNamesToRecord<ExtractRouteParamNames<TCurrentRoute$1>> | ConvertParamNamesToTuple<ExtractRouteParamNames<TCurrentRoute$1>> : Params;
1164
- 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>;
1165
- type InferParamsOption<TSchema$1 extends CallApiSchema, TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey extends string> = MakeParamsOptionRequired<TSchema$1["params"], TBaseSchemaRoutes$1, TCurrentRouteSchemaKey, {
836
+ retryStatusCodes?: RetryStatusCodes[];
1166
837
  /**
1167
- * Parameters to be appended to the URL (i.e: /:id)
838
+ * Strategy to use when retrying
839
+ * @default "linear"
1168
840
  */
1169
- params?: InferSchemaOutput<TSchema$1["params"], InferParamsFromRoute<TCurrentRouteSchemaKey>>;
1170
- }>;
1171
- type InferExtraOptions<TSchema$1 extends CallApiSchema, TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey extends string, TCallApiContext extends CallApiContext> = InferMetaOption<TSchema$1, TCallApiContext> & InferParamsOption<TSchema$1, TBaseSchemaRoutes$1, TCurrentRouteSchemaKey> & InferQueryOption<TSchema$1>;
1172
- type InferPluginOptions<TPluginArray extends CallApiPlugin[]> = UnionToIntersection<TPluginArray extends Array<infer TPlugin> ? TPlugin extends CallApiPlugin ? TPlugin["defineExtraOptions"] extends AnyFunction$1<infer TReturnedSchema> ? InferSchemaOutput<TReturnedSchema> : never : never : never>;
1173
- type ResultModeOption<TErrorData$1, TResultMode extends ResultModeType> = TErrorData$1 extends false ? {
1174
- resultMode: "onlyData";
1175
- } : TErrorData$1 extends false | undefined ? {
1176
- resultMode?: "onlyData";
1177
- } : {
1178
- resultMode?: TResultMode;
1179
- };
1180
- type ThrowOnErrorUnion = boolean;
1181
- type ThrowOnErrorType<TErrorData$1, TThrowOnError extends ThrowOnErrorUnion> = TThrowOnError | ((context: ErrorContext<TErrorData$1>) => TThrowOnError);
1182
- type ThrowOnErrorOption<TErrorData$1, TThrowOnError extends ThrowOnErrorUnion> = TErrorData$1 extends false ? {
1183
- throwOnError: true;
1184
- } : TErrorData$1 extends false | undefined ? {
1185
- throwOnError?: true;
1186
- } : {
1187
- throwOnError?: ThrowOnErrorType<TErrorData$1, TThrowOnError>;
1188
- };
841
+ retryStrategy?: "exponential" | "linear";
842
+ }
1189
843
  //#endregion
1190
844
  //#region src/types/common.d.ts
1191
845
  interface Register {}
1192
- type MetaObjectType = Record<string, unknown>;
1193
846
  type GlobalMeta = Register extends {
1194
- meta?: infer TMeta extends MetaObjectType;
1195
- } ? TMeta : never;
847
+ meta?: infer TMeta extends DefaultMetaObject;
848
+ } ? TMeta : DefaultMetaObject;
1196
849
  type CallApiContext = {
1197
- Meta?: MetaObjectType;
850
+ Data?: DefaultDataType;
851
+ ErrorData?: DefaultDataType;
852
+ InferredPluginOptions?: unknown;
853
+ Meta?: DefaultMetaObject;
854
+ ResultMode?: ResultModeType;
1198
855
  };
1199
856
  type FetchSpecificKeysUnion = Exclude<(typeof fetchSpecificKeys)[number], "body" | "headers" | "method">;
1200
857
  type ModifiedRequestInit = RequestInit & {
@@ -1218,7 +875,9 @@ type CallApiRequestOptions = Prettify<{
1218
875
  type CallApiRequestOptionsForHooks = Omit<CallApiRequestOptions, "headers"> & {
1219
876
  headers: Record<string, string | undefined>;
1220
877
  };
1221
- type SharedExtraOptions<TCallApiContext extends CallApiContext = CallApiContext, TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TResultMode extends ResultModeType = ResultModeType, 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 & {
878
+ 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"> = {
879
+ InferredPluginOptions: TComputedPluginOptions;
880
+ }> = 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 & {
1222
881
  /**
1223
882
  * Automatically add an Authorization header value.
1224
883
  *
@@ -1396,7 +1055,7 @@ type SharedExtraOptions<TCallApiContext extends CallApiContext = CallApiContext,
1396
1055
  * });
1397
1056
  * ```
1398
1057
  */
1399
- meta?: TCallApiContext["Meta"];
1058
+ meta?: TCallApiContext$1["Meta"] extends DefaultMetaObject ? TCallApiContext$1["Meta"] : DefaultCallApiContext["Meta"];
1400
1059
  /**
1401
1060
  * Custom function to parse response strings into actual value instead of the default response.json().
1402
1061
  *
@@ -1466,7 +1125,7 @@ type SharedExtraOptions<TCallApiContext extends CallApiContext = CallApiContext,
1466
1125
  * // Usage: const stream = await callApi("/large-dataset", { responseType: "stream" });
1467
1126
  * ```
1468
1127
  */
1469
- responseType?: TResponseType;
1128
+ responseType?: TResponseType$1;
1470
1129
  /**
1471
1130
  * Controls what data is included in the returned result object.
1472
1131
  *
@@ -1521,7 +1180,7 @@ type SharedExtraOptions<TCallApiContext extends CallApiContext = CallApiContext,
1521
1180
  * }
1522
1181
  * ```
1523
1182
  */
1524
- resultMode?: TResultMode;
1183
+ resultMode?: TResultMode$1;
1525
1184
  /**
1526
1185
  * Controls whether errors are thrown as exceptions or returned in the result.
1527
1186
  *
@@ -1566,7 +1225,7 @@ type SharedExtraOptions<TCallApiContext extends CallApiContext = CallApiContext,
1566
1225
  * }
1567
1226
  * ```
1568
1227
  */
1569
- throwOnError?: ThrowOnErrorType<TErrorData$1, TThrowOnError>;
1228
+ throwOnError?: ThrowOnErrorType<TErrorData$1, TThrowOnError$1>;
1570
1229
  /**
1571
1230
  * Request timeout in milliseconds. Request will be aborted if it takes longer.
1572
1231
  *
@@ -1590,154 +1249,444 @@ type SharedExtraOptions<TCallApiContext extends CallApiContext = CallApiContext,
1590
1249
  * timeout: 0
1591
1250
  * ```
1592
1251
  */
1593
- timeout?: number;
1594
- };
1595
- type BaseCallApiExtraOptions<TBaseCallApiContext extends CallApiContext = CallApiContext, TBaseData = DefaultDataType, TBaseErrorData = DefaultDataType, TBaseResultMode extends ResultModeType = ResultModeType, TBaseThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TBaseResponseType extends ResponseTypeType = ResponseTypeType, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig> = SharedExtraOptions<TBaseCallApiContext, TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBasePluginArray> & {
1252
+ timeout?: number;
1253
+ };
1254
+ 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> & {
1255
+ /**
1256
+ * Array of base CallApi plugins to extend library functionality.
1257
+ *
1258
+ * Base plugins are applied to all instances created from this base configuration
1259
+ * and provide foundational functionality like authentication, logging, or caching.
1260
+ *
1261
+ * @example
1262
+ * ```ts
1263
+ * // Add logging plugin
1264
+ *
1265
+ * // Create base client with common plugins
1266
+ * const callApi = createFetchClient({
1267
+ * baseURL: "https://api.example.com",
1268
+ * plugins: [loggerPlugin({ enabled: true })]
1269
+ * });
1270
+ *
1271
+ * // All requests inherit base plugins
1272
+ * await callApi("/users");
1273
+ * await callApi("/posts");
1274
+ *
1275
+ * ```
1276
+ */
1277
+ plugins?: TBasePluginArray$1;
1278
+ /**
1279
+ * Base validation schemas for the client configuration.
1280
+ *
1281
+ * Defines validation rules for requests and responses that apply to all
1282
+ * instances created from this base configuration. Provides type safety
1283
+ * and runtime validation for API interactions.
1284
+ */
1285
+ schema?: TBaseSchemaAndConfig$1;
1286
+ /**
1287
+ * Controls which configuration parts skip automatic merging between base and instance configs.
1288
+ *
1289
+ * By default, CallApi automatically merges base configuration with instance configuration.
1290
+ * This option allows you to disable automatic merging for specific parts when you need
1291
+ * manual control over how configurations are combined.
1292
+ *
1293
+ * @enum
1294
+ * - **"all"**: Disables automatic merging for both request options and extra options
1295
+ * - **"options"**: Disables automatic merging of extra options only (hooks, plugins, etc.)
1296
+ * - **"request"**: Disables automatic merging of request options only (headers, body, etc.)
1297
+ *
1298
+ * @example
1299
+ * ```ts
1300
+ * // Skip all automatic merging - full manual control
1301
+ * const client = callApi.create((ctx) => ({
1302
+ * skipAutoMergeFor: "all",
1303
+ *
1304
+ * // Manually decide what to merge
1305
+ * baseURL: ctx.options.baseURL, // Keep base URL
1306
+ * timeout: 5000, // Override timeout
1307
+ * headers: {
1308
+ * ...ctx.request.headers, // Merge headers manually
1309
+ * "X-Custom": "value" // Add custom header
1310
+ * }
1311
+ * }));
1312
+ *
1313
+ * // Skip options merging - manual plugin/hook control
1314
+ * const client = callApi.create((ctx) => ({
1315
+ * skipAutoMergeFor: "options",
1316
+ *
1317
+ * // Manually control which plugins to use
1318
+ * plugins: [
1319
+ * ...ctx.options.plugins?.filter(p => p.name !== "unwanted") || [],
1320
+ * customPlugin
1321
+ * ],
1322
+ *
1323
+ * // Request options still auto-merge
1324
+ * method: "POST"
1325
+ * }));
1326
+ *
1327
+ * // Skip request merging - manual request control
1328
+ * const client = callApi.create((ctx) => ({
1329
+ * skipAutoMergeFor: "request",
1330
+ *
1331
+ * // Extra options still auto-merge (plugins, hooks, etc.)
1332
+ *
1333
+ * // Manually control request options
1334
+ * headers: {
1335
+ * "Content-Type": "application/json",
1336
+ * // Don't merge base headers
1337
+ * },
1338
+ * method: ctx.request.method || "GET"
1339
+ * }));
1340
+ *
1341
+ * // Use case: Conditional merging based on request
1342
+ * const client = createFetchClient((ctx) => ({
1343
+ * skipAutoMergeFor: "options",
1344
+ *
1345
+ * // Only use auth plugin for protected routes
1346
+ * plugins: ctx.initURL.includes("/protected/")
1347
+ * ? [...(ctx.options.plugins || []), authPlugin]
1348
+ * : ctx.options.plugins?.filter(p => p.name !== "auth") || []
1349
+ * }));
1350
+ * ```
1351
+ */
1352
+ skipAutoMergeFor?: "all" | "options" | "request";
1353
+ };
1354
+ type InferExtendSchemaContext<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey$1 extends string> = {
1355
+ baseSchemaRoutes: TBaseSchemaRoutes$1;
1356
+ currentRouteSchema: GetCurrentRouteSchema<TBaseSchemaRoutes$1, TCurrentRouteSchemaKey$1>;
1357
+ };
1358
+ type GetExtendSchemaConfigContext<TBaseSchemaConfig extends CallApiSchemaConfig> = {
1359
+ baseSchemaConfig: TBaseSchemaConfig;
1360
+ };
1361
+ type InferExtendPluginContext<TBasePluginArray$1 extends CallApiPlugin[]> = {
1362
+ basePlugins: TBasePluginArray$1;
1363
+ };
1364
+ 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> & {
1365
+ /**
1366
+ * Array of instance-specific CallApi plugins or a function to configure plugins.
1367
+ *
1368
+ * Instance plugins are added to the base plugins and provide functionality
1369
+ * specific to this particular API instance. Can be a static array or a function
1370
+ * that receives base plugins and returns the instance plugins.
1371
+ *
1372
+ */
1373
+ plugins?: TPluginArray$1 | ((context: TComputedPluginContext) => TPluginArray$1);
1374
+ /**
1375
+ * For instance-specific validation schemas
1376
+ *
1377
+ * Defines validation rules specific to this API instance, extending or overriding the base schema.
1378
+ *
1379
+ * Can be a static schema object or a function that receives base schema context and returns instance schemas.
1380
+ *
1381
+ */
1382
+ schema?: TSchema$1 | ((context: TComputedSchemaContext) => TSchema$1);
1383
+ /**
1384
+ * Instance-specific schema configuration or a function to configure schema behavior.
1385
+ *
1386
+ * Controls how validation schemas are applied and behave for this specific API instance.
1387
+ * Can override base schema configuration or extend it with instance-specific validation rules.
1388
+ *
1389
+ */
1390
+ schemaConfig?: TSchemaConfig$1 | ((context: TComputedSchemaConfigContext) => TSchemaConfig$1);
1391
+ };
1392
+ type CallApiExtraOptionsForHooks<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = Hooks & Omit<CallApiExtraOptions<TCallApiContext$1>, keyof Hooks>;
1393
+ type InstanceContext = {
1394
+ initURL: string;
1395
+ options: CallApiExtraOptions;
1396
+ request: CallApiRequestOptions;
1397
+ };
1398
+ 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);
1399
+ 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>>;
1400
+ //#endregion
1401
+ //#region src/stream.d.ts
1402
+ type StreamProgressEvent = {
1403
+ /**
1404
+ * Current chunk of data being streamed
1405
+ */
1406
+ chunk: Uint8Array;
1407
+ /**
1408
+ * Progress in percentage
1409
+ */
1410
+ progress: number;
1411
+ /**
1412
+ * Total size of data in bytes
1413
+ */
1414
+ totalBytes: number;
1415
+ /**
1416
+ * Amount of data transferred so far
1417
+ */
1418
+ transferredBytes: number;
1419
+ };
1420
+ declare global {
1421
+ interface ReadableStream<R> {
1422
+ [Symbol.asyncIterator]: () => AsyncIterableIterator<R>;
1423
+ }
1424
+ }
1425
+ //#endregion
1426
+ //#region src/hooks.d.ts
1427
+ interface Hooks<TCallApiContext$1 extends Pick<CallApiContext, "Data" | "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TData$1 = TCallApiContext$1["Data"], TErrorData$1 = TCallApiContext$1["ErrorData"]> {
1428
+ /**
1429
+ * Hook called when any error occurs within the request/response lifecycle.
1430
+ *
1431
+ * This is a unified error handler that catches both request errors (network failures,
1432
+ * timeouts, etc.) and response errors (HTTP error status codes). It's essentially
1433
+ * a combination of `onRequestError` and `onResponseError` hooks.
1434
+ *
1435
+ * @param context - Error context containing error details, request info, and response (if available)
1436
+ * @returns Promise or void - Hook can be async or sync
1437
+ */
1438
+ onError?: (context: ErrorContext<TCallApiContext$1, TErrorData$1>) => Awaitable<unknown>;
1439
+ /**
1440
+ * Hook called before the HTTP request is sent and before any internal processing of the request object begins.
1441
+ *
1442
+ * This is the ideal place to modify request headers, add authentication,
1443
+ * implement request logging, or perform any setup before the network call.
1444
+ *
1445
+ * @param context - Request context with mutable request object and configuration
1446
+ * @returns Promise or void - Hook can be async or sync
1447
+ *
1448
+ */
1449
+ onRequest?: (context: RequestContext<TCallApiContext$1>) => Awaitable<unknown>;
1450
+ /**
1451
+ * Hook called when an error occurs during the fetch request itself.
1452
+ *
1453
+ * This handles network-level errors like connection failures, timeouts,
1454
+ * DNS resolution errors, or other issues that prevent getting an HTTP response.
1455
+ * Note that HTTP error status codes (4xx, 5xx) are handled by `onResponseError`.
1456
+ *
1457
+ * @param context - Request error context with error details and null response
1458
+ * @returns Promise or void - Hook can be async or sync
1459
+ */
1460
+ onRequestError?: (context: RequestErrorContext<TCallApiContext$1>) => Awaitable<unknown>;
1461
+ /**
1462
+ * Hook called just before the HTTP request is sent and after the request has been processed.
1463
+ *
1464
+ * @param context - Request context with mutable request object and configuration
1465
+ */
1466
+ onRequestReady?: (context: RequestContext<TCallApiContext$1>) => Awaitable<unknown>;
1596
1467
  /**
1597
- * Array of base CallApi plugins to extend library functionality.
1468
+ * Hook called during upload stream progress tracking.
1598
1469
  *
1599
- * Base plugins are applied to all instances created from this base configuration
1600
- * and provide foundational functionality like authentication, logging, or caching.
1470
+ * This hook is triggered when uploading data (like file uploads) and provides
1471
+ * progress information about the upload. Useful for implementing progress bars
1472
+ * or upload status indicators.
1601
1473
  *
1602
- * @example
1603
- * ```ts
1604
- * // Add logging plugin
1474
+ * @param context - Request stream context with progress event and request instance
1475
+ * @returns Promise or void - Hook can be async or sync
1605
1476
  *
1606
- * // Create base client with common plugins
1607
- * const callApi = createFetchClient({
1608
- * baseURL: "https://api.example.com",
1609
- * plugins: [loggerPlugin({ enabled: true })]
1610
- * });
1477
+ */
1478
+ onRequestStream?: (context: RequestStreamContext<TCallApiContext$1>) => Awaitable<unknown>;
1479
+ /**
1480
+ * Hook called when any HTTP response is received from the API.
1611
1481
  *
1612
- * // All requests inherit base plugins
1613
- * await callApi("/users");
1614
- * await callApi("/posts");
1482
+ * This hook is triggered for both successful (2xx) and error (4xx, 5xx) responses.
1483
+ * It's useful for response logging, metrics collection, or any processing that
1484
+ * should happen regardless of response status.
1485
+ *
1486
+ * @param context - Response context with either success data or error information
1487
+ * @returns Promise or void - Hook can be async or sync
1615
1488
  *
1616
- * ```
1617
1489
  */
1618
- plugins?: TBasePluginArray;
1490
+ onResponse?: (context: ResponseContext<TCallApiContext$1, TData$1, TErrorData$1>) => Awaitable<unknown>;
1619
1491
  /**
1620
- * Base validation schemas for the client configuration.
1492
+ * Hook called when an HTTP error response (4xx, 5xx) is received from the API.
1621
1493
  *
1622
- * Defines validation rules for requests and responses that apply to all
1623
- * instances created from this base configuration. Provides type safety
1624
- * and runtime validation for API interactions.
1494
+ * This handles server-side errors where an HTTP response was successfully received
1495
+ * but indicates an error condition. Different from `onRequestError` which handles
1496
+ * network-level failures.
1497
+ *
1498
+ * @param context - Response error context with HTTP error details and response
1499
+ * @returns Promise or void - Hook can be async or sync
1625
1500
  */
1626
- schema?: TBaseSchemaAndConfig;
1501
+ onResponseError?: (context: ResponseErrorContext<TCallApiContext$1, TErrorData$1>) => Awaitable<unknown>;
1627
1502
  /**
1628
- * Controls which configuration parts skip automatic merging between base and instance configs.
1503
+ * Hook called during download stream progress tracking.
1629
1504
  *
1630
- * By default, CallApi automatically merges base configuration with instance configuration.
1631
- * This option allows you to disable automatic merging for specific parts when you need
1632
- * manual control over how configurations are combined.
1505
+ * This hook is triggered when downloading data (like file downloads) and provides
1506
+ * progress information about the download. Useful for implementing progress bars
1507
+ * or download status indicators.
1633
1508
  *
1634
- * @enum
1635
- * - **"all"**: Disables automatic merging for both request options and extra options
1636
- * - **"options"**: Disables automatic merging of extra options only (hooks, plugins, etc.)
1637
- * - **"request"**: Disables automatic merging of request options only (headers, body, etc.)
1509
+ * @param context - Response stream context with progress event and response
1510
+ * @returns Promise or void - Hook can be async or sync
1638
1511
  *
1639
- * @example
1640
- * ```ts
1641
- * // Skip all automatic merging - full manual control
1642
- * const client = callApi.create((ctx) => ({
1643
- * skipAutoMergeFor: "all",
1512
+ */
1513
+ onResponseStream?: (context: ResponseStreamContext<TCallApiContext$1>) => Awaitable<unknown>;
1514
+ /**
1515
+ * Hook called when a request is being retried.
1644
1516
  *
1645
- * // Manually decide what to merge
1646
- * baseURL: ctx.options.baseURL, // Keep base URL
1647
- * timeout: 5000, // Override timeout
1648
- * headers: {
1649
- * ...ctx.request.headers, // Merge headers manually
1650
- * "X-Custom": "value" // Add custom header
1651
- * }
1652
- * }));
1517
+ * This hook is triggered before each retry attempt, providing information about
1518
+ * the previous failure and the current retry attempt number. Useful for implementing
1519
+ * custom retry logic, exponential backoff, or retry logging.
1653
1520
  *
1654
- * // Skip options merging - manual plugin/hook control
1655
- * const client = callApi.create((ctx) => ({
1656
- * skipAutoMergeFor: "options",
1521
+ * @param context - Retry context with error details and retry attempt count
1522
+ * @returns Promise or void - Hook can be async or sync
1657
1523
  *
1658
- * // Manually control which plugins to use
1659
- * plugins: [
1660
- * ...ctx.options.plugins?.filter(p => p.name !== "unwanted") || [],
1661
- * customPlugin
1662
- * ],
1524
+ */
1525
+ onRetry?: (response: RetryContext<TCallApiContext$1, TErrorData$1>) => Awaitable<unknown>;
1526
+ /**
1527
+ * Hook called when a successful response (2xx status) is received from the API.
1663
1528
  *
1664
- * // Request options still auto-merge
1665
- * method: "POST"
1666
- * }));
1529
+ * This hook is triggered only for successful responses and provides access to
1530
+ * the parsed response data. Ideal for success logging, caching, or post-processing
1531
+ * of successful API responses.
1667
1532
  *
1668
- * // Skip request merging - manual request control
1669
- * const client = callApi.create((ctx) => ({
1670
- * skipAutoMergeFor: "request",
1533
+ * @param context - Success context with parsed response data and response object
1534
+ * @returns Promise or void - Hook can be async or sync
1671
1535
  *
1672
- * // Extra options still auto-merge (plugins, hooks, etc.)
1536
+ */
1537
+ onSuccess?: (context: SuccessContext<TCallApiContext$1, TData$1>) => Awaitable<unknown>;
1538
+ /**
1539
+ * Hook called when a validation error occurs.
1673
1540
  *
1674
- * // Manually control request options
1675
- * headers: {
1676
- * "Content-Type": "application/json",
1677
- * // Don't merge base headers
1678
- * },
1679
- * method: ctx.request.method || "GET"
1680
- * }));
1541
+ * This hook is triggered when request or response data fails validation against
1542
+ * a defined schema. It provides access to the validation error details and can
1543
+ * be used for custom error handling, logging, or fallback behavior.
1681
1544
  *
1682
- * // Use case: Conditional merging based on request
1683
- * const client = createFetchClient((ctx) => ({
1684
- * skipAutoMergeFor: "options",
1545
+ * @param context - Validation error context with error details and response (if available)
1546
+ * @returns Promise or void - Hook can be async or sync
1685
1547
  *
1686
- * // Only use auth plugin for protected routes
1687
- * plugins: ctx.initURL.includes("/protected/")
1688
- * ? [...(ctx.options.plugins || []), authPlugin]
1689
- * : ctx.options.plugins?.filter(p => p.name !== "auth") || []
1690
- * }));
1691
- * ```
1692
1548
  */
1693
- skipAutoMergeFor?: "all" | "options" | "request";
1694
- };
1695
- type InferExtendSchemaContext<TBaseSchemaRoutes$1 extends BaseCallApiSchemaRoutes, TCurrentRouteSchemaKey extends string> = {
1696
- baseSchemaRoutes: TBaseSchemaRoutes$1;
1697
- currentRouteSchema: GetCurrentRouteSchema<TBaseSchemaRoutes$1, TCurrentRouteSchemaKey>;
1698
- };
1699
- type InferExtendSchemaConfigContext<TBaseSchemaConfig extends CallApiSchemaConfig> = {
1700
- baseSchemaConfig: TBaseSchemaConfig;
1701
- };
1702
- type InferExtendPluginContext<TBasePluginArray extends CallApiPlugin[]> = {
1703
- basePlugins: TBasePluginArray;
1704
- };
1705
- type CallApiExtraOptions<TCallApiContext extends CallApiContext = CallApiContext, TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TResultMode extends ResultModeType = ResultModeType, 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<TCallApiContext, TData$1, TErrorData$1, TResultMode, TThrowOnError, TResponseType, TPluginArray> & {
1549
+ onValidationError?: (context: ValidationErrorContext<TCallApiContext$1>) => Awaitable<unknown>;
1550
+ }
1551
+ 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]> };
1552
+ interface HookConfigOptions {
1706
1553
  /**
1707
- * Array of instance-specific CallApi plugins or a function to configure plugins.
1554
+ * Controls the execution mode of all composed hooks (main + plugin hooks).
1708
1555
  *
1709
- * Instance plugins are added to the base plugins and provide functionality
1710
- * specific to this particular API instance. Can be a static array or a function
1711
- * that receives base plugins and returns the instance plugins.
1556
+ * - **"parallel"**: All hooks execute simultaneously via Promise.all() for better performance
1557
+ * - **"sequential"**: All hooks execute one by one in registration order via await in a loop
1712
1558
  *
1559
+ * This affects how ALL hooks execute together, regardless of their source (main or plugin).
1560
+ *
1561
+ * @default "parallel"
1713
1562
  */
1714
- plugins?: TPluginArray | ((context: TComputedPluginContext) => TPluginArray);
1563
+ hooksExecutionMode?: "parallel" | "sequential";
1564
+ }
1565
+ type RequestContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = {
1715
1566
  /**
1716
- * For instance-specific validation schemas
1717
- *
1718
- * Defines validation rules specific to this API instance, extending or overriding the base schema.
1567
+ * Base configuration object passed to createFetchClient.
1719
1568
  *
1720
- * Can be a static schema object or a function that receives base schema context and returns instance schemas.
1569
+ * Contains the foundational configuration that applies to all requests
1570
+ * made by this client instance, such as baseURL, default headers, and
1571
+ * global options.
1572
+ */
1573
+ baseConfig: Exclude<BaseCallApiConfig, AnyFunction$1>;
1574
+ /**
1575
+ * Instance-specific configuration object passed to the callApi instance.
1721
1576
  *
1577
+ * Contains configuration specific to this particular API call, which
1578
+ * can override or extend the base configuration.
1722
1579
  */
1723
- schema?: TSchema$1 | ((context: TComputedSchemaContext) => TSchema$1);
1580
+ config: CallApiConfig;
1724
1581
  /**
1725
- * Instance-specific schema configuration or a function to configure schema behavior.
1582
+ * Merged options combining base config, instance config, and default options.
1726
1583
  *
1727
- * Controls how validation schemas are applied and behave for this specific API instance.
1728
- * Can override base schema configuration or extend it with instance-specific validation rules.
1584
+ * This is the final resolved configuration that will be used for the request,
1585
+ * with proper precedence applied (instance > base > defaults).
1586
+ */
1587
+ options: CallApiExtraOptionsForHooks<TCallApiContext$1>;
1588
+ /**
1589
+ * Merged request object ready to be sent.
1729
1590
  *
1591
+ * Contains the final request configuration including URL, method, headers,
1592
+ * body, and other fetch options. This object can be modified in onRequest
1593
+ * hooks to customize the outgoing request.
1730
1594
  */
1731
- schemaConfig?: TSchemaConfig$1 | ((context: TComputedSchemaConfigContext) => TSchemaConfig$1);
1595
+ request: CallApiRequestOptionsForHooks;
1732
1596
  };
1733
- type CallApiExtraOptionsForHooks<TCallApiContext extends CallApiContext = CallApiContext> = Hooks & Omit<CallApiExtraOptions<TCallApiContext>, keyof Hooks>;
1734
- type InstanceContext = {
1597
+ type ValidationErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1598
+ error: PossibleValidationError;
1599
+ response: Response | null;
1600
+ }>;
1601
+ type SuccessContext<TCallApiContext$1 extends Pick<CallApiContext, "Data" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TData$1 = TCallApiContext$1["Data"]> = UnmaskType<RequestContext<TCallApiContext$1> & {
1602
+ data: NoInfer<TData$1>;
1603
+ response: Response;
1604
+ }>;
1605
+ 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>, {
1606
+ error: PossibleHTTPError<TErrorData$1>;
1607
+ }>>)>;
1608
+ type RequestErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = RequestContext<TCallApiContext$1> & {
1609
+ error: PossibleJavaScriptError;
1610
+ response: null;
1611
+ };
1612
+ type ErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TErrorData$1 = TCallApiContext$1["ErrorData"]> = UnmaskType<RequestContext<TCallApiContext$1> & ({
1613
+ error: PossibleHTTPError<TErrorData$1>;
1614
+ response: Response;
1615
+ } | {
1616
+ error: PossibleJavaScriptOrValidationError;
1617
+ response: Response | null;
1618
+ })>;
1619
+ type ResponseErrorContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TErrorData$1 = TCallApiContext$1["ErrorData"]> = UnmaskType<Extract<ErrorContext<TCallApiContext$1, TErrorData$1>, {
1620
+ error: PossibleHTTPError<TErrorData$1>;
1621
+ }> & RequestContext<TCallApiContext$1>>;
1622
+ type RetryContext<TCallApiContext$1 extends Pick<CallApiContext, "ErrorData" | "InferredPluginOptions" | "Meta"> = DefaultCallApiContext, TErrorData$1 = TCallApiContext$1["ErrorData"]> = UnmaskType<ErrorContext<TCallApiContext$1, TErrorData$1> & {
1623
+ retryAttemptCount: number;
1624
+ }>;
1625
+ type RequestStreamContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1626
+ event: StreamProgressEvent;
1627
+ requestInstance: Request;
1628
+ }>;
1629
+ type ResponseStreamContext<TCallApiContext$1 extends Pick<CallApiContext, "InferredPluginOptions" | "Meta"> = DefaultCallApiContext> = UnmaskType<RequestContext<TCallApiContext$1> & {
1630
+ event: StreamProgressEvent;
1631
+ response: Response;
1632
+ }>;
1633
+ //#endregion
1634
+ //#region src/plugins.d.ts
1635
+ type PluginSetupContext<TCallApiContext$1 extends CallApiContext = DefaultCallApiContext> = RequestContext<TCallApiContext$1> & {
1735
1636
  initURL: string;
1736
- options: CallApiExtraOptions;
1637
+ };
1638
+ type PluginInitResult = Partial<Omit<PluginSetupContext, "initURL" | "request"> & {
1639
+ initURL: InitURLOrURLObject;
1737
1640
  request: CallApiRequestOptions;
1641
+ }>;
1642
+ 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>;
1643
+ interface CallApiPlugin {
1644
+ /**
1645
+ * Defines additional options that can be passed to callApi
1646
+ */
1647
+ defineExtraOptions?: (...params: never[]) => unknown;
1648
+ /**
1649
+ * A description for the plugin
1650
+ */
1651
+ description?: string;
1652
+ /**
1653
+ * Hooks for the plugin
1654
+ */
1655
+ hooks?: PluginHooks | ((context: PluginSetupContext) => Awaitable<PluginHooks>);
1656
+ /**
1657
+ * A unique id for the plugin
1658
+ */
1659
+ id: string;
1660
+ /**
1661
+ * Middlewares that for the plugin
1662
+ */
1663
+ middlewares?: Middlewares | ((context: PluginSetupContext) => Awaitable<Middlewares>);
1664
+ /**
1665
+ * A name for the plugin
1666
+ */
1667
+ name: string;
1668
+ /**
1669
+ * Base schema for the client.
1670
+ */
1671
+ schema?: BaseCallApiSchemaAndConfig;
1672
+ /**
1673
+ * A function that will be called when the plugin is initialized. This will be called before the any of the other internal functions.
1674
+ */
1675
+ setup?: (context: PluginSetupContext) => Awaitable<PluginInitResult> | Awaitable<void>;
1676
+ /**
1677
+ * A version for the plugin
1678
+ */
1679
+ version?: string;
1680
+ }
1681
+ //#endregion
1682
+ //#region src/types/default-types.d.ts
1683
+ type DefaultDataType = unknown;
1684
+ type DefaultPluginArray = CallApiPlugin[];
1685
+ type DefaultThrowOnError = boolean;
1686
+ type DefaultMetaObject = Record<string, unknown>;
1687
+ type DefaultCallApiContext = Omit<Required<CallApiContext>, "Meta"> & {
1688
+ Meta: GlobalMeta;
1738
1689
  };
1739
- type BaseCallApiConfig<TBaseCallApiContext extends CallApiContext = CallApiContext, TBaseData = DefaultDataType, TBaseErrorData = DefaultDataType, TBaseResultMode extends ResultModeType = ResultModeType, TBaseThrowOnError extends ThrowOnErrorUnion = DefaultThrowOnError, TBaseResponseType extends ResponseTypeType = ResponseTypeType, TBaseSchemaAndConfig extends BaseCallApiSchemaAndConfig = BaseCallApiSchemaAndConfig, TBasePluginArray extends CallApiPlugin[] = DefaultPluginArray, TComputedBaseConfig = BaseCallApiExtraOptions<TBaseCallApiContext, TBaseData, TBaseErrorData, TBaseResultMode, TBaseThrowOnError, TBaseResponseType, TBasePluginArray, TBaseSchemaAndConfig>> = (CallApiRequestOptions & TComputedBaseConfig) | ((context: InstanceContext) => CallApiRequestOptions & TComputedBaseConfig);
1740
- type CallApiConfig<TCallApiContext extends CallApiContext = CallApiContext, TData$1 = DefaultDataType, TErrorData$1 = DefaultDataType, TResultMode extends ResultModeType = ResultModeType, 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, TCallApiContext> & InferRequestOptions<TSchema$1, TInitURL> & Omit<CallApiExtraOptions<TCallApiContext, TData$1, TErrorData$1, TResultMode, TThrowOnError, TResponseType, TBasePluginArray, TPluginArray, TBaseSchemaRoutes$1, TSchema$1, TBaseSchemaConfig, TSchemaConfig$1, TCurrentRouteSchemaKey>, keyof InferExtraOptions<CallApiSchema, BaseCallApiSchemaRoutes, string, CallApiContext>> & Omit<CallApiRequestOptions, keyof InferRequestOptions<CallApiSchema, string>>;
1741
1690
  //#endregion
1742
1691
  //#region src/validation.d.ts
1743
1692
  type ResultVariant = "infer-input" | "infer-output";
@@ -1823,6 +1772,7 @@ type BaseCallApiSchemaAndConfig = {
1823
1772
  routes: BaseCallApiSchemaRoutes;
1824
1773
  };
1825
1774
  //#endregion
1775
+ //#region src/createFetchClient.d.ts
1826
1776
  //#endregion
1827
1777
  //#region src/logger/logger.d.ts
1828
1778
  type ConsoleLikeObject = {
@@ -1862,12 +1812,12 @@ declare const loggerPlugin: (options?: LoggerOptions) => {
1862
1812
  name: "Logger";
1863
1813
  version: "1.1.0";
1864
1814
  hooks: {
1865
- onRequest: (ctx: RequestContext & PluginExtraOptions<unknown>) => void;
1866
- onRequestError: (ctx: RequestContext & {
1815
+ onRequest: (ctx: RequestContext<DefaultCallApiContext>) => void;
1816
+ onRequestError: (ctx: RequestContext<DefaultCallApiContext> & {
1867
1817
  error: PossibleJavaScriptError;
1868
1818
  response: null;
1869
- } & PluginExtraOptions<unknown>) => void;
1870
- onResponseError: (ctx: RequestContext & {
1819
+ }) => void;
1820
+ onResponseError: (ctx: RequestContext<DefaultCallApiContext> & {
1871
1821
  error: {
1872
1822
  errorData: never;
1873
1823
  message: string;
@@ -1875,8 +1825,8 @@ declare const loggerPlugin: (options?: LoggerOptions) => {
1875
1825
  originalError: _zayne_labs_callapi_utils0.HTTPError;
1876
1826
  };
1877
1827
  response: Response;
1878
- } & PluginExtraOptions<unknown>) => void;
1879
- onRetry: (ctx: ((RequestContext & ({
1828
+ }) => void;
1829
+ onRetry: (ctx: (RequestContext<DefaultCallApiContext> & ({
1880
1830
  error: PossibleJavaScriptOrValidationError;
1881
1831
  response: Response | null;
1882
1832
  } | {
@@ -1889,15 +1839,15 @@ declare const loggerPlugin: (options?: LoggerOptions) => {
1889
1839
  response: Response;
1890
1840
  })) & {
1891
1841
  retryAttemptCount: number;
1892
- }) & PluginExtraOptions<unknown>) => void;
1893
- onSuccess: (ctx: RequestContext & {
1842
+ }) => void;
1843
+ onSuccess: (ctx: RequestContext<DefaultCallApiContext> & {
1894
1844
  data: never;
1895
1845
  response: Response;
1896
- } & PluginExtraOptions<unknown>) => void;
1897
- onValidationError: (ctx: RequestContext & {
1846
+ }) => void;
1847
+ onValidationError: (ctx: RequestContext<DefaultCallApiContext> & {
1898
1848
  error: PossibleValidationError;
1899
1849
  response: Response | null;
1900
- } & PluginExtraOptions<unknown>) => void;
1850
+ }) => void;
1901
1851
  };
1902
1852
  };
1903
1853
  //#endregion