@fgrzl/fetch 1.4.0-alpha.2 → 1.4.0
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/CONTRIBUTING.md +2 -2
- package/LICENSE +201 -21
- package/README.md +88 -82
- package/dist/cjs/index.js +146 -76
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/index.d.ts +124 -77
- package/dist/index.js +127 -79
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +67 -16
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ var FetchClient = class {
|
|
|
4
4
|
this.middlewares = [];
|
|
5
5
|
this.credentials = config.credentials ?? "same-origin";
|
|
6
6
|
this.baseUrl = config.baseUrl;
|
|
7
|
+
this.defaultTimeout = config.timeout;
|
|
7
8
|
}
|
|
8
9
|
use(middleware) {
|
|
9
10
|
this.middlewares.push(middleware);
|
|
@@ -29,7 +30,7 @@ var FetchClient = class {
|
|
|
29
30
|
*
|
|
30
31
|
* @example Chain with middleware:
|
|
31
32
|
* ```typescript
|
|
32
|
-
* const client =
|
|
33
|
+
* const client = addProductionStack(new FetchClient())
|
|
33
34
|
* .setBaseUrl(process.env.API_BASE_URL);
|
|
34
35
|
* ```
|
|
35
36
|
*/
|
|
@@ -37,11 +38,31 @@ var FetchClient = class {
|
|
|
37
38
|
this.baseUrl = baseUrl;
|
|
38
39
|
return this;
|
|
39
40
|
}
|
|
40
|
-
async request(url, init = {}) {
|
|
41
|
+
async request(url, init = {}, options) {
|
|
41
42
|
const resolvedUrl = this.resolveUrl(url);
|
|
43
|
+
let timeoutId;
|
|
44
|
+
let timeoutController;
|
|
45
|
+
let effectiveSignal = options?.signal || init.signal;
|
|
46
|
+
const timeoutMs = options?.timeout ?? this.defaultTimeout;
|
|
47
|
+
if (timeoutMs && timeoutMs > 0) {
|
|
48
|
+
timeoutController = new AbortController();
|
|
49
|
+
if (effectiveSignal) {
|
|
50
|
+
effectiveSignal.addEventListener("abort", () => {
|
|
51
|
+
timeoutController?.abort();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
effectiveSignal = timeoutController.signal;
|
|
55
|
+
timeoutId = setTimeout(() => {
|
|
56
|
+
timeoutController?.abort();
|
|
57
|
+
}, timeoutMs);
|
|
58
|
+
}
|
|
42
59
|
let index = 0;
|
|
43
60
|
const execute = async (request) => {
|
|
44
|
-
const currentRequest = request || {
|
|
61
|
+
const currentRequest = request || {
|
|
62
|
+
...init,
|
|
63
|
+
url: resolvedUrl,
|
|
64
|
+
...effectiveSignal ? { signal: effectiveSignal } : {}
|
|
65
|
+
};
|
|
45
66
|
const currentUrl = currentRequest.url || resolvedUrl;
|
|
46
67
|
if (index >= this.middlewares.length) {
|
|
47
68
|
const { url: _, ...requestInit } = currentRequest;
|
|
@@ -54,8 +75,14 @@ var FetchClient = class {
|
|
|
54
75
|
}
|
|
55
76
|
return middleware(currentRequest, execute);
|
|
56
77
|
};
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
try {
|
|
79
|
+
const result = await execute();
|
|
80
|
+
return result;
|
|
81
|
+
} finally {
|
|
82
|
+
if (timeoutId !== void 0) {
|
|
83
|
+
clearTimeout(timeoutId);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
59
86
|
}
|
|
60
87
|
async coreFetch(request, url) {
|
|
61
88
|
try {
|
|
@@ -87,6 +114,20 @@ var FetchClient = class {
|
|
|
87
114
|
}
|
|
88
115
|
};
|
|
89
116
|
} catch (error) {
|
|
117
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
118
|
+
return {
|
|
119
|
+
data: null,
|
|
120
|
+
status: 0,
|
|
121
|
+
statusText: "Request Aborted",
|
|
122
|
+
headers: new Headers(),
|
|
123
|
+
url,
|
|
124
|
+
ok: false,
|
|
125
|
+
error: {
|
|
126
|
+
message: "Request was aborted",
|
|
127
|
+
body: error
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
90
131
|
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
91
132
|
return {
|
|
92
133
|
data: null,
|
|
@@ -179,6 +220,7 @@ var FetchClient = class {
|
|
|
179
220
|
* @template T - Expected response data type (will be null for HEAD requests)
|
|
180
221
|
* @param url - Request URL
|
|
181
222
|
* @param params - Query parameters to append to URL
|
|
223
|
+
* @param options - Request options (signal, timeout)
|
|
182
224
|
* @returns Promise resolving to typed response (data will always be null)
|
|
183
225
|
*
|
|
184
226
|
* @example Check if resource exists:
|
|
@@ -191,17 +233,16 @@ var FetchClient = class {
|
|
|
191
233
|
* }
|
|
192
234
|
* ```
|
|
193
235
|
*
|
|
194
|
-
* @example
|
|
236
|
+
* @example With cancellation:
|
|
195
237
|
* ```typescript
|
|
196
|
-
* const
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* }
|
|
238
|
+
* const controller = new AbortController();
|
|
239
|
+
* const request = client.head('/api/users', { id: 123 }, { signal: controller.signal });
|
|
240
|
+
* controller.abort(); // Cancel the request
|
|
200
241
|
* ```
|
|
201
242
|
*/
|
|
202
|
-
head(url, params) {
|
|
243
|
+
head(url, params, options) {
|
|
203
244
|
const finalUrl = this.buildUrlWithParams(url, params);
|
|
204
|
-
return this.request(finalUrl, { method: "HEAD" });
|
|
245
|
+
return this.request(finalUrl, { method: "HEAD" }, options);
|
|
205
246
|
}
|
|
206
247
|
/**
|
|
207
248
|
* HEAD request that returns useful metadata about a resource.
|
|
@@ -244,6 +285,7 @@ var FetchClient = class {
|
|
|
244
285
|
* @template T - Expected response data type
|
|
245
286
|
* @param url - Request URL
|
|
246
287
|
* @param params - Query parameters to append to URL
|
|
288
|
+
* @param options - Request options (signal, timeout)
|
|
247
289
|
* @returns Promise resolving to typed response
|
|
248
290
|
*
|
|
249
291
|
* @example
|
|
@@ -252,10 +294,15 @@ var FetchClient = class {
|
|
|
252
294
|
* const filteredUsers = await client.get<User[]>('/api/users', { status: 'active', limit: 10 });
|
|
253
295
|
* if (users.ok) console.log(users.data);
|
|
254
296
|
* ```
|
|
297
|
+
*
|
|
298
|
+
* @example With timeout:
|
|
299
|
+
* ```typescript
|
|
300
|
+
* const users = await client.get<User[]>('/api/users', {}, { timeout: 5000 });
|
|
301
|
+
* ```
|
|
255
302
|
*/
|
|
256
|
-
get(url, params) {
|
|
303
|
+
get(url, params, options) {
|
|
257
304
|
const finalUrl = this.buildUrlWithParams(url, params);
|
|
258
|
-
return this.request(finalUrl, { method: "GET" });
|
|
305
|
+
return this.request(finalUrl, { method: "GET" }, options);
|
|
259
306
|
}
|
|
260
307
|
/**
|
|
261
308
|
* POST request with automatic JSON serialization.
|
|
@@ -264,23 +311,35 @@ var FetchClient = class {
|
|
|
264
311
|
* @param url - Request URL
|
|
265
312
|
* @param body - Request body (auto-serialized to JSON)
|
|
266
313
|
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
314
|
+
* @param options - Request options (signal, timeout)
|
|
267
315
|
* @returns Promise resolving to typed response
|
|
268
316
|
*
|
|
269
317
|
* @example
|
|
270
318
|
* ```typescript
|
|
271
319
|
* const result = await client.post<User>('/api/users', { name: 'John' });
|
|
272
320
|
* ```
|
|
321
|
+
*
|
|
322
|
+
* @example With cancellation:
|
|
323
|
+
* ```typescript
|
|
324
|
+
* const controller = new AbortController();
|
|
325
|
+
* const result = client.post('/api/users', { name: 'John' }, {}, { signal: controller.signal });
|
|
326
|
+
* controller.abort();
|
|
327
|
+
* ```
|
|
273
328
|
*/
|
|
274
|
-
post(url, body, headers) {
|
|
329
|
+
post(url, body, headers, options) {
|
|
275
330
|
const requestHeaders = {
|
|
276
331
|
"Content-Type": "application/json",
|
|
277
332
|
...headers ?? {}
|
|
278
333
|
};
|
|
279
|
-
return this.request(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
334
|
+
return this.request(
|
|
335
|
+
url,
|
|
336
|
+
{
|
|
337
|
+
method: "POST",
|
|
338
|
+
headers: requestHeaders,
|
|
339
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
340
|
+
},
|
|
341
|
+
options
|
|
342
|
+
);
|
|
284
343
|
}
|
|
285
344
|
/**
|
|
286
345
|
* PUT request with automatic JSON serialization.
|
|
@@ -289,18 +348,23 @@ var FetchClient = class {
|
|
|
289
348
|
* @param url - Request URL
|
|
290
349
|
* @param body - Request body (auto-serialized to JSON)
|
|
291
350
|
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
351
|
+
* @param options - Request options (signal, timeout)
|
|
292
352
|
* @returns Promise resolving to typed response
|
|
293
353
|
*/
|
|
294
|
-
put(url, body, headers) {
|
|
354
|
+
put(url, body, headers, options) {
|
|
295
355
|
const requestHeaders = {
|
|
296
356
|
"Content-Type": "application/json",
|
|
297
357
|
...headers ?? {}
|
|
298
358
|
};
|
|
299
|
-
return this.request(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
359
|
+
return this.request(
|
|
360
|
+
url,
|
|
361
|
+
{
|
|
362
|
+
method: "PUT",
|
|
363
|
+
headers: requestHeaders,
|
|
364
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
365
|
+
},
|
|
366
|
+
options
|
|
367
|
+
);
|
|
304
368
|
}
|
|
305
369
|
/**
|
|
306
370
|
* PATCH request with automatic JSON serialization.
|
|
@@ -309,18 +373,23 @@ var FetchClient = class {
|
|
|
309
373
|
* @param url - Request URL
|
|
310
374
|
* @param body - Request body (auto-serialized to JSON)
|
|
311
375
|
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
376
|
+
* @param options - Request options (signal, timeout)
|
|
312
377
|
* @returns Promise resolving to typed response
|
|
313
378
|
*/
|
|
314
|
-
patch(url, body, headers) {
|
|
379
|
+
patch(url, body, headers, options) {
|
|
315
380
|
const requestHeaders = {
|
|
316
381
|
"Content-Type": "application/json",
|
|
317
382
|
...headers ?? {}
|
|
318
383
|
};
|
|
319
|
-
return this.request(
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
384
|
+
return this.request(
|
|
385
|
+
url,
|
|
386
|
+
{
|
|
387
|
+
method: "PATCH",
|
|
388
|
+
headers: requestHeaders,
|
|
389
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
390
|
+
},
|
|
391
|
+
options
|
|
392
|
+
);
|
|
324
393
|
}
|
|
325
394
|
/**
|
|
326
395
|
* DELETE request with query parameter support.
|
|
@@ -328,6 +397,7 @@ var FetchClient = class {
|
|
|
328
397
|
* @template T - Expected response data type
|
|
329
398
|
* @param url - Request URL
|
|
330
399
|
* @param params - Query parameters to append to URL
|
|
400
|
+
* @param options - Request options (signal, timeout)
|
|
331
401
|
* @returns Promise resolving to typed response
|
|
332
402
|
*
|
|
333
403
|
* @example
|
|
@@ -337,9 +407,9 @@ var FetchClient = class {
|
|
|
337
407
|
* if (result.ok) console.log('Deleted successfully');
|
|
338
408
|
* ```
|
|
339
409
|
*/
|
|
340
|
-
del(url, params) {
|
|
410
|
+
del(url, params, options) {
|
|
341
411
|
const finalUrl = this.buildUrlWithParams(url, params);
|
|
342
|
-
return this.request(finalUrl, { method: "DELETE" });
|
|
412
|
+
return this.request(finalUrl, { method: "DELETE" }, options);
|
|
343
413
|
}
|
|
344
414
|
};
|
|
345
415
|
|
|
@@ -397,7 +467,7 @@ function createAuthenticationMiddleware(options) {
|
|
|
397
467
|
}
|
|
398
468
|
|
|
399
469
|
// src/middleware/authentication/index.ts
|
|
400
|
-
function
|
|
470
|
+
function addAuthentication(client, options) {
|
|
401
471
|
return client.use(createAuthenticationMiddleware(options));
|
|
402
472
|
}
|
|
403
473
|
|
|
@@ -476,7 +546,7 @@ function createAuthorizationMiddleware(options = {}) {
|
|
|
476
546
|
}
|
|
477
547
|
|
|
478
548
|
// src/middleware/authorization/index.ts
|
|
479
|
-
function
|
|
549
|
+
function addAuthorization(client, options = {}) {
|
|
480
550
|
return client.use(createAuthorizationMiddleware(options));
|
|
481
551
|
}
|
|
482
552
|
|
|
@@ -620,7 +690,7 @@ function createCacheMiddleware(options = {}) {
|
|
|
620
690
|
}
|
|
621
691
|
|
|
622
692
|
// src/middleware/cache/index.ts
|
|
623
|
-
function
|
|
693
|
+
function addCache(client, options = {}) {
|
|
624
694
|
return client.use(createCacheMiddleware(options));
|
|
625
695
|
}
|
|
626
696
|
|
|
@@ -677,7 +747,7 @@ function createCSRFMiddleware(options = {}) {
|
|
|
677
747
|
}
|
|
678
748
|
|
|
679
749
|
// src/middleware/csrf/index.ts
|
|
680
|
-
function
|
|
750
|
+
function addCSRF(client, options = {}) {
|
|
681
751
|
return client.use(createCSRFMiddleware(options));
|
|
682
752
|
}
|
|
683
753
|
|
|
@@ -809,7 +879,7 @@ function getHeadersObject(headers) {
|
|
|
809
879
|
}
|
|
810
880
|
|
|
811
881
|
// src/middleware/logging/index.ts
|
|
812
|
-
function
|
|
882
|
+
function addLogging(client, options = {}) {
|
|
813
883
|
return client.use(createLoggingMiddleware(options));
|
|
814
884
|
}
|
|
815
885
|
|
|
@@ -892,7 +962,7 @@ function createRateLimitMiddleware(options = {}) {
|
|
|
892
962
|
}
|
|
893
963
|
|
|
894
964
|
// src/middleware/rate-limit/index.ts
|
|
895
|
-
function
|
|
965
|
+
function addRateLimit(client, options = {}) {
|
|
896
966
|
return client.use(createRateLimitMiddleware(options));
|
|
897
967
|
}
|
|
898
968
|
|
|
@@ -990,40 +1060,40 @@ function createRetryMiddleware(options = {}) {
|
|
|
990
1060
|
}
|
|
991
1061
|
|
|
992
1062
|
// src/middleware/retry/index.ts
|
|
993
|
-
function
|
|
1063
|
+
function addRetry(client, options = {}) {
|
|
994
1064
|
return client.use(createRetryMiddleware(options));
|
|
995
1065
|
}
|
|
996
1066
|
|
|
997
1067
|
// src/middleware/index.ts
|
|
998
|
-
function
|
|
1068
|
+
function addProductionStack(client, config = {}) {
|
|
999
1069
|
let enhanced = client;
|
|
1000
1070
|
if (config.auth) {
|
|
1001
|
-
enhanced =
|
|
1071
|
+
enhanced = addAuthentication(enhanced, config.auth);
|
|
1002
1072
|
}
|
|
1003
1073
|
if (config.cache !== void 0) {
|
|
1004
|
-
enhanced =
|
|
1074
|
+
enhanced = addCache(enhanced, config.cache);
|
|
1005
1075
|
}
|
|
1006
1076
|
if (config.retry !== void 0) {
|
|
1007
|
-
enhanced =
|
|
1077
|
+
enhanced = addRetry(enhanced, config.retry);
|
|
1008
1078
|
}
|
|
1009
1079
|
if (config.rateLimit !== void 0) {
|
|
1010
|
-
enhanced =
|
|
1080
|
+
enhanced = addRateLimit(enhanced, config.rateLimit);
|
|
1011
1081
|
}
|
|
1012
1082
|
if (config.logging !== void 0) {
|
|
1013
|
-
enhanced =
|
|
1083
|
+
enhanced = addLogging(enhanced, config.logging);
|
|
1014
1084
|
}
|
|
1015
1085
|
return enhanced;
|
|
1016
1086
|
}
|
|
1017
|
-
function
|
|
1087
|
+
function addDevelopmentStack(client, config = {}) {
|
|
1018
1088
|
let enhanced = client;
|
|
1019
1089
|
if (config.auth) {
|
|
1020
|
-
enhanced =
|
|
1090
|
+
enhanced = addAuthentication(enhanced, config.auth);
|
|
1021
1091
|
}
|
|
1022
|
-
enhanced =
|
|
1092
|
+
enhanced = addRetry(enhanced, {
|
|
1023
1093
|
maxRetries: 1,
|
|
1024
1094
|
delay: 100
|
|
1025
1095
|
});
|
|
1026
|
-
enhanced =
|
|
1096
|
+
enhanced = addLogging(enhanced, {
|
|
1027
1097
|
level: "debug",
|
|
1028
1098
|
includeRequestHeaders: true,
|
|
1029
1099
|
includeResponseHeaders: true,
|
|
@@ -1032,8 +1102,8 @@ function useDevelopmentStack(client, config = {}) {
|
|
|
1032
1102
|
});
|
|
1033
1103
|
return enhanced;
|
|
1034
1104
|
}
|
|
1035
|
-
function
|
|
1036
|
-
return
|
|
1105
|
+
function addBasicStack(client, config) {
|
|
1106
|
+
return addRetry(addAuthentication(client, config.auth), { maxRetries: 2 });
|
|
1037
1107
|
}
|
|
1038
1108
|
|
|
1039
1109
|
// src/errors/index.ts
|
|
@@ -1115,7 +1185,7 @@ function appendQueryParams(baseUrl, query) {
|
|
|
1115
1185
|
}
|
|
1116
1186
|
|
|
1117
1187
|
// src/index.ts
|
|
1118
|
-
var api =
|
|
1188
|
+
var api = addProductionStack(
|
|
1119
1189
|
new FetchClient({
|
|
1120
1190
|
// Smart default: include cookies for session-based auth
|
|
1121
1191
|
// Can be overridden by creating a custom FetchClient
|
|
@@ -1143,29 +1213,7 @@ var api = useProductionStack(
|
|
|
1143
1213
|
}
|
|
1144
1214
|
);
|
|
1145
1215
|
var index_default = api;
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
HttpError,
|
|
1150
|
-
NetworkError,
|
|
1151
|
-
appendQueryParams,
|
|
1152
|
-
buildQueryParams,
|
|
1153
|
-
createAuthenticationMiddleware,
|
|
1154
|
-
createAuthorizationMiddleware,
|
|
1155
|
-
createCacheMiddleware,
|
|
1156
|
-
createLoggingMiddleware,
|
|
1157
|
-
createRateLimitMiddleware,
|
|
1158
|
-
createRetryMiddleware,
|
|
1159
|
-
index_default as default,
|
|
1160
|
-
useAuthentication,
|
|
1161
|
-
useAuthorization,
|
|
1162
|
-
useBasicStack,
|
|
1163
|
-
useCSRF,
|
|
1164
|
-
useCache,
|
|
1165
|
-
useDevelopmentStack,
|
|
1166
|
-
useLogging,
|
|
1167
|
-
useProductionStack,
|
|
1168
|
-
useRateLimit,
|
|
1169
|
-
useRetry
|
|
1170
|
-
};
|
|
1216
|
+
|
|
1217
|
+
export { FetchClient, FetchError, HttpError, NetworkError, addAuthentication, addAuthorization, addBasicStack, addCSRF, addCache, addDevelopmentStack, addLogging, addProductionStack, addRateLimit, addRetry, appendQueryParams, buildQueryParams, createAuthenticationMiddleware, createAuthorizationMiddleware, createCacheMiddleware, createLoggingMiddleware, createRateLimitMiddleware, createRetryMiddleware, index_default as default };
|
|
1218
|
+
//# sourceMappingURL=index.js.map
|
|
1171
1219
|
//# sourceMappingURL=index.js.map
|