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