@fgrzl/fetch 1.3.0 → 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 +69 -18
package/dist/cjs/index.js
CHANGED
|
@@ -24,6 +24,16 @@ __export(index_exports, {
|
|
|
24
24
|
FetchError: () => FetchError,
|
|
25
25
|
HttpError: () => HttpError,
|
|
26
26
|
NetworkError: () => NetworkError,
|
|
27
|
+
addAuthentication: () => addAuthentication,
|
|
28
|
+
addAuthorization: () => addAuthorization,
|
|
29
|
+
addBasicStack: () => addBasicStack,
|
|
30
|
+
addCSRF: () => addCSRF,
|
|
31
|
+
addCache: () => addCache,
|
|
32
|
+
addDevelopmentStack: () => addDevelopmentStack,
|
|
33
|
+
addLogging: () => addLogging,
|
|
34
|
+
addProductionStack: () => addProductionStack,
|
|
35
|
+
addRateLimit: () => addRateLimit,
|
|
36
|
+
addRetry: () => addRetry,
|
|
27
37
|
appendQueryParams: () => appendQueryParams,
|
|
28
38
|
buildQueryParams: () => buildQueryParams,
|
|
29
39
|
createAuthenticationMiddleware: () => createAuthenticationMiddleware,
|
|
@@ -32,17 +42,7 @@ __export(index_exports, {
|
|
|
32
42
|
createLoggingMiddleware: () => createLoggingMiddleware,
|
|
33
43
|
createRateLimitMiddleware: () => createRateLimitMiddleware,
|
|
34
44
|
createRetryMiddleware: () => createRetryMiddleware,
|
|
35
|
-
default: () => index_default
|
|
36
|
-
useAuthentication: () => useAuthentication,
|
|
37
|
-
useAuthorization: () => useAuthorization,
|
|
38
|
-
useBasicStack: () => useBasicStack,
|
|
39
|
-
useCSRF: () => useCSRF,
|
|
40
|
-
useCache: () => useCache,
|
|
41
|
-
useDevelopmentStack: () => useDevelopmentStack,
|
|
42
|
-
useLogging: () => useLogging,
|
|
43
|
-
useProductionStack: () => useProductionStack,
|
|
44
|
-
useRateLimit: () => useRateLimit,
|
|
45
|
-
useRetry: () => useRetry
|
|
45
|
+
default: () => index_default
|
|
46
46
|
});
|
|
47
47
|
module.exports = __toCommonJS(index_exports);
|
|
48
48
|
|
|
@@ -52,6 +52,7 @@ var FetchClient = class {
|
|
|
52
52
|
this.middlewares = [];
|
|
53
53
|
this.credentials = config.credentials ?? "same-origin";
|
|
54
54
|
this.baseUrl = config.baseUrl;
|
|
55
|
+
this.defaultTimeout = config.timeout;
|
|
55
56
|
}
|
|
56
57
|
use(middleware) {
|
|
57
58
|
this.middlewares.push(middleware);
|
|
@@ -77,7 +78,7 @@ var FetchClient = class {
|
|
|
77
78
|
*
|
|
78
79
|
* @example Chain with middleware:
|
|
79
80
|
* ```typescript
|
|
80
|
-
* const client =
|
|
81
|
+
* const client = addProductionStack(new FetchClient())
|
|
81
82
|
* .setBaseUrl(process.env.API_BASE_URL);
|
|
82
83
|
* ```
|
|
83
84
|
*/
|
|
@@ -85,11 +86,31 @@ var FetchClient = class {
|
|
|
85
86
|
this.baseUrl = baseUrl;
|
|
86
87
|
return this;
|
|
87
88
|
}
|
|
88
|
-
async request(url, init = {}) {
|
|
89
|
+
async request(url, init = {}, options) {
|
|
89
90
|
const resolvedUrl = this.resolveUrl(url);
|
|
91
|
+
let timeoutId;
|
|
92
|
+
let timeoutController;
|
|
93
|
+
let effectiveSignal = options?.signal || init.signal;
|
|
94
|
+
const timeoutMs = options?.timeout ?? this.defaultTimeout;
|
|
95
|
+
if (timeoutMs && timeoutMs > 0) {
|
|
96
|
+
timeoutController = new AbortController();
|
|
97
|
+
if (effectiveSignal) {
|
|
98
|
+
effectiveSignal.addEventListener("abort", () => {
|
|
99
|
+
timeoutController?.abort();
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
effectiveSignal = timeoutController.signal;
|
|
103
|
+
timeoutId = setTimeout(() => {
|
|
104
|
+
timeoutController?.abort();
|
|
105
|
+
}, timeoutMs);
|
|
106
|
+
}
|
|
90
107
|
let index = 0;
|
|
91
108
|
const execute = async (request) => {
|
|
92
|
-
const currentRequest = request || {
|
|
109
|
+
const currentRequest = request || {
|
|
110
|
+
...init,
|
|
111
|
+
url: resolvedUrl,
|
|
112
|
+
...effectiveSignal ? { signal: effectiveSignal } : {}
|
|
113
|
+
};
|
|
93
114
|
const currentUrl = currentRequest.url || resolvedUrl;
|
|
94
115
|
if (index >= this.middlewares.length) {
|
|
95
116
|
const { url: _, ...requestInit } = currentRequest;
|
|
@@ -102,8 +123,14 @@ var FetchClient = class {
|
|
|
102
123
|
}
|
|
103
124
|
return middleware(currentRequest, execute);
|
|
104
125
|
};
|
|
105
|
-
|
|
106
|
-
|
|
126
|
+
try {
|
|
127
|
+
const result = await execute();
|
|
128
|
+
return result;
|
|
129
|
+
} finally {
|
|
130
|
+
if (timeoutId !== void 0) {
|
|
131
|
+
clearTimeout(timeoutId);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
107
134
|
}
|
|
108
135
|
async coreFetch(request, url) {
|
|
109
136
|
try {
|
|
@@ -135,6 +162,20 @@ var FetchClient = class {
|
|
|
135
162
|
}
|
|
136
163
|
};
|
|
137
164
|
} catch (error) {
|
|
165
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
166
|
+
return {
|
|
167
|
+
data: null,
|
|
168
|
+
status: 0,
|
|
169
|
+
statusText: "Request Aborted",
|
|
170
|
+
headers: new Headers(),
|
|
171
|
+
url,
|
|
172
|
+
ok: false,
|
|
173
|
+
error: {
|
|
174
|
+
message: "Request was aborted",
|
|
175
|
+
body: error
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
138
179
|
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
139
180
|
return {
|
|
140
181
|
data: null,
|
|
@@ -227,6 +268,7 @@ var FetchClient = class {
|
|
|
227
268
|
* @template T - Expected response data type (will be null for HEAD requests)
|
|
228
269
|
* @param url - Request URL
|
|
229
270
|
* @param params - Query parameters to append to URL
|
|
271
|
+
* @param options - Request options (signal, timeout)
|
|
230
272
|
* @returns Promise resolving to typed response (data will always be null)
|
|
231
273
|
*
|
|
232
274
|
* @example Check if resource exists:
|
|
@@ -239,17 +281,16 @@ var FetchClient = class {
|
|
|
239
281
|
* }
|
|
240
282
|
* ```
|
|
241
283
|
*
|
|
242
|
-
* @example
|
|
284
|
+
* @example With cancellation:
|
|
243
285
|
* ```typescript
|
|
244
|
-
* const
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* }
|
|
286
|
+
* const controller = new AbortController();
|
|
287
|
+
* const request = client.head('/api/users', { id: 123 }, { signal: controller.signal });
|
|
288
|
+
* controller.abort(); // Cancel the request
|
|
248
289
|
* ```
|
|
249
290
|
*/
|
|
250
|
-
head(url, params) {
|
|
291
|
+
head(url, params, options) {
|
|
251
292
|
const finalUrl = this.buildUrlWithParams(url, params);
|
|
252
|
-
return this.request(finalUrl, { method: "HEAD" });
|
|
293
|
+
return this.request(finalUrl, { method: "HEAD" }, options);
|
|
253
294
|
}
|
|
254
295
|
/**
|
|
255
296
|
* HEAD request that returns useful metadata about a resource.
|
|
@@ -292,6 +333,7 @@ var FetchClient = class {
|
|
|
292
333
|
* @template T - Expected response data type
|
|
293
334
|
* @param url - Request URL
|
|
294
335
|
* @param params - Query parameters to append to URL
|
|
336
|
+
* @param options - Request options (signal, timeout)
|
|
295
337
|
* @returns Promise resolving to typed response
|
|
296
338
|
*
|
|
297
339
|
* @example
|
|
@@ -300,10 +342,15 @@ var FetchClient = class {
|
|
|
300
342
|
* const filteredUsers = await client.get<User[]>('/api/users', { status: 'active', limit: 10 });
|
|
301
343
|
* if (users.ok) console.log(users.data);
|
|
302
344
|
* ```
|
|
345
|
+
*
|
|
346
|
+
* @example With timeout:
|
|
347
|
+
* ```typescript
|
|
348
|
+
* const users = await client.get<User[]>('/api/users', {}, { timeout: 5000 });
|
|
349
|
+
* ```
|
|
303
350
|
*/
|
|
304
|
-
get(url, params) {
|
|
351
|
+
get(url, params, options) {
|
|
305
352
|
const finalUrl = this.buildUrlWithParams(url, params);
|
|
306
|
-
return this.request(finalUrl, { method: "GET" });
|
|
353
|
+
return this.request(finalUrl, { method: "GET" }, options);
|
|
307
354
|
}
|
|
308
355
|
/**
|
|
309
356
|
* POST request with automatic JSON serialization.
|
|
@@ -312,23 +359,35 @@ var FetchClient = class {
|
|
|
312
359
|
* @param url - Request URL
|
|
313
360
|
* @param body - Request body (auto-serialized to JSON)
|
|
314
361
|
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
362
|
+
* @param options - Request options (signal, timeout)
|
|
315
363
|
* @returns Promise resolving to typed response
|
|
316
364
|
*
|
|
317
365
|
* @example
|
|
318
366
|
* ```typescript
|
|
319
367
|
* const result = await client.post<User>('/api/users', { name: 'John' });
|
|
320
368
|
* ```
|
|
369
|
+
*
|
|
370
|
+
* @example With cancellation:
|
|
371
|
+
* ```typescript
|
|
372
|
+
* const controller = new AbortController();
|
|
373
|
+
* const result = client.post('/api/users', { name: 'John' }, {}, { signal: controller.signal });
|
|
374
|
+
* controller.abort();
|
|
375
|
+
* ```
|
|
321
376
|
*/
|
|
322
|
-
post(url, body, headers) {
|
|
377
|
+
post(url, body, headers, options) {
|
|
323
378
|
const requestHeaders = {
|
|
324
379
|
"Content-Type": "application/json",
|
|
325
380
|
...headers ?? {}
|
|
326
381
|
};
|
|
327
|
-
return this.request(
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
382
|
+
return this.request(
|
|
383
|
+
url,
|
|
384
|
+
{
|
|
385
|
+
method: "POST",
|
|
386
|
+
headers: requestHeaders,
|
|
387
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
388
|
+
},
|
|
389
|
+
options
|
|
390
|
+
);
|
|
332
391
|
}
|
|
333
392
|
/**
|
|
334
393
|
* PUT request with automatic JSON serialization.
|
|
@@ -337,18 +396,23 @@ var FetchClient = class {
|
|
|
337
396
|
* @param url - Request URL
|
|
338
397
|
* @param body - Request body (auto-serialized to JSON)
|
|
339
398
|
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
399
|
+
* @param options - Request options (signal, timeout)
|
|
340
400
|
* @returns Promise resolving to typed response
|
|
341
401
|
*/
|
|
342
|
-
put(url, body, headers) {
|
|
402
|
+
put(url, body, headers, options) {
|
|
343
403
|
const requestHeaders = {
|
|
344
404
|
"Content-Type": "application/json",
|
|
345
405
|
...headers ?? {}
|
|
346
406
|
};
|
|
347
|
-
return this.request(
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
407
|
+
return this.request(
|
|
408
|
+
url,
|
|
409
|
+
{
|
|
410
|
+
method: "PUT",
|
|
411
|
+
headers: requestHeaders,
|
|
412
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
413
|
+
},
|
|
414
|
+
options
|
|
415
|
+
);
|
|
352
416
|
}
|
|
353
417
|
/**
|
|
354
418
|
* PATCH request with automatic JSON serialization.
|
|
@@ -357,18 +421,23 @@ var FetchClient = class {
|
|
|
357
421
|
* @param url - Request URL
|
|
358
422
|
* @param body - Request body (auto-serialized to JSON)
|
|
359
423
|
* @param headers - Additional headers (Content-Type: application/json is default)
|
|
424
|
+
* @param options - Request options (signal, timeout)
|
|
360
425
|
* @returns Promise resolving to typed response
|
|
361
426
|
*/
|
|
362
|
-
patch(url, body, headers) {
|
|
427
|
+
patch(url, body, headers, options) {
|
|
363
428
|
const requestHeaders = {
|
|
364
429
|
"Content-Type": "application/json",
|
|
365
430
|
...headers ?? {}
|
|
366
431
|
};
|
|
367
|
-
return this.request(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
432
|
+
return this.request(
|
|
433
|
+
url,
|
|
434
|
+
{
|
|
435
|
+
method: "PATCH",
|
|
436
|
+
headers: requestHeaders,
|
|
437
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
438
|
+
},
|
|
439
|
+
options
|
|
440
|
+
);
|
|
372
441
|
}
|
|
373
442
|
/**
|
|
374
443
|
* DELETE request with query parameter support.
|
|
@@ -376,6 +445,7 @@ var FetchClient = class {
|
|
|
376
445
|
* @template T - Expected response data type
|
|
377
446
|
* @param url - Request URL
|
|
378
447
|
* @param params - Query parameters to append to URL
|
|
448
|
+
* @param options - Request options (signal, timeout)
|
|
379
449
|
* @returns Promise resolving to typed response
|
|
380
450
|
*
|
|
381
451
|
* @example
|
|
@@ -385,9 +455,9 @@ var FetchClient = class {
|
|
|
385
455
|
* if (result.ok) console.log('Deleted successfully');
|
|
386
456
|
* ```
|
|
387
457
|
*/
|
|
388
|
-
del(url, params) {
|
|
458
|
+
del(url, params, options) {
|
|
389
459
|
const finalUrl = this.buildUrlWithParams(url, params);
|
|
390
|
-
return this.request(finalUrl, { method: "DELETE" });
|
|
460
|
+
return this.request(finalUrl, { method: "DELETE" }, options);
|
|
391
461
|
}
|
|
392
462
|
};
|
|
393
463
|
|
|
@@ -445,7 +515,7 @@ function createAuthenticationMiddleware(options) {
|
|
|
445
515
|
}
|
|
446
516
|
|
|
447
517
|
// src/middleware/authentication/index.ts
|
|
448
|
-
function
|
|
518
|
+
function addAuthentication(client, options) {
|
|
449
519
|
return client.use(createAuthenticationMiddleware(options));
|
|
450
520
|
}
|
|
451
521
|
|
|
@@ -524,7 +594,7 @@ function createAuthorizationMiddleware(options = {}) {
|
|
|
524
594
|
}
|
|
525
595
|
|
|
526
596
|
// src/middleware/authorization/index.ts
|
|
527
|
-
function
|
|
597
|
+
function addAuthorization(client, options = {}) {
|
|
528
598
|
return client.use(createAuthorizationMiddleware(options));
|
|
529
599
|
}
|
|
530
600
|
|
|
@@ -668,7 +738,7 @@ function createCacheMiddleware(options = {}) {
|
|
|
668
738
|
}
|
|
669
739
|
|
|
670
740
|
// src/middleware/cache/index.ts
|
|
671
|
-
function
|
|
741
|
+
function addCache(client, options = {}) {
|
|
672
742
|
return client.use(createCacheMiddleware(options));
|
|
673
743
|
}
|
|
674
744
|
|
|
@@ -725,7 +795,7 @@ function createCSRFMiddleware(options = {}) {
|
|
|
725
795
|
}
|
|
726
796
|
|
|
727
797
|
// src/middleware/csrf/index.ts
|
|
728
|
-
function
|
|
798
|
+
function addCSRF(client, options = {}) {
|
|
729
799
|
return client.use(createCSRFMiddleware(options));
|
|
730
800
|
}
|
|
731
801
|
|
|
@@ -857,7 +927,7 @@ function getHeadersObject(headers) {
|
|
|
857
927
|
}
|
|
858
928
|
|
|
859
929
|
// src/middleware/logging/index.ts
|
|
860
|
-
function
|
|
930
|
+
function addLogging(client, options = {}) {
|
|
861
931
|
return client.use(createLoggingMiddleware(options));
|
|
862
932
|
}
|
|
863
933
|
|
|
@@ -940,7 +1010,7 @@ function createRateLimitMiddleware(options = {}) {
|
|
|
940
1010
|
}
|
|
941
1011
|
|
|
942
1012
|
// src/middleware/rate-limit/index.ts
|
|
943
|
-
function
|
|
1013
|
+
function addRateLimit(client, options = {}) {
|
|
944
1014
|
return client.use(createRateLimitMiddleware(options));
|
|
945
1015
|
}
|
|
946
1016
|
|
|
@@ -1038,40 +1108,40 @@ function createRetryMiddleware(options = {}) {
|
|
|
1038
1108
|
}
|
|
1039
1109
|
|
|
1040
1110
|
// src/middleware/retry/index.ts
|
|
1041
|
-
function
|
|
1111
|
+
function addRetry(client, options = {}) {
|
|
1042
1112
|
return client.use(createRetryMiddleware(options));
|
|
1043
1113
|
}
|
|
1044
1114
|
|
|
1045
1115
|
// src/middleware/index.ts
|
|
1046
|
-
function
|
|
1116
|
+
function addProductionStack(client, config = {}) {
|
|
1047
1117
|
let enhanced = client;
|
|
1048
1118
|
if (config.auth) {
|
|
1049
|
-
enhanced =
|
|
1119
|
+
enhanced = addAuthentication(enhanced, config.auth);
|
|
1050
1120
|
}
|
|
1051
1121
|
if (config.cache !== void 0) {
|
|
1052
|
-
enhanced =
|
|
1122
|
+
enhanced = addCache(enhanced, config.cache);
|
|
1053
1123
|
}
|
|
1054
1124
|
if (config.retry !== void 0) {
|
|
1055
|
-
enhanced =
|
|
1125
|
+
enhanced = addRetry(enhanced, config.retry);
|
|
1056
1126
|
}
|
|
1057
1127
|
if (config.rateLimit !== void 0) {
|
|
1058
|
-
enhanced =
|
|
1128
|
+
enhanced = addRateLimit(enhanced, config.rateLimit);
|
|
1059
1129
|
}
|
|
1060
1130
|
if (config.logging !== void 0) {
|
|
1061
|
-
enhanced =
|
|
1131
|
+
enhanced = addLogging(enhanced, config.logging);
|
|
1062
1132
|
}
|
|
1063
1133
|
return enhanced;
|
|
1064
1134
|
}
|
|
1065
|
-
function
|
|
1135
|
+
function addDevelopmentStack(client, config = {}) {
|
|
1066
1136
|
let enhanced = client;
|
|
1067
1137
|
if (config.auth) {
|
|
1068
|
-
enhanced =
|
|
1138
|
+
enhanced = addAuthentication(enhanced, config.auth);
|
|
1069
1139
|
}
|
|
1070
|
-
enhanced =
|
|
1140
|
+
enhanced = addRetry(enhanced, {
|
|
1071
1141
|
maxRetries: 1,
|
|
1072
1142
|
delay: 100
|
|
1073
1143
|
});
|
|
1074
|
-
enhanced =
|
|
1144
|
+
enhanced = addLogging(enhanced, {
|
|
1075
1145
|
level: "debug",
|
|
1076
1146
|
includeRequestHeaders: true,
|
|
1077
1147
|
includeResponseHeaders: true,
|
|
@@ -1080,8 +1150,8 @@ function useDevelopmentStack(client, config = {}) {
|
|
|
1080
1150
|
});
|
|
1081
1151
|
return enhanced;
|
|
1082
1152
|
}
|
|
1083
|
-
function
|
|
1084
|
-
return
|
|
1153
|
+
function addBasicStack(client, config) {
|
|
1154
|
+
return addRetry(addAuthentication(client, config.auth), { maxRetries: 2 });
|
|
1085
1155
|
}
|
|
1086
1156
|
|
|
1087
1157
|
// src/errors/index.ts
|
|
@@ -1163,7 +1233,7 @@ function appendQueryParams(baseUrl, query) {
|
|
|
1163
1233
|
}
|
|
1164
1234
|
|
|
1165
1235
|
// src/index.ts
|
|
1166
|
-
var api =
|
|
1236
|
+
var api = addProductionStack(
|
|
1167
1237
|
new FetchClient({
|
|
1168
1238
|
// Smart default: include cookies for session-based auth
|
|
1169
1239
|
// Can be overridden by creating a custom FetchClient
|
|
@@ -1197,6 +1267,16 @@ var index_default = api;
|
|
|
1197
1267
|
FetchError,
|
|
1198
1268
|
HttpError,
|
|
1199
1269
|
NetworkError,
|
|
1270
|
+
addAuthentication,
|
|
1271
|
+
addAuthorization,
|
|
1272
|
+
addBasicStack,
|
|
1273
|
+
addCSRF,
|
|
1274
|
+
addCache,
|
|
1275
|
+
addDevelopmentStack,
|
|
1276
|
+
addLogging,
|
|
1277
|
+
addProductionStack,
|
|
1278
|
+
addRateLimit,
|
|
1279
|
+
addRetry,
|
|
1200
1280
|
appendQueryParams,
|
|
1201
1281
|
buildQueryParams,
|
|
1202
1282
|
createAuthenticationMiddleware,
|
|
@@ -1204,16 +1284,6 @@ var index_default = api;
|
|
|
1204
1284
|
createCacheMiddleware,
|
|
1205
1285
|
createLoggingMiddleware,
|
|
1206
1286
|
createRateLimitMiddleware,
|
|
1207
|
-
createRetryMiddleware
|
|
1208
|
-
useAuthentication,
|
|
1209
|
-
useAuthorization,
|
|
1210
|
-
useBasicStack,
|
|
1211
|
-
useCSRF,
|
|
1212
|
-
useCache,
|
|
1213
|
-
useDevelopmentStack,
|
|
1214
|
-
useLogging,
|
|
1215
|
-
useProductionStack,
|
|
1216
|
-
useRateLimit,
|
|
1217
|
-
useRetry
|
|
1287
|
+
createRetryMiddleware
|
|
1218
1288
|
});
|
|
1219
1289
|
//# sourceMappingURL=index.js.map
|