@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/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 = useProductionStack(new FetchClient())
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 || { ...init, url: resolvedUrl };
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
- const result = await execute();
106
- return result;
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 Check with query parameters:
284
+ * @example With cancellation:
243
285
  * ```typescript
244
- * const exists = await client.head('/api/users', { id: 123 });
245
- * if (exists.status === 404) {
246
- * console.log('User not found');
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(url, {
328
- method: "POST",
329
- headers: requestHeaders,
330
- ...body !== void 0 ? { body: JSON.stringify(body) } : {}
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(url, {
348
- method: "PUT",
349
- headers: requestHeaders,
350
- ...body !== void 0 ? { body: JSON.stringify(body) } : {}
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(url, {
368
- method: "PATCH",
369
- headers: requestHeaders,
370
- ...body !== void 0 ? { body: JSON.stringify(body) } : {}
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 useAuthentication(client, options) {
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 useAuthorization(client, options = {}) {
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 useCache(client, options = {}) {
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 useCSRF(client, options = {}) {
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 useLogging(client, options = {}) {
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 useRateLimit(client, options = {}) {
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 useRetry(client, options = {}) {
1111
+ function addRetry(client, options = {}) {
1042
1112
  return client.use(createRetryMiddleware(options));
1043
1113
  }
1044
1114
 
1045
1115
  // src/middleware/index.ts
1046
- function useProductionStack(client, config = {}) {
1116
+ function addProductionStack(client, config = {}) {
1047
1117
  let enhanced = client;
1048
1118
  if (config.auth) {
1049
- enhanced = useAuthentication(enhanced, config.auth);
1119
+ enhanced = addAuthentication(enhanced, config.auth);
1050
1120
  }
1051
1121
  if (config.cache !== void 0) {
1052
- enhanced = useCache(enhanced, config.cache);
1122
+ enhanced = addCache(enhanced, config.cache);
1053
1123
  }
1054
1124
  if (config.retry !== void 0) {
1055
- enhanced = useRetry(enhanced, config.retry);
1125
+ enhanced = addRetry(enhanced, config.retry);
1056
1126
  }
1057
1127
  if (config.rateLimit !== void 0) {
1058
- enhanced = useRateLimit(enhanced, config.rateLimit);
1128
+ enhanced = addRateLimit(enhanced, config.rateLimit);
1059
1129
  }
1060
1130
  if (config.logging !== void 0) {
1061
- enhanced = useLogging(enhanced, config.logging);
1131
+ enhanced = addLogging(enhanced, config.logging);
1062
1132
  }
1063
1133
  return enhanced;
1064
1134
  }
1065
- function useDevelopmentStack(client, config = {}) {
1135
+ function addDevelopmentStack(client, config = {}) {
1066
1136
  let enhanced = client;
1067
1137
  if (config.auth) {
1068
- enhanced = useAuthentication(enhanced, config.auth);
1138
+ enhanced = addAuthentication(enhanced, config.auth);
1069
1139
  }
1070
- enhanced = useRetry(enhanced, {
1140
+ enhanced = addRetry(enhanced, {
1071
1141
  maxRetries: 1,
1072
1142
  delay: 100
1073
1143
  });
1074
- enhanced = useLogging(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 useBasicStack(client, config) {
1084
- return useRetry(useAuthentication(client, config.auth), { maxRetries: 2 });
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 = useProductionStack(
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