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