fetch-request-browser 1.0.11 → 1.0.12

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
@@ -582,6 +582,9 @@ await sendPOST<IHTTPBinResponse>(
582
582
  ## Running the Tests
583
583
 
584
584
  ```bash
585
+ # unit and integration tests
586
+ npm run test
587
+
585
588
  # unit tests
586
589
  npm run test:unit
587
590
 
package/dist/index.d.ts CHANGED
@@ -22,7 +22,7 @@ declare const send: <T>(input: IRequestInput, options?: Partial<IOptions>, retry
22
22
  * worth retrying as they could fail temporarily and prevent a view from loading.
23
23
  * @param input
24
24
  * @param options?
25
- * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying
25
+ * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying (Defaults to [3, 5])
26
26
  * @returns Promise<IRequestResponse>
27
27
  * @throws
28
28
  * - INVALID_REQUEST_URL: if the provided input URL cannot be parsed
@@ -38,7 +38,7 @@ declare const sendGET: <T>(input: IRequestInput, options?: Partial<IOptions>, re
38
38
  * Builds and sends a POST HTTP Request based on the provided input and options.
39
39
  * @param input
40
40
  * @param options?
41
- * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying
41
+ * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying. (Defaults to undefined)
42
42
  * @returns Promise<IRequestResponse>
43
43
  * @throws
44
44
  * - INVALID_REQUEST_URL: if the provided input URL cannot be parsed
@@ -54,7 +54,7 @@ declare const sendPOST: <T>(input: IRequestInput, options?: Partial<IOptions>, r
54
54
  * Builds and sends a PUT HTTP Request based on the provided input and options.
55
55
  * @param input
56
56
  * @param options?
57
- * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying
57
+ * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying. (Defaults to undefined)
58
58
  * @returns Promise<IRequestResponse>
59
59
  * @throws
60
60
  * - INVALID_REQUEST_URL: if the provided input URL cannot be parsed
@@ -70,7 +70,7 @@ declare const sendPUT: <T>(input: IRequestInput, options?: Partial<IOptions>, re
70
70
  * Builds and sends a PATCH HTTP Request based on the provided input and options.
71
71
  * @param input
72
72
  * @param options?
73
- * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying
73
+ * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying. (Defaults to undefined)
74
74
  * @returns Promise<IRequestResponse>
75
75
  * @throws
76
76
  * - INVALID_REQUEST_URL: if the provided input URL cannot be parsed
@@ -86,7 +86,7 @@ declare const sendPATCH: <T>(input: IRequestInput, options?: Partial<IOptions>,
86
86
  * Builds and sends a DELETE HTTP Request based on the provided input and options.
87
87
  * @param input
88
88
  * @param options?
89
- * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying
89
+ * @param retryDelaySchedule? - list of seconds that will be applied to the delay before retrying. (Defaults to undefined)
90
90
  * @returns Promise<IRequestResponse>
91
91
  * @throws
92
92
  * - INVALID_REQUEST_URL: if the provided input URL cannot be parsed
package/dist/index.js CHANGED
@@ -1 +1 @@
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};
1
+ import{extractMessage}from"error-message-utils";import{isArrayValid,delay}from"web-utils-kit";import{buildOptions,buildRequest,isRequestRetryable,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(!isArrayValid(s)||!isRequestRetryable(r))throw r;return await delay(s[0]),send(e,t,s.slice(1))}},sendGET=(e,t,s=[3,5])=>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};
@@ -10,6 +10,17 @@ import { IRequestInput, IRequestOptions, IResponseDataType, IOptions } from '../
10
10
  * - INVALID_REQUEST_OPTIONS: if the Request Instance cannot be instantiated due to the passed opts
11
11
  */
12
12
  declare const buildRequest: (input: IRequestInput, options?: Partial<IRequestOptions>) => Request;
13
+ /**
14
+ * Extracts the error message from the error object and checks if it is retryable based on the
15
+ * status code included in the message. The list of non-retryable status codes includes:
16
+ * - 401: Unauthorized
17
+ * - 403: Forbidden
18
+ * - 404: Not Found
19
+ * - 429: Too Many Requests
20
+ * @param error The error object thrown by the fetch request or the validation functions
21
+ * @returns boolean indicating whether the request is retryable or not
22
+ */
23
+ declare const isRequestRetryable: (error: unknown) => boolean;
13
24
  /**
14
25
  * Extracts the data from the Response object based on the provided data type.
15
26
  * @param res
@@ -33,4 +44,4 @@ declare const extractErrorMessageFromResponseBody: (res: Response) => Promise<st
33
44
  * @returns IOptions
34
45
  */
35
46
  declare const buildOptions: (options?: Partial<IOptions>) => IOptions;
36
- export { buildRequest, extractResponseData, extractErrorMessageFromResponseBody, buildOptions, };
47
+ export { buildRequest, isRequestRetryable, extractResponseData, extractErrorMessageFromResponseBody, buildOptions, };
@@ -1 +1 @@
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};
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))}},isRequestRetryable=e=>{const r=extractMessage(e);return!(r.includes("401")||r.includes("403")||r.includes("404")||r.includes("429"))},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,isRequestRetryable,extractResponseData,extractErrorMessageFromResponseBody,buildOptions};
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "fetch-request-browser",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
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
9
  "build": "ts-lib-builder --tsconfig=tsconfig.build.json",
10
- "test": "echo \"Error: tests are executed with npm run test:(integration|unit)\" && exit 1",
10
+ "test": "npm run test:unit && npm run test:integration",
11
11
  "test:integration": "vitest run --config vitest.test-integration.config.ts",
12
12
  "test:unit": "vitest run --config vitest.test-unit.config.ts",
13
13
  "watch-test:integration": "vitest --config vitest.test-integration.config.ts",
@@ -39,12 +39,12 @@
39
39
  "eslint-config-airbnb-typescript": "18.0.0",
40
40
  "eslint-config-prettier": "10.1.8",
41
41
  "prettier": "3.6.2",
42
- "ts-lib-builder": "1.0.7",
42
+ "ts-lib-builder": "1.0.8",
43
43
  "typescript": "5.7.3",
44
44
  "vitest": "3.2.4"
45
45
  },
46
46
  "dependencies": {
47
- "error-message-utils": "1.1.5",
48
- "web-utils-kit": "1.0.6"
47
+ "error-message-utils": "1.1.6",
48
+ "web-utils-kit": "1.0.16"
49
49
  }
50
50
  }