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