fetch-request-browser 1.0.9 → 1.0.11

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/README.md CHANGED
@@ -12,7 +12,7 @@ If you are working on a node-based environment, make use of [fetch-request-node]
12
12
 
13
13
  Install the package:
14
14
  ```bash
15
- npm install -S fetch-request-browser
15
+ npm i -S fetch-request-browser
16
16
  ```
17
17
 
18
18
  ### Examples
@@ -34,6 +34,7 @@ await sendGET<IHTTPBinResponse>(
34
34
  );
35
35
  // {
36
36
  // code: 200,
37
+ // statusText: 'OK',
37
38
  // headers: Headers {
38
39
  // date: 'Fri, 06 Dec 2024 14:14:12 GMT',
39
40
  // 'content-type': 'application/json',
@@ -81,6 +82,7 @@ await sendPOST<IHTTPBinResponse>(
81
82
  );
82
83
  // {
83
84
  // code: 200,
85
+ // statusText: 'OK',
84
86
  // headers: Headers {
85
87
  // date: 'Fri, 06 Dec 2024 12:57:25 GMT',
86
88
  // 'content-type': 'application/json',
@@ -123,6 +125,7 @@ await sendPOST<IHTTPBinResponse>(
123
125
 
124
126
  <details>
125
127
  <summary><code>send</code></summary>
128
+ <br/>
126
129
 
127
130
  Builds and sends an HTTP Request based on the provided input and options.
128
131
  ```typescript
@@ -133,6 +136,7 @@ await sendPOST<IHTTPBinResponse>(
133
136
  );
134
137
  // {
135
138
  // code: 200,
139
+ // statusText: 'OK',
136
140
  // headers: Headers {
137
141
  // date: 'Fri, 06 Dec 2024 13:05:20 GMT',
138
142
  // 'content-type': 'application/json',
@@ -158,16 +162,19 @@ await sendPOST<IHTTPBinResponse>(
158
162
  // }
159
163
  // }
160
164
  ```
165
+ <br/>
161
166
  </details>
162
167
 
163
168
  <details>
164
169
  <summary><code>sendGET</code></summary>
170
+ <br/>
165
171
 
166
172
  Builds and sends a `GET` HTTP Request based on the provided input and options.
167
173
  ```typescript
168
174
  await sendGET<IHTTPBinResponse>('https://httpbin.org/get?foo=hey&bar=123');
169
175
  // {
170
176
  // code: 200,
177
+ // statusText: 'OK',
171
178
  // headers: Headers {
172
179
  // date: 'Fri, 06 Dec 2024 13:05:20 GMT',
173
180
  // 'content-type': 'application/json',
@@ -193,10 +200,12 @@ await sendPOST<IHTTPBinResponse>(
193
200
  // }
194
201
  // }
195
202
  ```
203
+ <br/>
196
204
  </details>
197
205
 
198
206
  <details>
199
207
  <summary><code>sendPOST</code></summary>
208
+ <br/>
200
209
 
201
210
  Builds and sends a `POST` HTTP Request based on the provided input and options.
202
211
  ```typescript
@@ -213,6 +222,7 @@ await sendPOST<IHTTPBinResponse>(
213
222
  );
214
223
  // {
215
224
  // code: 200,
225
+ // statusText: 'OK',
216
226
  // headers: Headers {
217
227
  // date: 'Fri, 06 Dec 2024 13:13:18 GMT',
218
228
  // 'content-type': 'application/json',
@@ -244,10 +254,12 @@ await sendPOST<IHTTPBinResponse>(
244
254
  // }
245
255
  // }
246
256
  ```
257
+ <br/>
247
258
  </details>
248
259
 
249
260
  <details>
250
261
  <summary><code>sendPUT</code></summary>
262
+ <br/>
251
263
 
252
264
  Builds and sends a `PUT` HTTP Request based on the provided input and options.
253
265
  ```typescript
@@ -264,6 +276,7 @@ await sendPOST<IHTTPBinResponse>(
264
276
  );
265
277
  // {
266
278
  // code: 200,
279
+ // statusText: 'OK',
267
280
  // headers: Headers {
268
281
  // date: 'Fri, 06 Dec 2024 13:19:07 GMT',
269
282
  // 'content-type': 'application/json',
@@ -295,10 +308,12 @@ await sendPOST<IHTTPBinResponse>(
295
308
  // }
296
309
  // }
297
310
  ```
311
+ <br/>
298
312
  </details>
299
313
 
300
314
  <details>
301
315
  <summary><code>sendPATCH</code></summary>
316
+ <br/>
302
317
 
303
318
  Builds and sends a `PATCH` HTTP Request based on the provided input and options.
304
319
  ```typescript
@@ -315,6 +330,7 @@ await sendPOST<IHTTPBinResponse>(
315
330
  );
316
331
  // {
317
332
  // code: 200,
333
+ // statusText: 'OK',
318
334
  // headers: Headers {
319
335
  // date: 'Fri, 06 Dec 2024 13:22:54 GMT',
320
336
  // 'content-type': 'application/json',
@@ -346,16 +362,19 @@ await sendPOST<IHTTPBinResponse>(
346
362
  // }
347
363
  // }
348
364
  ```
365
+ <br/>
349
366
  </details>
350
367
 
351
368
  <details>
352
369
  <summary><code>sendDELETE</code></summary>
370
+ <br/>
353
371
 
354
372
  Builds and sends a `DELETE` HTTP Request based on the provided input and options.
355
373
  ```typescript
356
374
  await sendDELETE<IHTTPBinResponse>('https://httpbin.org/delete?id=1');
357
375
  // {
358
376
  // code: 200,
377
+ // statusText: 'OK',
359
378
  // headers: Headers {
360
379
  // date: 'Fri, 06 Dec 2024 13:25:41 GMT',
361
380
  // 'content-type': 'application/json',
@@ -386,6 +405,7 @@ await sendPOST<IHTTPBinResponse>(
386
405
  // }
387
406
  // }
388
407
  ```
408
+ <br/>
389
409
  </details>
390
410
 
391
411
 
@@ -399,24 +419,29 @@ await sendPOST<IHTTPBinResponse>(
399
419
 
400
420
  <details>
401
421
  <summary><code>IRequestInput</code></summary>
422
+ <br/>
402
423
 
403
424
  The URL of the request's target.
404
425
  ```typescript
405
426
  type IRequestInput = string | URL;
406
427
  ```
428
+ <br/>
407
429
  </details>
408
430
 
409
431
  <details>
410
432
  <summary><code>IRequestMethod</code></summary>
433
+ <br/>
411
434
 
412
435
  The HTTP Methods supported by this library. To make use of a different one, pass the method name directly in the request options.
413
436
  ```typescript
414
437
  type IRequestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
415
438
  ```
439
+ <br/>
416
440
  </details>
417
441
 
418
442
  <details>
419
443
  <summary><code>RequestInit</code></summary>
444
+ <br/>
420
445
 
421
446
  The [`RequestInit`](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit) dictionary of the Fetch API represents the set of options that can be used to configure a fetch request.
422
447
  ```typescript
@@ -450,10 +475,12 @@ await sendPOST<IHTTPBinResponse>(
450
475
  window?: null;
451
476
  }
452
477
  ```
478
+ <br/>
453
479
  </details>
454
480
 
455
481
  <details>
456
482
  <summary><code>IRequestOptions</code></summary>
483
+ <br/>
457
484
 
458
485
  The options that can be applied when sending a Fetch Request.
459
486
  IMPORTANT: the reason RequestInit is extended is because in the original type, the body property does not accept plain objects. Even though this makes sense, utilities so the Request's body is always going to have a valid type.
@@ -467,19 +494,23 @@ await sendPOST<IHTTPBinResponse>(
467
494
  method: IRequestMethod;
468
495
  }
469
496
  ```
497
+ <br/>
470
498
  </details>
471
499
 
472
500
  <details>
473
501
  <summary><code>IResponseDataType</code></summary>
502
+ <br/>
474
503
 
475
504
  The type of data that will be extracted from the HTTP Response body.
476
505
  ```typescript
477
506
  type IResponseDataType = 'arrayBuffer' | 'blob' | 'formData' | 'json' | 'text';
478
507
  ```
508
+ <br/>
479
509
  </details>
480
510
 
481
511
  <details>
482
512
  <summary><code>IOptions</code></summary>
513
+ <br/>
483
514
 
484
515
  The options object that can be passed and used for any request.
485
516
  ```typescript
@@ -507,10 +538,12 @@ await sendPOST<IHTTPBinResponse>(
507
538
  skipStatusCodeValidation: boolean;
508
539
  }
509
540
  ```
541
+ <br/>
510
542
  </details>
511
543
 
512
544
  <details>
513
545
  <summary><code>IRequestResponse<T></code></summary>
546
+ <br/>
514
547
 
515
548
  The object containing the result of the Request.
516
549
  ```typescript
@@ -518,6 +551,9 @@ await sendPOST<IHTTPBinResponse>(
518
551
  // the HTTP status code extracted from the Response
519
552
  code: number;
520
553
 
554
+ // the message associated with the status code
555
+ statusText: string;
556
+
521
557
  // the Response's Headers. Useful as some service providers attach important info in the headers
522
558
  headers: Headers;
523
559
 
@@ -525,6 +561,7 @@ await sendPOST<IHTTPBinResponse>(
525
561
  data: T;
526
562
  }
527
563
  ```
564
+ <br/>
528
565
  </details>
529
566
 
530
567
 
@@ -560,29 +597,4 @@ npm run test:integration
560
597
 
561
598
  ## License
562
599
 
563
- [MIT](https://choosealicense.com/licenses/mit/)
564
-
565
-
566
-
567
-
568
-
569
- <br />
570
-
571
- ## Deployment
572
-
573
- Install dependencies:
574
- ```bash
575
- npm install
576
- ```
577
-
578
-
579
- Build the library:
580
- ```bash
581
- npm start
582
- ```
583
-
584
-
585
- Publish to `npm`:
586
- ```bash
587
- npm publish
588
- ```
600
+ [MIT](https://choosealicense.com/licenses/mit/)
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{extractMessage}from"error-message-utils";import{isArrayValid,delay}from"web-utils-kit";import{buildOptions,buildRequest,extractResponseData}from"./utils/utils.js";import{validateResponse}from"./validations/validations.js";const __executeSend=async(e,s)=>{const t=buildOptions(s),n=buildRequest(e,t.requestOptions),r=await fetch(n);return validateResponse(n,r,t),r.redirected&&console.warn(`The request sent to '${n.url}' was redirected. Please update the implementation to avoid future redirections.`),{code:r.status,headers:r.headers,data:await extractResponseData(r,t.responseDataType)}},send=async(e,s,t)=>{try{return await __executeSend(e,s)}catch(n){if(extractMessage(n).includes("429")||!isArrayValid(t))throw n;return await delay(t[0]),send(e,s,t.slice(1))}},sendGET=(e,s,t)=>send(e,{...s,requestOptions:{...s?.requestOptions,method:"GET"}},t),sendPOST=(e,s,t)=>send(e,{...s,requestOptions:{...s?.requestOptions,method:"POST"}},t),sendPUT=(e,s,t)=>send(e,{...s,requestOptions:{...s?.requestOptions,method:"PUT"}},t),sendPATCH=(e,s,t)=>send(e,{...s,requestOptions:{...s?.requestOptions,method:"PATCH"}},t),sendDELETE=(e,s,t)=>send(e,{...s,requestOptions:{...s?.requestOptions,method:"DELETE"}},t);export{send,sendGET,sendPOST,sendPUT,sendPATCH,sendDELETE};
1
+ import{extractMessage}from"error-message-utils";import{isArrayValid,delay}from"web-utils-kit";import{buildOptions,buildRequest,extractErrorMessageFromResponseBody,extractResponseData}from"./utils/utils.js";import{validateResponse}from"./validations/validations.js";const __executeSend=async(e,t)=>{const s=buildOptions(t),r=buildRequest(e,s.requestOptions),a=await fetch(r);try{return validateResponse(r,a,s),a.redirected&&console.warn(`The request sent to '${r.url}' was redirected. Please update the implementation to avoid future redirections.`),{code:a.status,statusText:a.statusText,headers:a.headers,data:await extractResponseData(a,s.responseDataType)}}catch(e){const t=await extractErrorMessageFromResponseBody(a);if(t)throw new Error(extractMessage(e),{cause:t});throw e}},send=async(e,t,s)=>{try{return await __executeSend(e,t)}catch(r){if(extractMessage(r).includes("429")||!isArrayValid(s))throw r;return await delay(s[0]),send(e,t,s.slice(1))}},sendGET=(e,t,s)=>send(e,{...t,requestOptions:{...t?.requestOptions,method:"GET"}},s),sendPOST=(e,t,s)=>send(e,{...t,requestOptions:{...t?.requestOptions,method:"POST"}},s),sendPUT=(e,t,s)=>send(e,{...t,requestOptions:{...t?.requestOptions,method:"PUT"}},s),sendPATCH=(e,t,s)=>send(e,{...t,requestOptions:{...t?.requestOptions,method:"PATCH"}},s),sendDELETE=(e,t,s)=>send(e,{...t,requestOptions:{...t?.requestOptions,method:"DELETE"}},s);export{send,sendGET,sendPOST,sendPUT,sendPATCH,sendDELETE};
@@ -2,4 +2,4 @@ type IErrorCode = 'INVALID_REQUEST_URL' | 'INVALID_REQUEST_HEADERS' | 'INVALID_R
2
2
  declare const ERRORS: {
3
3
  [key in IErrorCode]: IErrorCode;
4
4
  };
5
- export { ERRORS, };
5
+ export { ERRORS };
@@ -54,6 +54,7 @@ interface IOptions {
54
54
  */
55
55
  interface IRequestResponse<T> {
56
56
  code: number;
57
+ statusText: string;
57
58
  headers: Headers;
58
59
  data: T;
59
60
  }
@@ -19,10 +19,18 @@ declare const buildRequest: (input: IRequestInput, options?: Partial<IRequestOpt
19
19
  * - INVALID_RESPONSE_DTYPE: if the data type is not supported by the Response Instance
20
20
  */
21
21
  declare const extractResponseData: <T>(res: Response, dType: IResponseDataType) => Promise<T>;
22
+ /**
23
+ * Attempts to extract the error message from the response object. If it fails, it returns
24
+ * undefined.
25
+ * @param res
26
+ * @returns Promise<string | undefined>
27
+ * @stable
28
+ */
29
+ declare const extractErrorMessageFromResponseBody: (res: Response) => Promise<string | undefined>;
22
30
  /**
23
31
  * Builds the main options object based on given args (if any).
24
32
  * @param options
25
33
  * @returns IOptions
26
34
  */
27
35
  declare const buildOptions: (options?: Partial<IOptions>) => IOptions;
28
- export { buildRequest, extractResponseData, buildOptions, };
36
+ export { buildRequest, extractResponseData, extractErrorMessageFromResponseBody, buildOptions, };
@@ -1 +1 @@
1
- import{encodeError,isEncodedError}from"error-message-utils";import{isArrayValid,isObjectValid}from"web-utils-kit";import{ERRORS}from"../shared/errors.js";const __buildRequestInput=e=>{if(e instanceof URL)return e;try{return new URL(e)}catch(e){throw new Error(encodeError(e,ERRORS.INVALID_REQUEST_URL))}},__buildRequestHeaders=(e,r)=>{let t;if(e&&"object"==typeof e)try{t=new Headers(e)}catch(e){throw new Error(encodeError(e,ERRORS.INVALID_REQUEST_HEADERS))}else t=e instanceof Headers?e:"GET"===r?new Headers({Accept:"application/json"}):new Headers({Accept:"application/json","Content-Type":"application/json"});return t.has("Accept")||t.append("Accept","application/json"),t.has("Content-Type")||"GET"===r||t.append("Content-Type","application/json"),t},__buildRequestBody=e=>e?isObjectValid(e,!0)||isArrayValid(e,!0)?JSON.stringify(e):e:null,__buildRequestOptions=(e={})=>{const r=e.method??"GET";return{method:r,mode:e.mode??"cors",cache:e.cache??"default",credentials:e.credentials??"same-origin",headers:__buildRequestHeaders(e.headers,r),priority:e.priority??"auto",redirect:e.redirect??"follow",referrer:e.referrer??"about:client",referrerPolicy:e.referrerPolicy??"no-referrer-when-downgrade",signal:e.signal,integrity:e.integrity||"",keepalive:e.keepalive??!1,body:"GET"===r?null:__buildRequestBody(e.body)}},buildRequest=(e,r)=>{try{return new Request(__buildRequestInput(e),__buildRequestOptions(r))}catch(e){if(isEncodedError(e))throw e;throw new Error(encodeError(e,ERRORS.INVALID_REQUEST_OPTIONS))}},extractResponseData=async(e,r)=>{switch(r){case"arrayBuffer":return e.arrayBuffer();case"blob":return e.blob();case"formData":return e.formData();case"json":return e.json();case"text":return e.text();default:throw new Error(encodeError(`The provided response data type '${r}' is invalid.`,ERRORS.INVALID_RESPONSE_DTYPE))}},buildOptions=(e={})=>({requestOptions:e.requestOptions,responseDataType:e.responseDataType??"json",acceptableStatusCodes:e.acceptableStatusCodes,acceptableStatusCodesRange:e.acceptableStatusCodesRange??{min:200,max:299},skipStatusCodeValidation:e.skipStatusCodeValidation??!1});export{buildRequest,extractResponseData,buildOptions};
1
+ import{encodeError,extractMessage,isDefaultErrorMessage,isEncodedError}from"error-message-utils";import{isArrayValid,isObjectValid}from"web-utils-kit";import{ERRORS}from"../shared/errors.js";const __buildRequestInput=e=>{if(e instanceof URL)return e;try{return new URL(e)}catch(e){throw new Error(encodeError(e,ERRORS.INVALID_REQUEST_URL))}},__buildRequestHeaders=(e,r)=>{let t;if(e&&"object"==typeof e)try{t=new Headers(e)}catch(e){throw new Error(encodeError(e,ERRORS.INVALID_REQUEST_HEADERS))}else t=e instanceof Headers?e:"GET"===r?new Headers({Accept:"application/json"}):new Headers({Accept:"application/json","Content-Type":"application/json"});return t.has("Accept")||t.append("Accept","application/json"),t.has("Content-Type")||"GET"===r||t.append("Content-Type","application/json"),t},__buildRequestBody=e=>e?isObjectValid(e,!0)||isArrayValid(e,!0)?JSON.stringify(e):e:null,__buildRequestOptions=(e={})=>{const r=e.method??"GET";return{method:r,mode:e.mode??"cors",cache:e.cache??"default",credentials:e.credentials??"same-origin",headers:__buildRequestHeaders(e.headers,r),priority:e.priority??"auto",redirect:e.redirect??"follow",referrer:e.referrer??"about:client",referrerPolicy:e.referrerPolicy??"no-referrer-when-downgrade",signal:e.signal,integrity:e.integrity||"",keepalive:e.keepalive??!1,body:"GET"===r?null:__buildRequestBody(e.body)}},buildRequest=(e,r)=>{try{return new Request(__buildRequestInput(e),__buildRequestOptions(r))}catch(e){if(isEncodedError(e))throw e;throw new Error(encodeError(e,ERRORS.INVALID_REQUEST_OPTIONS))}},extractResponseData=async(e,r)=>{switch(r){case"arrayBuffer":return e.arrayBuffer();case"blob":return e.blob();case"formData":return e.formData();case"json":return e.json();case"text":return e.text();default:throw new Error(encodeError(`The provided response data type '${r}' is invalid.`,ERRORS.INVALID_RESPONSE_DTYPE))}},extractErrorMessageFromResponseBody=async e=>{try{const r=await e.json(),t=extractMessage(r);return isDefaultErrorMessage(t)?void 0:t}catch(e){return}},buildOptions=(e={})=>({requestOptions:e.requestOptions,responseDataType:e.responseDataType??"json",acceptableStatusCodes:e.acceptableStatusCodes,acceptableStatusCodesRange:e.acceptableStatusCodesRange??{min:200,max:299},skipStatusCodeValidation:e.skipStatusCodeValidation??!1});export{buildRequest,extractResponseData,extractErrorMessageFromResponseBody,buildOptions};
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "fetch-request-browser",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "The fetch-request-browser package makes working with external APIs simple and efficient. This intuitive wrapper leverages the power of the Fetch API, providing a clean and concise interface for your API interactions.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
8
8
  "scripts": {
9
- "start": "ts-lib-builder --tsconfig=tsconfig.build.json",
9
+ "build": "ts-lib-builder --tsconfig=tsconfig.build.json",
10
10
  "test": "echo \"Error: tests are executed with npm run test:(integration|unit)\" && exit 1",
11
11
  "test:integration": "vitest run --config vitest.test-integration.config.ts",
12
12
  "test:unit": "vitest run --config vitest.test-unit.config.ts",
@@ -33,16 +33,18 @@
33
33
  },
34
34
  "homepage": "https://github.com/jesusgraterol/fetch-request-browser#readme",
35
35
  "devDependencies": {
36
- "@types/node": "^20.17.17",
37
- "@typescript-eslint/eslint-plugin": "^7.18.0",
38
- "@typescript-eslint/parser": "^7.18.0",
39
- "eslint-config-airbnb-typescript": "^18.0.0",
40
- "ts-lib-builder": "^1.0.5",
41
- "typescript": "^5.7.3",
42
- "vitest": "^1.6.1"
36
+ "@types/node": "20.17.17",
37
+ "@typescript-eslint/eslint-plugin": "7.18.0",
38
+ "@typescript-eslint/parser": "7.18.0",
39
+ "eslint-config-airbnb-typescript": "18.0.0",
40
+ "eslint-config-prettier": "10.1.8",
41
+ "prettier": "3.6.2",
42
+ "ts-lib-builder": "1.0.7",
43
+ "typescript": "5.7.3",
44
+ "vitest": "3.2.4"
43
45
  },
44
46
  "dependencies": {
45
- "error-message-utils": "^1.1.2",
46
- "web-utils-kit": "^1.0.5"
47
+ "error-message-utils": "1.1.5",
48
+ "web-utils-kit": "1.0.6"
47
49
  }
48
50
  }