@alwatr/fetch 10.1.0 → 10.1.1

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/dev/main.js CHANGED
@@ -1,5 +1,5 @@
1
- /* 📦 @alwatr/fetch v10.1.0 */
2
- import{HttpStatusCodes as l}from"@alwatr/http-primer";function g(t){switch(t){case l.Error_Client_400_Bad_Request:return"bad_request";case l.Error_Client_401_Unauthorized:return"unauthorized";case l.Error_Client_403_Forbidden:return"forbidden";case l.Error_Client_404_Not_Found:return"not_found";case l.Error_Client_408_Request_Timeout:return"request_timeout";case l.Error_Client_409_Conflict:return"conflict";case l.Error_Client_413_Payload_Too_Large:return"payload_too_large";case l.Error_Client_422_Unprocessable_Entity:return"unprocessable_content";case l.Error_Client_429_Too_Many_Requests:return"rate_limited";default:if(t>=500&&t<600)return"server_error";return"http_error"}}class s extends Error{response;data;reason;get status(){return this.response?.status}ok=!1;constructor(t,r,n,e){super(r);this.name="FetchError",this.reason=t,this.response=n,this.data=e}}import{MimeTypes as k}from"@alwatr/http-primer";import{createLogger as F}from"@alwatr/logger";import{getGlobalThis as M}from"@alwatr/global-this";import{parseDuration as E}from"@alwatr/parse-duration";var c=F("@alwatr/fetch"),H=M(),h={method:"GET",timeout:8000,retry:3,retryDelay:1000,removeDuplicate:"never",cacheStrategy:"network_only",cacheStorageName:"fetch_cache"};function C(t,r={}){if(t==null)return r;if(typeof Headers<"u"&&t instanceof Headers)return t.forEach((n,e)=>{r[e.toLowerCase()]=n}),r;if(Array.isArray(t)){for(let[n,e]of t)if(typeof n==="string"&&typeof e==="string")r[n.toLowerCase()]=e;return r}if(typeof t==="object")for(let n of Object.keys(t)){let e=t[n];if(e!=null)r[n.toLowerCase()]=String(e)}return r}function T(t){let r=[];for(let n of Object.keys(t)){let e=t[n];if(e===void 0||e===null)continue;if(Array.isArray(e)){for(let o of e)if(o!==void 0&&o!==null)r.push(`${encodeURIComponent(n)}=${encodeURIComponent(String(o))}`)}else r.push(`${encodeURIComponent(n)}=${encodeURIComponent(String(e))}`)}return r.join("&")}function x(t,r){if(r==null)return t;let n=T(r);if(n.length===0)return t;let e=t,o="",a=t.indexOf("#");if(a!==-1)e=t.slice(0,a),o=t.slice(a);let i=e.includes("?")?"&":"?";return`${e}${i}${n}${o}`}function w(t,r={}){c.logMethod?.("processOptions_");let n=x(t,r.queryParams),e={...h,...r,headers:C(r.headers),url:n,method:r.method?.toUpperCase()??h.method,timeout:E(r.timeout??h.timeout),retryDelay:E(r.retryDelay??h.retryDelay),retry:typeof r.retry==="number"&&Number.isFinite(r.retry)?Math.max(1,Math.floor(r.retry)):h.retry};if(e.window??=null,e.cacheStrategy!=="network_only"&&(typeof caches>"u"||e.method!=="GET"&&e.method!=="HEAD"))c.incident?.("processOptions_","fetch_cache_strategy_unsupported",{method:e.method,cacheStrategy:e.cacheStrategy,hasCaches:typeof caches<"u"}),e.cacheStrategy="network_only";if(e.removeDuplicate==="auto")e.removeDuplicate=typeof caches<"u"?"until_load":"always";if(r.bodyJson!==void 0)e.body=JSON.stringify(r.bodyJson),e.headers["content-type"]=k.JSON;if(r.bearerToken!==void 0)e.headers.authorization=`Bearer ${r.bearerToken}`;else if(r.alwatrAuth!==void 0)e.headers.authorization=`Alwatr ${r.alwatrAuth.userId}:${r.alwatrAuth.userToken}`;return e}import{delay as D}from"@alwatr/delay";import{getGlobalThis as I}from"@alwatr/global-this";import{HttpStatusCodes as m}from"@alwatr/http-primer";import{getGlobalThis as v}from"@alwatr/global-this";var b=v();function y(t){let r=t.signal;if(r?.aborted)return c.incident?.("handleTimeout_","already_aborted",{reason:r.reason}),Promise.reject(new s("aborted","The operation was aborted"));if(t.timeout===0)return b.fetch(t.url,t);return c.logMethod?.("handleTimeout_"),new Promise((n,e)=>{let o=typeof AbortController==="function"?new AbortController:null,a;if(o!==null){if(t.signal=o.signal,r!=null)a=()=>{o.abort(r.reason)},r.addEventListener("abort",a,{once:!0})}let i=!1,p=setTimeout(()=>{i=!0,o?.abort("fetch_timeout"),e(new s("timeout","fetch_timeout"))},t.timeout);b.fetch(t.url,t).then((f)=>{if(!i)n(f)}).catch((f)=>{if(i)return;if(r?.aborted||f instanceof Error&&f.name==="AbortError")e(new s("aborted","The operation was aborted"));else e(f)}).finally(()=>{if(clearTimeout(p),t.signal=r,r!=null&&a!==void 0)r.removeEventListener("abort",a)})})}var O=I();function P(t){return t>=m.Error_Server_500_Internal_Server_Error||t===m.Error_Client_408_Request_Timeout||t===m.Error_Client_429_Too_Many_Requests}function V(t){let r=t?.headers?.get("retry-after");if(!r)return;let n=Number(r);if(!isNaN(n)&&n>0)return n*1000;let e=Date.parse(r);if(!isNaN(e)){let o=e-Date.now();return o>0?o:0}return}async function d(t){if(t.retry<=1)return y(t);c.logMethod?.("handleRetryPattern_"),t.retry--;let r;try{if(r=await y(t),r.ok||!P(r.status))return r}catch(e){if(c.accident("fetch","fetch_failed_retry",e),t.signal?.aborted||e instanceof s&&e.reason==="aborted")throw e;if(O.navigator?.onLine===!1)throw c.accident("handleRetryPattern_","offline","Skip retry because offline"),e;return await D.by(t.retryDelay),d(t)}if(c.accident("fetch","fetch_failed_retry",{status:r.status}),O.navigator?.onLine===!1)return c.accident("handleRetryPattern_","offline","Skip retry because offline"),r;let n=V(r)??t.retryDelay;return await D.by(n),d(t)}var _=new Map;function A(t){let r=typeof t.body==="string"?t.body:"",n=t.headers.authorization??"";return`${t.method} ${t.url} [auth:${n}] [body:${r}]`}async function u(t){if(t.removeDuplicate==="never")return d(t);c.logMethod?.("handleRemoveDuplicate_");let r=A(t),n=_.get(r);if(n==null)n=d(t),_.set(r,n);try{let e=await n;if(!e.ok||t.removeDuplicate==="until_load")_.delete(r);return e.clone()}catch(e){throw _.delete(r),e}}import{delay as J}from"@alwatr/delay";async function R(t){if(t.cacheStrategy==="network_only")return u(t);c.logMethod?.("handleCacheStrategy_");let r;try{r=await caches.open(t.cacheStorageName)}catch(e){return c.accident("handleCacheStrategy_","cache_open_failed",{err:e}),t.cacheStrategy="network_only",u(t)}let n=new Request(t.url,t);switch(t.cacheStrategy){case"cache_first":{try{let o=await r.match(n);if(o!=null)return o}catch(o){c.accident("handleCacheStrategy_","cache_match_failed",{err:o})}let e=await u(t);if(e.ok)try{await r.put(n,e.clone())}catch{}return e}case"cache_only":{let e;try{e=await r.match(n)}catch(o){c.accident("handleCacheStrategy_","cache_only_match_failed",{err:o})}if(e==null)throw new s("cache_not_found","Resource not found in cache");return e}case"network_first":try{let e=await u(t);if(e.ok)try{await r.put(n,e.clone())}catch{}return e}catch(e){try{let o=await r.match(n);if(o!=null)return o}catch{}throw e}case"update_cache":{let e=await u(t);if(e.ok)try{await r.put(n,e.clone())}catch{}return e}case"stale_while_revalidate":{let e;try{e=await r.match(n)}catch{}let o=u(t).then(async(a)=>{if(a.ok){try{await r.put(n,a.clone())}catch{}if(typeof t.revalidateCallback==="function"){let i=t.revalidateCallback,p=a.clone();await J.nextMacrotask();try{await i(p)}catch(f){c.accident("handleCacheStrategy_","revalidate_callback_failed",{err:f})}}}return a});return e??o}default:return u(t)}}async function S(t,r={}){let n=w(t,r);c.logMethodArgs?.("fetch",n);try{let e=await R(n);if(!e.ok){let o=g(e.status);throw new s(o,`HTTP error! status: ${e.status} ${e.statusText}`,e)}return[e,null]}catch(e){let o;if(e instanceof s){if(o=e,o.response!==void 0&&o.data===void 0){let a=await o.response.text().catch(()=>"");if(a.trim().length>0)try{o.data=JSON.parse(a)}catch{o.data=a}}}else if(e instanceof Error)if(e.name==="AbortError")o=new s("aborted",e.message);else o=new s("network_error",e.message);else o=new s("unknown_error",String(e??"unknown_error"));return c.accident("fetch",o.reason,{error:o}),[null,o]}}async function N(t,r={}){c.logMethod?.("fetchJson");let[n,e]=await S(t,r);if(e)return[null,e];let o=await n.text().catch(()=>"");if(o.trim().length===0){let a=new s("json_parse_error","Response body is empty, cannot parse JSON",n,o);return c.accident("fetchJson",a.reason,{error:a}),[null,a]}try{let a=JSON.parse(o);if(r.requireJsonResponseWithOkTrue&&(typeof a!=="object"||a===null||a.ok!==!0)){let i=new s("json_response_error",'Response JSON "ok" property is not true',n,a);return c.accident("fetchJson",i.reason,{error:i}),[null,i]}return[a,null]}catch(a){let i=new s("json_parse_error",a instanceof Error?a.message:"Failed to parse JSON response",n,o);return c.accident("fetchJson",i.reason,{error:i}),[null,i]}}N.version=S.version="10.1.0";export{s as FetchError,S as fetch,N as fetchJson,g as httpStatusToErrorReason};
1
+ /* 📦 @alwatr/fetch v10.1.1 */
2
+ import{HttpStatusCodes as l}from"@alwatr/http-primer";function g(t){switch(t){case l.Error_Client_400_Bad_Request:return"bad_request";case l.Error_Client_401_Unauthorized:return"unauthorized";case l.Error_Client_403_Forbidden:return"forbidden";case l.Error_Client_404_Not_Found:return"not_found";case l.Error_Client_408_Request_Timeout:return"request_timeout";case l.Error_Client_409_Conflict:return"conflict";case l.Error_Client_413_Payload_Too_Large:return"payload_too_large";case l.Error_Client_422_Unprocessable_Entity:return"unprocessable_content";case l.Error_Client_429_Too_Many_Requests:return"rate_limited";default:if(t>=500&&t<600)return"server_error";return"http_error"}}class s extends Error{response;data;reason;get status(){return this.response?.status}ok=!1;constructor(t,r,n,e){super(r);this.name="FetchError",this.reason=t,this.response=n,this.data=e}}import{MimeTypes as k}from"@alwatr/http-primer";import{createLogger as F}from"@alwatr/logger";import{getGlobalThis as M}from"@alwatr/global-this";import{parseDuration as E}from"@alwatr/parse-duration";var c=F("@alwatr/fetch"),H=M(),f={method:"GET",timeout:8000,retry:3,retryDelay:1000,removeDuplicate:"never",cacheStrategy:"network_only",cacheStorageName:"fetch_cache"};function C(t,r={}){if(t==null)return r;if(typeof Headers<"u"&&t instanceof Headers)return t.forEach((n,e)=>{r[e.toLowerCase()]=n}),r;if(Array.isArray(t)){for(let[n,e]of t)if(typeof n==="string"&&typeof e==="string")r[n.toLowerCase()]=e;return r}if(typeof t==="object")for(let n of Object.keys(t)){let e=t[n];if(e!=null)r[n.toLowerCase()]=String(e)}return r}function T(t){let r=[];for(let n of Object.keys(t)){let e=t[n];if(e==null)continue;if(Array.isArray(e)){for(let o of e)if(o!=null)r.push(`${encodeURIComponent(n)}=${encodeURIComponent(String(o))}`)}else r.push(`${encodeURIComponent(n)}=${encodeURIComponent(String(e))}`)}return r.join("&")}function x(t,r){if(r==null)return t;let n=T(r);if(n.length===0)return t;let e=t,o="",a=t.indexOf("#");if(a!==-1)e=t.slice(0,a),o=t.slice(a);let i=e.includes("?")?"&":"?";return`${e}${i}${n}${o}`}function w(t,r={}){c.logMethod?.("processOptions_");let n=x(t,r.queryParams),e={...f,...r,headers:C(r.headers),url:n,method:r.method?.toUpperCase()??f.method,timeout:E(r.timeout??f.timeout),retryDelay:E(r.retryDelay??f.retryDelay),retry:typeof r.retry==="number"&&Number.isFinite(r.retry)?Math.max(1,Math.floor(r.retry)):f.retry};if(e.window??=null,e.cacheStrategy!=="network_only"&&(typeof caches>"u"||e.method!=="GET"&&e.method!=="HEAD"))c.incident?.("processOptions_","fetch_cache_strategy_unsupported",{method:e.method,cacheStrategy:e.cacheStrategy,hasCaches:typeof caches<"u"}),e.cacheStrategy="network_only";if(e.removeDuplicate==="auto")e.removeDuplicate=typeof caches<"u"?"until_load":"always";if(r.bodyJson!=null)e.body=JSON.stringify(r.bodyJson),e.headers["content-type"]=k.JSON;if(r.bearerToken!=null)e.headers.authorization=`Bearer ${r.bearerToken}`;else if(r.alwatrAuth!=null)e.headers.authorization=`Alwatr ${r.alwatrAuth.userId}:${r.alwatrAuth.userToken}`;return e}import{delay as D}from"@alwatr/delay";import{getGlobalThis as I}from"@alwatr/global-this";import{HttpStatusCodes as m}from"@alwatr/http-primer";import{getGlobalThis as v}from"@alwatr/global-this";var b=v();function y(t){let r=t.signal;if(r?.aborted)return c.incident?.("handleTimeout_","already_aborted",{reason:r.reason}),Promise.reject(new s("aborted","The operation was aborted"));if(t.timeout===0)return b.fetch(t.url,t);return c.logMethod?.("handleTimeout_"),new Promise((n,e)=>{let o=typeof AbortController==="function"?new AbortController:null,a;if(o!==null){if(t.signal=o.signal,r!=null)a=()=>{o.abort(r.reason)},r.addEventListener("abort",a,{once:!0})}let i=!1,p=setTimeout(()=>{i=!0,o?.abort("fetch_timeout"),e(new s("timeout","fetch_timeout"))},t.timeout);b.fetch(t.url,t).then((h)=>{if(!i)n(h)}).catch((h)=>{if(i)return;if(r?.aborted||h instanceof Error&&h.name==="AbortError")e(new s("aborted","The operation was aborted"));else e(h)}).finally(()=>{if(clearTimeout(p),t.signal=r,r!=null&&a!=null)r.removeEventListener("abort",a)})})}var O=I();function P(t){return t>=m.Error_Server_500_Internal_Server_Error||t===m.Error_Client_408_Request_Timeout||t===m.Error_Client_429_Too_Many_Requests}function V(t){let r=t?.headers?.get("retry-after");if(!r)return;let n=Number(r);if(!isNaN(n)&&n>0)return n*1000;let e=Date.parse(r);if(!isNaN(e)){let o=e-Date.now();return o>0?o:0}return}async function _(t){if(t.retry<=1)return y(t);c.logMethod?.("handleRetryPattern_"),t.retry--;let r;try{if(r=await y(t),r.ok||!P(r.status))return r}catch(e){if(c.accident("fetch","fetch_failed_retry",e),t.signal?.aborted||e instanceof s&&e.reason==="aborted")throw e;if(O.navigator?.onLine===!1)throw c.accident("handleRetryPattern_","offline","Skip retry because offline"),e;return await D.by(t.retryDelay),_(t)}if(c.accident("fetch","fetch_failed_retry",{status:r.status}),O.navigator?.onLine===!1)return c.accident("handleRetryPattern_","offline","Skip retry because offline"),r;let n=V(r)??t.retryDelay;return await D.by(n),_(t)}var d=new Map;function A(t){let r=typeof t.body==="string"?t.body:"",n=t.headers.authorization??"";return`${t.method} ${t.url} [auth:${n}] [body:${r}]`}async function u(t){if(t.removeDuplicate==="never")return _(t);c.logMethod?.("handleRemoveDuplicate_");let r=A(t),n=d.get(r);if(n==null)n=_(t),d.set(r,n);try{let e=await n;if(!e.ok||t.removeDuplicate==="until_load")d.delete(r);return e.clone()}catch(e){throw d.delete(r),e}}import{delay as J}from"@alwatr/delay";async function R(t){if(t.cacheStrategy==="network_only")return u(t);c.logMethod?.("handleCacheStrategy_");let r;try{r=await caches.open(t.cacheStorageName)}catch(e){return c.accident("handleCacheStrategy_","cache_open_failed",{err:e}),t.cacheStrategy="network_only",u(t)}let n=new Request(t.url,t);switch(t.cacheStrategy){case"cache_first":{try{let o=await r.match(n);if(o!=null)return o}catch(o){c.accident("handleCacheStrategy_","cache_match_failed",{err:o})}let e=await u(t);if(e.ok)try{await r.put(n,e.clone())}catch{}return e}case"cache_only":{let e;try{e=await r.match(n)}catch(o){c.accident("handleCacheStrategy_","cache_only_match_failed",{err:o})}if(e==null)throw new s("cache_not_found","Resource not found in cache");return e}case"network_first":try{let e=await u(t);if(e.ok)try{await r.put(n,e.clone())}catch{}return e}catch(e){try{let o=await r.match(n);if(o!=null)return o}catch{}throw e}case"update_cache":{let e=await u(t);if(e.ok)try{await r.put(n,e.clone())}catch{}return e}case"stale_while_revalidate":{let e;try{e=await r.match(n)}catch{}let o=u(t).then(async(a)=>{if(a.ok){try{await r.put(n,a.clone())}catch{}if(typeof t.revalidateCallback==="function"){let i=t.revalidateCallback,p=a.clone();await J.nextMacrotask();try{await i(p)}catch(h){c.accident("handleCacheStrategy_","revalidate_callback_failed",{err:h})}}}return a});return e??o}default:return u(t)}}async function S(t,r={}){let n=w(t,r);c.logMethodArgs?.("fetch",n);try{let e=await R(n);if(!e.ok){let o=g(e.status);throw new s(o,`HTTP error! status: ${e.status} ${e.statusText}`,e)}return[e,null]}catch(e){let o;if(e instanceof s){if(o=e,o.response!=null&&o.data==null){let a=await o.response.text().catch(()=>"");if(a.trim().length>0)try{o.data=JSON.parse(a)}catch{o.data=a}}}else if(e instanceof Error)if(e.name==="AbortError")o=new s("aborted",e.message);else o=new s("network_error",e.message);else o=new s("unknown_error",String(e??"unknown_error"));return c.accident("fetch",o.reason,{error:o}),[null,o]}}async function N(t,r={}){c.logMethod?.("fetchJson");let[n,e]=await S(t,r);if(e)return[null,e];let o=await n.text().catch(()=>"");if(o.trim().length===0){let a=new s("json_parse_error","Response body is empty, cannot parse JSON",n,o);return c.accident("fetchJson",a.reason,{error:a}),[null,a]}try{let a=JSON.parse(o);if(r.requireJsonResponseWithOkTrue&&(typeof a!=="object"||a===null||a.ok!==!0)){let i=new s("json_response_error",'Response JSON "ok" property is not true',n,a);return c.accident("fetchJson",i.reason,{error:i}),[null,i]}return[a,null]}catch(a){let i=new s("json_parse_error",a instanceof Error?a.message:"Failed to parse JSON response",n,o);return c.accident("fetchJson",i.reason,{error:i}),[null,i]}}N.version=S.version="10.1.1";export{s as FetchError,S as fetch,N as fetchJson,g as httpStatusToErrorReason};
3
3
 
4
- //# debugId=ED8587057A108B4C64756E2164756E21
4
+ //# debugId=0512877C39EC257264756E2164756E21
5
5
  //# sourceMappingURL=main.js.map
@@ -3,14 +3,14 @@
3
3
  "sources": ["../../src/error.ts", "../../src/options.ts", "../../src/retry.ts", "../../src/timeout.ts", "../../src/dedupe.ts", "../../src/cache.ts", "../../src/fetch.ts"],
4
4
  "sourcesContent": [
5
5
  "import {HttpStatusCodes} from '@alwatr/http-primer';\nimport type {FetchErrorReason} from './type.js';\n\n/**\n * Maps an HTTP status code to a semantic `FetchErrorReason`.\n *\n * @param status - The HTTP response status code.\n * @returns The mapped `FetchErrorReason`.\n *\n * @example\n * ```typescript\n * httpStatusToErrorReason(401); // 'unauthorized'\n * httpStatusToErrorReason(404); // 'not_found'\n * httpStatusToErrorReason(500); // 'server_error'\n * ```\n */\nexport function httpStatusToErrorReason(status: number): FetchErrorReason {\n switch (status) {\n case HttpStatusCodes.Error_Client_400_Bad_Request:\n return 'bad_request';\n case HttpStatusCodes.Error_Client_401_Unauthorized:\n return 'unauthorized';\n case HttpStatusCodes.Error_Client_403_Forbidden:\n return 'forbidden';\n case HttpStatusCodes.Error_Client_404_Not_Found:\n return 'not_found';\n case HttpStatusCodes.Error_Client_408_Request_Timeout:\n return 'request_timeout';\n case HttpStatusCodes.Error_Client_409_Conflict:\n return 'conflict';\n case HttpStatusCodes.Error_Client_413_Payload_Too_Large:\n return 'payload_too_large';\n case HttpStatusCodes.Error_Client_422_Unprocessable_Entity:\n return 'unprocessable_content';\n case HttpStatusCodes.Error_Client_429_Too_Many_Requests:\n return 'rate_limited';\n default:\n if (status >= 500 && status < 600) {\n return 'server_error';\n }\n return 'http_error';\n }\n}\n\n/**\n * Custom error class for fetch-related failures.\n *\n * This error is returned in the `[null, FetchError]` tuple when a request fails.\n * It enriches the standard `Error` with the `response`, the parsed `data` body,\n * and the specific `reason` enum.\n *\n * @example\n * ```typescript\n * const [response, error] = await fetch('/api/endpoint');\n * if (error) {\n * if (error.reason === 'unauthorized') {\n * redirectToLogin();\n * } else if (error.reason === 'server_error') {\n * showToast('Server unavailable, please try again later');\n * }\n * }\n * ```\n */\nexport class FetchError extends Error {\n /**\n * The original `Response` object, if one was received.\n */\n public response?: Response;\n\n /**\n * The parsed body of the error response, if available (JSON object, string, etc.).\n */\n public data?: unknown;\n\n /**\n * The specific semantic reason for the fetch failure.\n */\n public reason: FetchErrorReason;\n\n /**\n * Helper getter for the HTTP status code.\n */\n get status(): number | undefined {\n return this.response?.status;\n }\n\n /**\n * Always `false` to indicate error status.\n */\n readonly ok: false = false;\n\n constructor(reason: FetchErrorReason, message: string, response?: Response, data?: unknown) {\n super(message);\n this.name = 'FetchError';\n this.reason = reason;\n this.response = response;\n this.data = data;\n }\n}\n",
6
- "import {MimeTypes, type HttpMethod} from '@alwatr/http-primer';\nimport {createLogger} from '@alwatr/logger';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {parseDuration} from '@alwatr/parse-duration';\n\nimport type {AlwatrFetchOptions_, FetchOptions, InternalFetchOptions_, QueryParams} from './type.js';\n\nexport const logger_ = createLogger('@alwatr/fetch');\n\nexport const globalThis_ = getGlobalThis();\n\n/**\n * Immutable default options for all fetch requests.\n */\nexport const defaultFetchOptions: Readonly<AlwatrFetchOptions_> = {\n method: 'GET',\n timeout: 8_000,\n retry: 3,\n retryDelay: 1_000,\n removeDuplicate: 'never',\n cacheStrategy: 'network_only',\n cacheStorageName: 'fetch_cache',\n // headers: {}, // --- IGNORED ---\n};\n\n/**\n * Normalizes any standard `HeadersInit` into a fresh, isolated lowercase string record.\n *\n * @param headers - User-provided headers (plain object, Headers instance, or entries array).\n * @param baseHeaders - Optional base headers to merge with the user-provided headers.\n * @returns An isolated `Record<string, string>`.\n */\nexport function normalizeHeaders_(\n headers?: HeadersInit,\n baseHeaders: Record<string, string> = {},\n): Record<string, string> {\n if (headers == null) {\n return baseHeaders;\n }\n\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n headers.forEach((value, key) => {\n baseHeaders[key.toLowerCase()] = value;\n });\n return baseHeaders;\n }\n\n if (Array.isArray(headers)) {\n for (const [key, value] of headers) {\n if (typeof key === 'string' && typeof value === 'string') {\n baseHeaders[key.toLowerCase()] = value;\n }\n }\n return baseHeaders;\n }\n\n if (typeof headers === 'object') {\n for (const key of Object.keys(headers)) {\n const val = (headers as Record<string, unknown>)[key];\n if (val != null) {\n baseHeaders[key.toLowerCase()] = String(val);\n }\n }\n }\n\n return baseHeaders;\n}\n\n/**\n * Serializes query parameters into a query string.\n *\n * @param queryParams - Dictionary of query parameters.\n * @returns Serialized URL query string (without leading `?` or `&`).\n */\nexport function serializeQueryParams_(queryParams: QueryParams): string {\n const parts: string[] = [];\n\n for (const key of Object.keys(queryParams)) {\n const value = queryParams[key];\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== null) {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);\n }\n }\n } else {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n }\n }\n\n return parts.join('&');\n}\n\n/**\n * Appends query parameters to a URL, correctly respecting existing query parameters and hash anchors.\n *\n * @param url - The target URL.\n * @param queryParams - Query parameters to append.\n * @returns The resulting URL string.\n */\nexport function appendQueryParams_(url: string, queryParams?: QueryParams): string {\n if (queryParams == null) {\n return url;\n }\n\n const queryString = serializeQueryParams_(queryParams);\n if (queryString.length === 0) {\n return url;\n }\n\n // Handle hash fragment if present in URL\n let baseUrl = url;\n let hashPart = '';\n const hashIndex = url.indexOf('#');\n\n if (hashIndex !== -1) {\n baseUrl = url.slice(0, hashIndex);\n hashPart = url.slice(hashIndex);\n }\n\n const separator = baseUrl.includes('?') ? '&' : '?';\n return `${baseUrl}${separator}${queryString}${hashPart}`;\n}\n\n/**\n * Processes, sanitizes, and normalizes user-provided fetch options into a complete, isolated options object.\n *\n * @param url - The target URL.\n * @param options - User-provided options.\n * @returns Internal, complete, and isolated fetch options.\n * @internal\n */\nexport function processOptions_(url: string, options: FetchOptions = {}): InternalFetchOptions_ {\n DEV_MODE && logger_.logMethod?.('processOptions_');\n\n const processedUrl = appendQueryParams_(url, options.queryParams);\n\n const options_: InternalFetchOptions_ = {\n ...defaultFetchOptions,\n ...options,\n headers: normalizeHeaders_(options.headers),\n url: processedUrl,\n method: (options.method?.toUpperCase() as HttpMethod) ?? defaultFetchOptions.method,\n timeout: parseDuration(options.timeout ?? defaultFetchOptions.timeout),\n retryDelay: parseDuration(options.retryDelay ?? defaultFetchOptions.retryDelay),\n retry:\n typeof options.retry === 'number' && Number.isFinite(options.retry) ?\n Math.max(1, Math.floor(options.retry))\n : defaultFetchOptions.retry,\n };\n\n options_.window ??= null;\n\n // Cache API Preconditions: requires Cache API runtime support and cacheable HTTP method (GET/HEAD)\n if (\n options_.cacheStrategy !== 'network_only'\n && (typeof caches === 'undefined' || (options_.method !== 'GET' && options_.method !== 'HEAD'))\n ) {\n DEV_MODE\n && logger_.incident?.('processOptions_', 'fetch_cache_strategy_unsupported', {\n method: options_.method,\n cacheStrategy: options_.cacheStrategy,\n hasCaches: typeof caches !== 'undefined',\n });\n options_.cacheStrategy = 'network_only';\n }\n\n // Deduplication auto selection\n if (options_.removeDuplicate === 'auto') {\n options_.removeDuplicate = typeof caches !== 'undefined' ? 'until_load' : 'always';\n }\n\n // JSON Body serialization\n if (options.bodyJson !== undefined) {\n options_.body = JSON.stringify(options.bodyJson);\n options_.headers['content-type'] = MimeTypes.JSON;\n }\n\n // Authorization header configuration\n if (options.bearerToken !== undefined) {\n options_.headers.authorization = `Bearer ${options.bearerToken}`;\n } else if (options.alwatrAuth !== undefined) {\n options_.headers.authorization = `Alwatr ${options.alwatrAuth.userId}:${options.alwatrAuth.userToken}`;\n }\n\n return options_;\n}\n",
6
+ "import {MimeTypes, type HttpMethod} from '@alwatr/http-primer';\nimport {createLogger} from '@alwatr/logger';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {parseDuration} from '@alwatr/parse-duration';\n\nimport type {AlwatrFetchOptions_, FetchOptions, InternalFetchOptions_, QueryParams} from './type.js';\n\nexport const logger_ = createLogger('@alwatr/fetch');\n\nexport const globalThis_ = getGlobalThis();\n\n/**\n * Immutable default options for all fetch requests.\n */\nexport const defaultFetchOptions: Readonly<AlwatrFetchOptions_> = {\n method: 'GET',\n timeout: 8_000,\n retry: 3,\n retryDelay: 1_000,\n removeDuplicate: 'never',\n cacheStrategy: 'network_only',\n cacheStorageName: 'fetch_cache',\n // headers: {}, // --- IGNORED ---\n};\n\n/**\n * Normalizes any standard `HeadersInit` into a fresh, isolated lowercase string record.\n *\n * @param headers - User-provided headers (plain object, Headers instance, or entries array).\n * @param baseHeaders - Optional base headers to merge with the user-provided headers.\n * @returns An isolated `Record<string, string>`.\n */\nexport function normalizeHeaders_(\n headers?: HeadersInit,\n baseHeaders: Record<string, string> = {},\n): Record<string, string> {\n if (headers == null) {\n return baseHeaders;\n }\n\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n headers.forEach((value, key) => {\n baseHeaders[key.toLowerCase()] = value;\n });\n return baseHeaders;\n }\n\n if (Array.isArray(headers)) {\n for (const [key, value] of headers) {\n if (typeof key === 'string' && typeof value === 'string') {\n baseHeaders[key.toLowerCase()] = value;\n }\n }\n return baseHeaders;\n }\n\n if (typeof headers === 'object') {\n for (const key of Object.keys(headers)) {\n const val = (headers as Record<string, unknown>)[key];\n if (val != null) {\n baseHeaders[key.toLowerCase()] = String(val);\n }\n }\n }\n\n return baseHeaders;\n}\n\n/**\n * Serializes query parameters into a query string.\n *\n * @param queryParams - Dictionary of query parameters.\n * @returns Serialized URL query string (without leading `?` or `&`).\n */\nexport function serializeQueryParams_(queryParams: QueryParams): string {\n const parts: string[] = [];\n\n for (const key of Object.keys(queryParams)) {\n const value = queryParams[key];\n if (value == null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item != null) {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);\n }\n }\n } else {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n }\n }\n\n return parts.join('&');\n}\n\n/**\n * Appends query parameters to a URL, correctly respecting existing query parameters and hash anchors.\n *\n * @param url - The target URL.\n * @param queryParams - Query parameters to append.\n * @returns The resulting URL string.\n */\nexport function appendQueryParams_(url: string, queryParams?: QueryParams): string {\n if (queryParams == null) {\n return url;\n }\n\n const queryString = serializeQueryParams_(queryParams);\n if (queryString.length === 0) {\n return url;\n }\n\n // Handle hash fragment if present in URL\n let baseUrl = url;\n let hashPart = '';\n const hashIndex = url.indexOf('#');\n\n if (hashIndex !== -1) {\n baseUrl = url.slice(0, hashIndex);\n hashPart = url.slice(hashIndex);\n }\n\n const separator = baseUrl.includes('?') ? '&' : '?';\n return `${baseUrl}${separator}${queryString}${hashPart}`;\n}\n\n/**\n * Processes, sanitizes, and normalizes user-provided fetch options into a complete, isolated options object.\n *\n * @param url - The target URL.\n * @param options - User-provided options.\n * @returns Internal, complete, and isolated fetch options.\n * @internal\n */\nexport function processOptions_(url: string, options: FetchOptions = {}): InternalFetchOptions_ {\n DEV_MODE && logger_.logMethod?.('processOptions_');\n\n const processedUrl = appendQueryParams_(url, options.queryParams);\n\n const options_: InternalFetchOptions_ = {\n ...defaultFetchOptions,\n ...options,\n headers: normalizeHeaders_(options.headers),\n url: processedUrl,\n method: (options.method?.toUpperCase() as HttpMethod) ?? defaultFetchOptions.method,\n timeout: parseDuration(options.timeout ?? defaultFetchOptions.timeout),\n retryDelay: parseDuration(options.retryDelay ?? defaultFetchOptions.retryDelay),\n retry:\n typeof options.retry === 'number' && Number.isFinite(options.retry) ?\n Math.max(1, Math.floor(options.retry))\n : defaultFetchOptions.retry,\n };\n\n options_.window ??= null;\n\n // Cache API Preconditions: requires Cache API runtime support and cacheable HTTP method (GET/HEAD)\n if (\n options_.cacheStrategy !== 'network_only'\n && (typeof caches === 'undefined' || (options_.method !== 'GET' && options_.method !== 'HEAD'))\n ) {\n DEV_MODE\n && logger_.incident?.('processOptions_', 'fetch_cache_strategy_unsupported', {\n method: options_.method,\n cacheStrategy: options_.cacheStrategy,\n hasCaches: typeof caches !== 'undefined',\n });\n options_.cacheStrategy = 'network_only';\n }\n\n // Deduplication auto selection\n if (options_.removeDuplicate === 'auto') {\n options_.removeDuplicate = typeof caches !== 'undefined' ? 'until_load' : 'always';\n }\n\n // JSON Body serialization\n if (options.bodyJson != null) {\n options_.body = JSON.stringify(options.bodyJson);\n options_.headers['content-type'] = MimeTypes.JSON;\n }\n\n // Authorization header configuration\n if (options.bearerToken != null) {\n options_.headers.authorization = `Bearer ${options.bearerToken}`;\n } else if (options.alwatrAuth != null) {\n options_.headers.authorization = `Alwatr ${options.alwatrAuth.userId}:${options.alwatrAuth.userToken}`;\n }\n\n return options_;\n}\n",
7
7
  "import {delay} from '@alwatr/delay';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {HttpStatusCodes} from '@alwatr/http-primer';\nimport {FetchError} from './error.js';\nimport {logger_} from './options.js';\nimport {handleTimeout_} from './timeout.js';\n\nimport type {InternalFetchOptions_} from './type.js';\n\nconst globalThis_ = getGlobalThis();\n\n/**\n * Checks whether an HTTP response status code is retryable.\n *\n * Retryable statuses:\n * - Any 5xx Server Error (500, 502, 503, 504, ...)\n * - 408 Request Timeout\n * - 429 Too Many Requests\n */\nexport function isRetryableStatus_(status: number): boolean {\n return (\n status >= HttpStatusCodes.Error_Server_500_Internal_Server_Error\n || status === HttpStatusCodes.Error_Client_408_Request_Timeout\n || status === HttpStatusCodes.Error_Client_429_Too_Many_Requests\n );\n}\n\n/**\n * Parses the `Retry-After` header value (in seconds or HTTP-date) if present.\n *\n * @param response - The HTTP Response object.\n * @returns Delay duration in milliseconds, or undefined if absent/invalid.\n */\nexport function parseRetryAfterHeader_(response?: Response): number | undefined {\n const retryAfter = response?.headers?.get('retry-after');\n if (!retryAfter) return undefined;\n\n const seconds = Number(retryAfter);\n if (!isNaN(seconds) && seconds > 0) {\n return seconds * 1000;\n }\n\n const dateMs = Date.parse(retryAfter);\n if (!isNaN(dateMs)) {\n const diff = dateMs - Date.now();\n return diff > 0 ? diff : 0;\n }\n\n return undefined;\n}\n\n/**\n * Executes a fetch request with automatic retries on transient errors (5xx, 429, 408, network failures, timeouts).\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to the final `Response` after retry cycles.\n * @internal\n */\nexport async function handleRetryPattern_(options: InternalFetchOptions_): Promise<Response> {\n if (options.retry <= 1) {\n return handleTimeout_(options);\n }\n\n DEV_MODE && logger_.logMethod?.('handleRetryPattern_');\n options.retry--;\n\n let response: Response;\n try {\n response = await handleTimeout_(options);\n\n if (response.ok || !isRetryableStatus_(response.status)) {\n return response;\n }\n } catch (err) {\n DEV_MODE && logger_.accident('fetch', 'fetch_failed_retry', err);\n\n // Never retry if the request was intentionally aborted\n if (options.signal?.aborted || (err instanceof FetchError && err.reason === 'aborted')) {\n throw err;\n }\n\n // Do not retry if the runtime is offline\n if (globalThis_.navigator?.onLine === false) {\n DEV_MODE && logger_.accident('handleRetryPattern_', 'offline', 'Skip retry because offline');\n throw err;\n }\n\n await delay.by(options.retryDelay);\n\n return handleRetryPattern_(options);\n }\n\n // Handle transient retryable HTTP status (5xx, 429, 408)\n DEV_MODE && logger_.accident('fetch', 'fetch_failed_retry', {status: response.status});\n\n if (globalThis_.navigator?.onLine === false) {\n DEV_MODE && logger_.accident('handleRetryPattern_', 'offline', 'Skip retry because offline');\n return response;\n }\n\n const retryDelay = parseRetryAfterHeader_(response) ?? options.retryDelay;\n\n await delay.by(retryDelay);\n\n return handleRetryPattern_(options);\n}\n",
8
- "import {getGlobalThis} from '@alwatr/global-this';\nimport {FetchError} from './error.js';\nimport {logger_} from './options.js';\n\nimport type {InternalFetchOptions_} from './type.js';\n\nconst globalThis_ = getGlobalThis();\n\n/**\n * Executes a native `fetch` wrapped with an `AbortController` timeout.\n *\n * Checks for pre-aborted external signals, respects external cancellation,\n * and guarantees listener and timer cleanup on completion.\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to the native `Response` or rejecting with `FetchError`.\n * @internal\n */\nexport function handleTimeout_(options: InternalFetchOptions_): Promise<Response> {\n const externalSignal = options.signal;\n\n // Immediate abort check: If signal is already aborted, reject immediately without network overhead\n if (externalSignal?.aborted) {\n DEV_MODE && logger_.incident?.('handleTimeout_', 'already_aborted', {reason: externalSignal.reason});\n return Promise.reject(new FetchError('aborted', 'The operation was aborted'));\n }\n\n // If timeout is disabled (0), invoke native fetch directly with external signal\n if (options.timeout === 0) {\n return globalThis_.fetch(options.url, options as RequestInit);\n }\n\n DEV_MODE && logger_.logMethod?.('handleTimeout_');\n\n return new Promise((resolve, reject) => {\n const abortController = typeof AbortController === 'function' ? new AbortController() : null;\n\n let onExternalAbort: (() => void) | undefined;\n\n if (abortController !== null) {\n options.signal = abortController.signal;\n\n if (externalSignal != null) {\n onExternalAbort = () => {\n abortController.abort(externalSignal.reason);\n };\n externalSignal.addEventListener('abort', onExternalAbort, {once: true});\n }\n }\n\n let timeoutFired = false;\n\n const timeoutId = setTimeout(() => {\n timeoutFired = true;\n abortController?.abort('fetch_timeout');\n reject(new FetchError('timeout', 'fetch_timeout'));\n }, options.timeout);\n\n globalThis_\n .fetch(options.url, options as RequestInit)\n .then((response) => {\n if (!timeoutFired) {\n resolve(response);\n }\n })\n .catch((err: unknown) => {\n if (timeoutFired) {\n return;\n }\n\n if (externalSignal?.aborted || (err instanceof Error && err.name === 'AbortError')) {\n reject(new FetchError('aborted', 'The operation was aborted'));\n } else {\n reject(err);\n }\n })\n .finally(() => {\n clearTimeout(timeoutId);\n options.signal = externalSignal;\n if (externalSignal != null && onExternalAbort !== undefined) {\n externalSignal.removeEventListener('abort', onExternalAbort);\n }\n });\n });\n}\n",
8
+ "import {getGlobalThis} from '@alwatr/global-this';\nimport {FetchError} from './error.js';\nimport {logger_} from './options.js';\n\nimport type {InternalFetchOptions_} from './type.js';\n\nconst globalThis_ = getGlobalThis();\n\n/**\n * Executes a native `fetch` wrapped with an `AbortController` timeout.\n *\n * Checks for pre-aborted external signals, respects external cancellation,\n * and guarantees listener and timer cleanup on completion.\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to the native `Response` or rejecting with `FetchError`.\n * @internal\n */\nexport function handleTimeout_(options: InternalFetchOptions_): Promise<Response> {\n const externalSignal = options.signal;\n\n // Immediate abort check: If signal is already aborted, reject immediately without network overhead\n if (externalSignal?.aborted) {\n DEV_MODE && logger_.incident?.('handleTimeout_', 'already_aborted', {reason: externalSignal.reason});\n return Promise.reject(new FetchError('aborted', 'The operation was aborted'));\n }\n\n // If timeout is disabled (0), invoke native fetch directly with external signal\n if (options.timeout === 0) {\n return globalThis_.fetch(options.url, options as RequestInit);\n }\n\n DEV_MODE && logger_.logMethod?.('handleTimeout_');\n\n return new Promise((resolve, reject) => {\n const abortController = typeof AbortController === 'function' ? new AbortController() : null;\n\n let onExternalAbort: (() => void) | undefined;\n\n if (abortController !== null) {\n options.signal = abortController.signal;\n\n if (externalSignal != null) {\n onExternalAbort = () => {\n abortController.abort(externalSignal.reason);\n };\n externalSignal.addEventListener('abort', onExternalAbort, {once: true});\n }\n }\n\n let timeoutFired = false;\n\n const timeoutId = setTimeout(() => {\n timeoutFired = true;\n abortController?.abort('fetch_timeout');\n reject(new FetchError('timeout', 'fetch_timeout'));\n }, options.timeout);\n\n globalThis_\n .fetch(options.url, options as RequestInit)\n .then((response) => {\n if (!timeoutFired) {\n resolve(response);\n }\n })\n .catch((err: unknown) => {\n if (timeoutFired) {\n return;\n }\n\n if (externalSignal?.aborted || (err instanceof Error && err.name === 'AbortError')) {\n reject(new FetchError('aborted', 'The operation was aborted'));\n } else {\n reject(err);\n }\n })\n .finally(() => {\n clearTimeout(timeoutId);\n options.signal = externalSignal;\n if (externalSignal != null && onExternalAbort != null) {\n externalSignal.removeEventListener('abort', onExternalAbort);\n }\n });\n });\n}\n",
9
9
  "import {logger_} from './options.js';\nimport {handleRetryPattern_} from './retry.js';\n\nimport type {InternalFetchOptions_} from './type.js';\n\n/**\n * Storage for tracking in-flight duplicate requests.\n */\nconst duplicateRequestStorage_: Map<string, Promise<Response>> = new Map();\n\n/**\n * Computes a secure cache key for request deduplication.\n * Includes method, full URL, authorization header, and request body.\n *\n * @param options - Processed internal fetch options.\n * @returns Unique string identifier for the request intent.\n */\nexport function computeDedupeKey_(options: InternalFetchOptions_): string {\n const bodyString = typeof options.body === 'string' ? options.body : '';\n const auth = options.headers['authorization'] ?? '';\n return `${options.method} ${options.url} [auth:${auth}] [body:${bodyString}]`;\n}\n\n/**\n * Handles duplicate parallel request coalescing.\n *\n * If an identical request is already in-flight, returns a cloned response of the existing\n * promise to avoid redundant network round-trips.\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to an independent cloned `Response`.\n * @internal\n */\nexport async function handleRemoveDuplicate_(options: InternalFetchOptions_): Promise<Response> {\n if (options.removeDuplicate === 'never') {\n return handleRetryPattern_(options);\n }\n\n DEV_MODE && logger_.logMethod?.('handleRemoveDuplicate_');\n\n const cacheKey = computeDedupeKey_(options);\n\n let requestAsync = duplicateRequestStorage_.get(cacheKey);\n if (requestAsync == null) {\n requestAsync = handleRetryPattern_(options);\n duplicateRequestStorage_.set(cacheKey, requestAsync);\n }\n\n try {\n const response = await requestAsync;\n\n // Clean up stored promise for 'until_load' or failed responses\n if (!response.ok || options.removeDuplicate === 'until_load') {\n duplicateRequestStorage_.delete(cacheKey);\n }\n\n // Return a clone so every concurrent caller can independently consume the body\n return response.clone();\n } catch (err) {\n // If request failed, remove from storage immediately\n duplicateRequestStorage_.delete(cacheKey);\n throw err;\n }\n}\n",
10
10
  "import {FetchError} from './error.js';\nimport {handleRemoveDuplicate_} from './dedupe.js';\nimport {logger_} from './options.js';\nimport {delay} from '@alwatr/delay';\n\nimport type {InternalFetchOptions_} from './type.js';\n\n/**\n * Executes the caching lifecycle according to `cacheStrategy`.\n *\n * Interacts safely with Cache API:\n * - Falls back to network when Cache API is unavailable or throws.\n * - Guards against caching non-GET requests.\n * - Clones responses before storing to keep response bodies consumable.\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to a cached or freshly fetched `Response`.\n * @internal\n */\nexport async function handleCacheStrategy_(options: InternalFetchOptions_): Promise<Response> {\n if (options.cacheStrategy === 'network_only') {\n return handleRemoveDuplicate_(options);\n }\n\n DEV_MODE && logger_.logMethod?.('handleCacheStrategy_');\n\n let cacheStorage: Cache;\n try {\n cacheStorage = await caches.open(options.cacheStorageName);\n } catch (err) {\n DEV_MODE && logger_.accident('handleCacheStrategy_', 'cache_open_failed', {err});\n options.cacheStrategy = 'network_only';\n return handleRemoveDuplicate_(options);\n }\n\n const request = new Request(options.url, options);\n\n switch (options.cacheStrategy) {\n case 'cache_first': {\n try {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse != null) {\n return cachedResponse;\n }\n } catch (err) {\n DEV_MODE && logger_.accident('handleCacheStrategy_', 'cache_match_failed', {err});\n }\n\n const response = await handleRemoveDuplicate_(options);\n if (response.ok) {\n try {\n await cacheStorage.put(request, response.clone());\n } catch {\n // ignore cache put failures\n }\n }\n return response;\n }\n\n case 'cache_only': {\n let cachedResponse: Response | undefined;\n try {\n cachedResponse = await cacheStorage.match(request);\n } catch (err) {\n DEV_MODE && logger_.accident('handleCacheStrategy_', 'cache_only_match_failed', {err});\n }\n\n if (cachedResponse == null) {\n throw new FetchError('cache_not_found', 'Resource not found in cache');\n }\n return cachedResponse;\n }\n\n case 'network_first': {\n try {\n const networkResponse = await handleRemoveDuplicate_(options);\n if (networkResponse.ok) {\n try {\n await cacheStorage.put(request, networkResponse.clone());\n } catch {\n // ignore cache put failures\n }\n }\n return networkResponse;\n } catch (err) {\n try {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse != null) {\n return cachedResponse;\n }\n } catch {\n // ignore cache match error and throw original error\n }\n throw err;\n }\n }\n\n case 'update_cache': {\n const networkResponse = await handleRemoveDuplicate_(options);\n if (networkResponse.ok) {\n try {\n await cacheStorage.put(request, networkResponse.clone());\n } catch {\n // ignore cache put failures\n }\n }\n return networkResponse;\n }\n\n case 'stale_while_revalidate': {\n let cachedResponse: Response | undefined;\n try {\n cachedResponse = await cacheStorage.match(request);\n } catch {\n // ignore cache match error\n }\n\n const fetchedResponsePromise = handleRemoveDuplicate_(options).then(async (networkResponse) => {\n if (networkResponse.ok) {\n try {\n await cacheStorage.put(request, networkResponse.clone());\n } catch {\n // ignore cache put failures\n }\n if (typeof options.revalidateCallback === 'function') {\n const callback = options.revalidateCallback;\n const revalidatePayload = networkResponse.clone();\n await delay.nextMacrotask();\n try {\n await callback(revalidatePayload);\n } catch (err) {\n DEV_MODE && logger_.accident('handleCacheStrategy_', 'revalidate_callback_failed', {err});\n }\n }\n }\n return networkResponse;\n });\n\n return cachedResponse ?? fetchedResponsePromise;\n }\n\n default: {\n return handleRemoveDuplicate_(options);\n }\n }\n}\n",
11
- "import {FetchError, httpStatusToErrorReason} from './error.js';\nimport {handleCacheStrategy_} from './cache.js';\nimport {processOptions_, logger_} from './options.js';\n\nimport type {FetchJsonOptions, FetchJsonResponse, FetchOptions, FetchResponse} from './type.js';\n\n/**\n * An enhanced wrapper for the native `fetch` function.\n *\n * Provides:\n * - **Deterministic Errors**: Semantic `FetchError` reasons (e.g. `unauthorized`, `forbidden`, `not_found`, `server_error`, `timeout`, `aborted`, `rate_limited`).\n * - **Go-Style Tuple Return**: Never throws, returns `[response, null]` on success or `[null, FetchError]` on failure.\n * - **Automatic Timeout**: Aborts the request if it exceeds `timeout` duration.\n * - **Configurable Retry**: Automatically retries transient 5xx, 429, 408, or network errors with `retryDelay` and `Retry-After` support.\n * - **Parallel Deduplication**: Collapses identical concurrent in-flight requests.\n * - **Cache Strategies**: Integrates with Cache API (`cache_first`, `stale_while_revalidate`, etc.).\n * - **Isolated Headers & Query Params**: Safely formats query parameters and authorization credentials without mutating caller objects.\n *\n * @param url - The URL to fetch.\n * @param options - Configuration options for the fetch request.\n * @returns A promise resolving to `[Response, null]` on success, or `[null, FetchError]` on failure.\n *\n * @example\n * ```typescript\n * import {fetch} from '@alwatr/fetch';\n *\n * const [response, error] = await fetch('/api/products', {\n * queryParams: { limit: 10 },\n * timeout: '5s',\n * });\n *\n * if (error) {\n * if (error.reason === 'not_found') {\n * console.warn('Product not found');\n * }\n * return;\n * }\n *\n * const data = await response.json();\n * ```\n */\nexport async function fetch(url: string, options: FetchOptions = {}): Promise<FetchResponse> {\n const options_ = processOptions_(url, options);\n DEV_MODE && logger_.logMethodArgs?.('fetch', options_);\n\n try {\n const response = await handleCacheStrategy_(options_);\n\n if (!response.ok) {\n const reason = httpStatusToErrorReason(response.status);\n throw new FetchError(reason, `HTTP error! status: ${response.status} ${response.statusText}`, response);\n }\n\n return [response, null];\n } catch (err) {\n let error: FetchError;\n\n if (err instanceof FetchError) {\n error = err;\n\n if (error.response !== undefined && error.data === undefined) {\n const bodyText = await error.response.text().catch(() => '');\n\n if (bodyText.trim().length > 0) {\n try {\n error.data = JSON.parse(bodyText);\n } catch {\n error.data = bodyText;\n }\n }\n }\n } else if (err instanceof Error) {\n if (err.name === 'AbortError') {\n error = new FetchError('aborted', err.message);\n } else {\n error = new FetchError('network_error', err.message);\n }\n } else {\n error = new FetchError('unknown_error', String(err ?? 'unknown_error'));\n }\n\n DEV_MODE && logger_.accident('fetch', error.reason, {error});\n return [null, error];\n }\n}\n\n/**\n * An enhanced wrapper for `fetch` that automatically parses JSON responses.\n *\n * Accepts unconstrained generic interfaces, DTOs, and arrays without requiring index signatures.\n *\n * @template T - The expected type of the JSON response payload.\n *\n * @param url - The URL to fetch.\n * @param options - Configuration options for the fetch request.\n * @returns A promise resolving to `[data, null]` where data is typed as `T`, or `[null, FetchError]`.\n *\n * @example\n * ```typescript\n * import {fetchJson} from '@alwatr/fetch';\n *\n * interface User {\n * id: string;\n * name: string;\n * }\n *\n * const [users, error] = await fetchJson<User[]>('/api/users');\n * if (error) {\n * console.error('Failed to load users:', error.reason);\n * return;\n * }\n * console.log('Users count:', users.length);\n * ```\n */\nexport async function fetchJson<T = unknown>(\n url: string,\n options: FetchJsonOptions = {},\n): Promise<FetchJsonResponse<T>> {\n DEV_MODE && logger_.logMethod?.('fetchJson');\n\n const [response, error] = await fetch(url, options);\n\n if (error) {\n return [null, error];\n }\n\n const bodyText = await response.text().catch(() => '');\n if (bodyText.trim().length === 0) {\n const parseError = new FetchError(\n 'json_parse_error',\n 'Response body is empty, cannot parse JSON',\n response,\n bodyText,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n\n try {\n const data = JSON.parse(bodyText) as T;\n\n if (\n options.requireJsonResponseWithOkTrue\n && (typeof data !== 'object' || data === null || (data as Record<string, unknown>).ok !== true)\n ) {\n const parseError = new FetchError(\n 'json_response_error',\n 'Response JSON \"ok\" property is not true',\n response,\n data,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n\n return [data, null];\n } catch (err) {\n const parseError = new FetchError(\n 'json_parse_error',\n err instanceof Error ? err.message : 'Failed to parse JSON response',\n response,\n bodyText,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n}\n\nfetchJson.version = fetch.version = __package_version__;\n"
11
+ "import {FetchError, httpStatusToErrorReason} from './error.js';\nimport {handleCacheStrategy_} from './cache.js';\nimport {processOptions_, logger_} from './options.js';\n\nimport type {FetchJsonOptions, FetchJsonResponse, FetchOptions, FetchResponse} from './type.js';\n\n/**\n * An enhanced wrapper for the native `fetch` function.\n *\n * Provides:\n * - **Deterministic Errors**: Semantic `FetchError` reasons (e.g. `unauthorized`, `forbidden`, `not_found`, `server_error`, `timeout`, `aborted`, `rate_limited`).\n * - **Go-Style Tuple Return**: Never throws, returns `[response, null]` on success or `[null, FetchError]` on failure.\n * - **Automatic Timeout**: Aborts the request if it exceeds `timeout` duration.\n * - **Configurable Retry**: Automatically retries transient 5xx, 429, 408, or network errors with `retryDelay` and `Retry-After` support.\n * - **Parallel Deduplication**: Collapses identical concurrent in-flight requests.\n * - **Cache Strategies**: Integrates with Cache API (`cache_first`, `stale_while_revalidate`, etc.).\n * - **Isolated Headers & Query Params**: Safely formats query parameters and authorization credentials without mutating caller objects.\n *\n * @param url - The URL to fetch.\n * @param options - Configuration options for the fetch request.\n * @returns A promise resolving to `[Response, null]` on success, or `[null, FetchError]` on failure.\n *\n * @example\n * ```typescript\n * import {fetch} from '@alwatr/fetch';\n *\n * const [response, error] = await fetch('/api/products', {\n * queryParams: { limit: 10 },\n * timeout: '5s',\n * });\n *\n * if (error) {\n * if (error.reason === 'not_found') {\n * console.warn('Product not found');\n * }\n * return;\n * }\n *\n * const data = await response.json();\n * ```\n */\nexport async function fetch(url: string, options: FetchOptions = {}): Promise<FetchResponse> {\n const options_ = processOptions_(url, options);\n DEV_MODE && logger_.logMethodArgs?.('fetch', options_);\n\n try {\n const response = await handleCacheStrategy_(options_);\n\n if (!response.ok) {\n const reason = httpStatusToErrorReason(response.status);\n throw new FetchError(reason, `HTTP error! status: ${response.status} ${response.statusText}`, response);\n }\n\n return [response, null];\n } catch (err) {\n let error: FetchError;\n\n if (err instanceof FetchError) {\n error = err;\n\n if (error.response != null && error.data == null) {\n const bodyText = await error.response.text().catch(() => '');\n\n if (bodyText.trim().length > 0) {\n try {\n error.data = JSON.parse(bodyText);\n } catch {\n error.data = bodyText;\n }\n }\n }\n } else if (err instanceof Error) {\n if (err.name === 'AbortError') {\n error = new FetchError('aborted', err.message);\n } else {\n error = new FetchError('network_error', err.message);\n }\n } else {\n error = new FetchError('unknown_error', String(err ?? 'unknown_error'));\n }\n\n DEV_MODE && logger_.accident('fetch', error.reason, {error});\n return [null, error];\n }\n}\n\n/**\n * An enhanced wrapper for `fetch` that automatically parses JSON responses.\n *\n * Accepts unconstrained generic interfaces, DTOs, and arrays without requiring index signatures.\n *\n * @template T - The expected type of the JSON response payload.\n *\n * @param url - The URL to fetch.\n * @param options - Configuration options for the fetch request.\n * @returns A promise resolving to `[data, null]` where data is typed as `T`, or `[null, FetchError]`.\n *\n * @example\n * ```typescript\n * import {fetchJson} from '@alwatr/fetch';\n *\n * interface User {\n * id: string;\n * name: string;\n * }\n *\n * const [users, error] = await fetchJson<User[]>('/api/users');\n * if (error) {\n * console.error('Failed to load users:', error.reason);\n * return;\n * }\n * console.log('Users count:', users.length);\n * ```\n */\nexport async function fetchJson<T = unknown>(\n url: string,\n options: FetchJsonOptions = {},\n): Promise<FetchJsonResponse<T>> {\n DEV_MODE && logger_.logMethod?.('fetchJson');\n\n const [response, error] = await fetch(url, options);\n\n if (error) {\n return [null, error];\n }\n\n const bodyText = await response.text().catch(() => '');\n if (bodyText.trim().length === 0) {\n const parseError = new FetchError(\n 'json_parse_error',\n 'Response body is empty, cannot parse JSON',\n response,\n bodyText,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n\n try {\n const data = JSON.parse(bodyText) as T;\n\n if (\n options.requireJsonResponseWithOkTrue\n && (typeof data !== 'object' || data === null || (data as Record<string, unknown>).ok !== true)\n ) {\n const parseError = new FetchError(\n 'json_response_error',\n 'Response JSON \"ok\" property is not true',\n response,\n data,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n\n return [data, null];\n } catch (err) {\n const parseError = new FetchError(\n 'json_parse_error',\n err instanceof Error ? err.message : 'Failed to parse JSON response',\n response,\n bodyText,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n}\n\nfetchJson.version = fetch.version = __package_version__;\n"
12
12
  ],
13
- "mappings": "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",
14
- "debugId": "ED8587057A108B4C64756E2164756E21",
13
+ "mappings": "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",
14
+ "debugId": "0512877C39EC257264756E2164756E21",
15
15
  "names": []
16
16
  }
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
- /* 📦 @alwatr/fetch v10.1.0 */
2
- import{HttpStatusCodes as i}from"@alwatr/http-primer";function m(r){switch(r){case i.Error_Client_400_Bad_Request:return"bad_request";case i.Error_Client_401_Unauthorized:return"unauthorized";case i.Error_Client_403_Forbidden:return"forbidden";case i.Error_Client_404_Not_Found:return"not_found";case i.Error_Client_408_Request_Timeout:return"request_timeout";case i.Error_Client_409_Conflict:return"conflict";case i.Error_Client_413_Payload_Too_Large:return"payload_too_large";case i.Error_Client_422_Unprocessable_Entity:return"unprocessable_content";case i.Error_Client_429_Too_Many_Requests:return"rate_limited";default:if(r>=500&&r<600)return"server_error";return"http_error"}}class s extends Error{response;data;reason;get status(){return this.response?.status}ok=!1;constructor(r,t,n,e){super(t);this.name="FetchError",this.reason=r,this.response=n,this.data=e}}import{MimeTypes as S}from"@alwatr/http-primer";import{createLogger as k}from"@alwatr/logger";import{getGlobalThis as F}from"@alwatr/global-this";import{parseDuration as g}from"@alwatr/parse-duration";var G=k("@alwatr/fetch"),H=F(),f={method:"GET",timeout:8000,retry:3,retryDelay:1000,removeDuplicate:"never",cacheStrategy:"network_only",cacheStorageName:"fetch_cache"};function M(r,t={}){if(r==null)return t;if(typeof Headers<"u"&&r instanceof Headers)return r.forEach((n,e)=>{t[e.toLowerCase()]=n}),t;if(Array.isArray(r)){for(let[n,e]of r)if(typeof n==="string"&&typeof e==="string")t[n.toLowerCase()]=e;return t}if(typeof r==="object")for(let n of Object.keys(r)){let e=r[n];if(e!=null)t[n.toLowerCase()]=String(e)}return t}function C(r){let t=[];for(let n of Object.keys(r)){let e=r[n];if(e===void 0||e===null)continue;if(Array.isArray(e)){for(let o of e)if(o!==void 0&&o!==null)t.push(`${encodeURIComponent(n)}=${encodeURIComponent(String(o))}`)}else t.push(`${encodeURIComponent(n)}=${encodeURIComponent(String(e))}`)}return t.join("&")}function T(r,t){if(t==null)return r;let n=C(t);if(n.length===0)return r;let e=r,o="",a=r.indexOf("#");if(a!==-1)e=r.slice(0,a),o=r.slice(a);let c=e.includes("?")?"&":"?";return`${e}${c}${n}${o}`}function E(r,t={}){let n=T(r,t.queryParams),e={...f,...t,headers:M(t.headers),url:n,method:t.method?.toUpperCase()??f.method,timeout:g(t.timeout??f.timeout),retryDelay:g(t.retryDelay??f.retryDelay),retry:typeof t.retry==="number"&&Number.isFinite(t.retry)?Math.max(1,Math.floor(t.retry)):f.retry};if(e.window??=null,e.cacheStrategy!=="network_only"&&(typeof caches>"u"||e.method!=="GET"&&e.method!=="HEAD"))e.cacheStrategy="network_only";if(e.removeDuplicate==="auto")e.removeDuplicate=typeof caches<"u"?"until_load":"always";if(t.bodyJson!==void 0)e.body=JSON.stringify(t.bodyJson),e.headers["content-type"]=S.JSON;if(t.bearerToken!==void 0)e.headers.authorization=`Bearer ${t.bearerToken}`;else if(t.alwatrAuth!==void 0)e.headers.authorization=`Alwatr ${t.alwatrAuth.userId}:${t.alwatrAuth.userToken}`;return e}import{delay as b}from"@alwatr/delay";import{getGlobalThis as v}from"@alwatr/global-this";import{HttpStatusCodes as y}from"@alwatr/http-primer";import{getGlobalThis as x}from"@alwatr/global-this";var w=x();function p(r){let t=r.signal;if(t?.aborted)return Promise.reject(new s("aborted","The operation was aborted"));if(r.timeout===0)return w.fetch(r.url,r);return new Promise((n,e)=>{let o=typeof AbortController==="function"?new AbortController:null,a;if(o!==null){if(r.signal=o.signal,t!=null)a=()=>{o.abort(t.reason)},t.addEventListener("abort",a,{once:!0})}let c=!1,d=setTimeout(()=>{c=!0,o?.abort("fetch_timeout"),e(new s("timeout","fetch_timeout"))},r.timeout);w.fetch(r.url,r).then((u)=>{if(!c)n(u)}).catch((u)=>{if(c)return;if(t?.aborted||u instanceof Error&&u.name==="AbortError")e(new s("aborted","The operation was aborted"));else e(u)}).finally(()=>{if(clearTimeout(d),r.signal=t,t!=null&&a!==void 0)t.removeEventListener("abort",a)})})}var D=v();function I(r){return r>=y.Error_Server_500_Internal_Server_Error||r===y.Error_Client_408_Request_Timeout||r===y.Error_Client_429_Too_Many_Requests}function P(r){let t=r?.headers?.get("retry-after");if(!t)return;let n=Number(t);if(!isNaN(n)&&n>0)return n*1000;let e=Date.parse(t);if(!isNaN(e)){let o=e-Date.now();return o>0?o:0}return}async function _(r){if(r.retry<=1)return p(r);r.retry--;let t;try{if(t=await p(r),t.ok||!I(t.status))return t}catch(e){if(r.signal?.aborted||e instanceof s&&e.reason==="aborted")throw e;if(D.navigator?.onLine===!1)throw e;return await b.by(r.retryDelay),_(r)}if(D.navigator?.onLine===!1)return t;let n=P(t)??r.retryDelay;return await b.by(n),_(r)}var h=new Map;function V(r){let t=typeof r.body==="string"?r.body:"",n=r.headers.authorization??"";return`${r.method} ${r.url} [auth:${n}] [body:${t}]`}async function l(r){if(r.removeDuplicate==="never")return _(r);let t=V(r),n=h.get(t);if(n==null)n=_(r),h.set(t,n);try{let e=await n;if(!e.ok||r.removeDuplicate==="until_load")h.delete(t);return e.clone()}catch(e){throw h.delete(t),e}}import{delay as A}from"@alwatr/delay";async function O(r){if(r.cacheStrategy==="network_only")return l(r);let t;try{t=await caches.open(r.cacheStorageName)}catch(e){return r.cacheStrategy="network_only",l(r)}let n=new Request(r.url,r);switch(r.cacheStrategy){case"cache_first":{try{let o=await t.match(n);if(o!=null)return o}catch(o){}let e=await l(r);if(e.ok)try{await t.put(n,e.clone())}catch{}return e}case"cache_only":{let e;try{e=await t.match(n)}catch(o){}if(e==null)throw new s("cache_not_found","Resource not found in cache");return e}case"network_first":try{let e=await l(r);if(e.ok)try{await t.put(n,e.clone())}catch{}return e}catch(e){try{let o=await t.match(n);if(o!=null)return o}catch{}throw e}case"update_cache":{let e=await l(r);if(e.ok)try{await t.put(n,e.clone())}catch{}return e}case"stale_while_revalidate":{let e;try{e=await t.match(n)}catch{}let o=l(r).then(async(a)=>{if(a.ok){try{await t.put(n,a.clone())}catch{}if(typeof r.revalidateCallback==="function"){let c=r.revalidateCallback,d=a.clone();await A.nextMacrotask();try{await c(d)}catch(u){}}}return a});return e??o}default:return l(r)}}async function R(r,t={}){let n=E(r,t);try{let e=await O(n);if(!e.ok){let o=m(e.status);throw new s(o,`HTTP error! status: ${e.status} ${e.statusText}`,e)}return[e,null]}catch(e){let o;if(e instanceof s){if(o=e,o.response!==void 0&&o.data===void 0){let a=await o.response.text().catch(()=>"");if(a.trim().length>0)try{o.data=JSON.parse(a)}catch{o.data=a}}}else if(e instanceof Error)if(e.name==="AbortError")o=new s("aborted",e.message);else o=new s("network_error",e.message);else o=new s("unknown_error",String(e??"unknown_error"));return[null,o]}}async function J(r,t={}){let[n,e]=await R(r,t);if(e)return[null,e];let o=await n.text().catch(()=>"");if(o.trim().length===0)return[null,new s("json_parse_error","Response body is empty, cannot parse JSON",n,o)];try{let a=JSON.parse(o);if(t.requireJsonResponseWithOkTrue&&(typeof a!=="object"||a===null||a.ok!==!0))return[null,new s("json_response_error",'Response JSON "ok" property is not true',n,a)];return[a,null]}catch(a){return[null,new s("json_parse_error",a instanceof Error?a.message:"Failed to parse JSON response",n,o)]}}J.version=R.version="10.1.0";export{s as FetchError,R as fetch,J as fetchJson,m as httpStatusToErrorReason};
1
+ /* 📦 @alwatr/fetch v10.1.1 */
2
+ import{HttpStatusCodes as i}from"@alwatr/http-primer";function m(r){switch(r){case i.Error_Client_400_Bad_Request:return"bad_request";case i.Error_Client_401_Unauthorized:return"unauthorized";case i.Error_Client_403_Forbidden:return"forbidden";case i.Error_Client_404_Not_Found:return"not_found";case i.Error_Client_408_Request_Timeout:return"request_timeout";case i.Error_Client_409_Conflict:return"conflict";case i.Error_Client_413_Payload_Too_Large:return"payload_too_large";case i.Error_Client_422_Unprocessable_Entity:return"unprocessable_content";case i.Error_Client_429_Too_Many_Requests:return"rate_limited";default:if(r>=500&&r<600)return"server_error";return"http_error"}}class s extends Error{response;data;reason;get status(){return this.response?.status}ok=!1;constructor(r,t,n,e){super(t);this.name="FetchError",this.reason=r,this.response=n,this.data=e}}import{MimeTypes as S}from"@alwatr/http-primer";import{createLogger as k}from"@alwatr/logger";import{getGlobalThis as F}from"@alwatr/global-this";import{parseDuration as g}from"@alwatr/parse-duration";var G=k("@alwatr/fetch"),H=F(),_={method:"GET",timeout:8000,retry:3,retryDelay:1000,removeDuplicate:"never",cacheStrategy:"network_only",cacheStorageName:"fetch_cache"};function M(r,t={}){if(r==null)return t;if(typeof Headers<"u"&&r instanceof Headers)return r.forEach((n,e)=>{t[e.toLowerCase()]=n}),t;if(Array.isArray(r)){for(let[n,e]of r)if(typeof n==="string"&&typeof e==="string")t[n.toLowerCase()]=e;return t}if(typeof r==="object")for(let n of Object.keys(r)){let e=r[n];if(e!=null)t[n.toLowerCase()]=String(e)}return t}function C(r){let t=[];for(let n of Object.keys(r)){let e=r[n];if(e==null)continue;if(Array.isArray(e)){for(let o of e)if(o!=null)t.push(`${encodeURIComponent(n)}=${encodeURIComponent(String(o))}`)}else t.push(`${encodeURIComponent(n)}=${encodeURIComponent(String(e))}`)}return t.join("&")}function T(r,t){if(t==null)return r;let n=C(t);if(n.length===0)return r;let e=r,o="",a=r.indexOf("#");if(a!==-1)e=r.slice(0,a),o=r.slice(a);let c=e.includes("?")?"&":"?";return`${e}${c}${n}${o}`}function E(r,t={}){let n=T(r,t.queryParams),e={..._,...t,headers:M(t.headers),url:n,method:t.method?.toUpperCase()??_.method,timeout:g(t.timeout??_.timeout),retryDelay:g(t.retryDelay??_.retryDelay),retry:typeof t.retry==="number"&&Number.isFinite(t.retry)?Math.max(1,Math.floor(t.retry)):_.retry};if(e.window??=null,e.cacheStrategy!=="network_only"&&(typeof caches>"u"||e.method!=="GET"&&e.method!=="HEAD"))e.cacheStrategy="network_only";if(e.removeDuplicate==="auto")e.removeDuplicate=typeof caches<"u"?"until_load":"always";if(t.bodyJson!=null)e.body=JSON.stringify(t.bodyJson),e.headers["content-type"]=S.JSON;if(t.bearerToken!=null)e.headers.authorization=`Bearer ${t.bearerToken}`;else if(t.alwatrAuth!=null)e.headers.authorization=`Alwatr ${t.alwatrAuth.userId}:${t.alwatrAuth.userToken}`;return e}import{delay as b}from"@alwatr/delay";import{getGlobalThis as v}from"@alwatr/global-this";import{HttpStatusCodes as y}from"@alwatr/http-primer";import{getGlobalThis as x}from"@alwatr/global-this";var w=x();function d(r){let t=r.signal;if(t?.aborted)return Promise.reject(new s("aborted","The operation was aborted"));if(r.timeout===0)return w.fetch(r.url,r);return new Promise((n,e)=>{let o=typeof AbortController==="function"?new AbortController:null,a;if(o!==null){if(r.signal=o.signal,t!=null)a=()=>{o.abort(t.reason)},t.addEventListener("abort",a,{once:!0})}let c=!1,p=setTimeout(()=>{c=!0,o?.abort("fetch_timeout"),e(new s("timeout","fetch_timeout"))},r.timeout);w.fetch(r.url,r).then((u)=>{if(!c)n(u)}).catch((u)=>{if(c)return;if(t?.aborted||u instanceof Error&&u.name==="AbortError")e(new s("aborted","The operation was aborted"));else e(u)}).finally(()=>{if(clearTimeout(p),r.signal=t,t!=null&&a!=null)t.removeEventListener("abort",a)})})}var D=v();function I(r){return r>=y.Error_Server_500_Internal_Server_Error||r===y.Error_Client_408_Request_Timeout||r===y.Error_Client_429_Too_Many_Requests}function P(r){let t=r?.headers?.get("retry-after");if(!t)return;let n=Number(t);if(!isNaN(n)&&n>0)return n*1000;let e=Date.parse(t);if(!isNaN(e)){let o=e-Date.now();return o>0?o:0}return}async function h(r){if(r.retry<=1)return d(r);r.retry--;let t;try{if(t=await d(r),t.ok||!I(t.status))return t}catch(e){if(r.signal?.aborted||e instanceof s&&e.reason==="aborted")throw e;if(D.navigator?.onLine===!1)throw e;return await b.by(r.retryDelay),h(r)}if(D.navigator?.onLine===!1)return t;let n=P(t)??r.retryDelay;return await b.by(n),h(r)}var f=new Map;function V(r){let t=typeof r.body==="string"?r.body:"",n=r.headers.authorization??"";return`${r.method} ${r.url} [auth:${n}] [body:${t}]`}async function l(r){if(r.removeDuplicate==="never")return h(r);let t=V(r),n=f.get(t);if(n==null)n=h(r),f.set(t,n);try{let e=await n;if(!e.ok||r.removeDuplicate==="until_load")f.delete(t);return e.clone()}catch(e){throw f.delete(t),e}}import{delay as A}from"@alwatr/delay";async function O(r){if(r.cacheStrategy==="network_only")return l(r);let t;try{t=await caches.open(r.cacheStorageName)}catch(e){return r.cacheStrategy="network_only",l(r)}let n=new Request(r.url,r);switch(r.cacheStrategy){case"cache_first":{try{let o=await t.match(n);if(o!=null)return o}catch(o){}let e=await l(r);if(e.ok)try{await t.put(n,e.clone())}catch{}return e}case"cache_only":{let e;try{e=await t.match(n)}catch(o){}if(e==null)throw new s("cache_not_found","Resource not found in cache");return e}case"network_first":try{let e=await l(r);if(e.ok)try{await t.put(n,e.clone())}catch{}return e}catch(e){try{let o=await t.match(n);if(o!=null)return o}catch{}throw e}case"update_cache":{let e=await l(r);if(e.ok)try{await t.put(n,e.clone())}catch{}return e}case"stale_while_revalidate":{let e;try{e=await t.match(n)}catch{}let o=l(r).then(async(a)=>{if(a.ok){try{await t.put(n,a.clone())}catch{}if(typeof r.revalidateCallback==="function"){let c=r.revalidateCallback,p=a.clone();await A.nextMacrotask();try{await c(p)}catch(u){}}}return a});return e??o}default:return l(r)}}async function R(r,t={}){let n=E(r,t);try{let e=await O(n);if(!e.ok){let o=m(e.status);throw new s(o,`HTTP error! status: ${e.status} ${e.statusText}`,e)}return[e,null]}catch(e){let o;if(e instanceof s){if(o=e,o.response!=null&&o.data==null){let a=await o.response.text().catch(()=>"");if(a.trim().length>0)try{o.data=JSON.parse(a)}catch{o.data=a}}}else if(e instanceof Error)if(e.name==="AbortError")o=new s("aborted",e.message);else o=new s("network_error",e.message);else o=new s("unknown_error",String(e??"unknown_error"));return[null,o]}}async function J(r,t={}){let[n,e]=await R(r,t);if(e)return[null,e];let o=await n.text().catch(()=>"");if(o.trim().length===0)return[null,new s("json_parse_error","Response body is empty, cannot parse JSON",n,o)];try{let a=JSON.parse(o);if(t.requireJsonResponseWithOkTrue&&(typeof a!=="object"||a===null||a.ok!==!0))return[null,new s("json_response_error",'Response JSON "ok" property is not true',n,a)];return[a,null]}catch(a){return[null,new s("json_parse_error",a instanceof Error?a.message:"Failed to parse JSON response",n,o)]}}J.version=R.version="10.1.1";export{s as FetchError,R as fetch,J as fetchJson,m as httpStatusToErrorReason};
3
3
 
4
- //# debugId=F20B725A9BE69DAA64756E2164756E21
4
+ //# debugId=CB669A3FF161DEFF64756E2164756E21
5
5
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -3,14 +3,14 @@
3
3
  "sources": ["../src/error.ts", "../src/options.ts", "../src/retry.ts", "../src/timeout.ts", "../src/dedupe.ts", "../src/cache.ts", "../src/fetch.ts"],
4
4
  "sourcesContent": [
5
5
  "import {HttpStatusCodes} from '@alwatr/http-primer';\nimport type {FetchErrorReason} from './type.js';\n\n/**\n * Maps an HTTP status code to a semantic `FetchErrorReason`.\n *\n * @param status - The HTTP response status code.\n * @returns The mapped `FetchErrorReason`.\n *\n * @example\n * ```typescript\n * httpStatusToErrorReason(401); // 'unauthorized'\n * httpStatusToErrorReason(404); // 'not_found'\n * httpStatusToErrorReason(500); // 'server_error'\n * ```\n */\nexport function httpStatusToErrorReason(status: number): FetchErrorReason {\n switch (status) {\n case HttpStatusCodes.Error_Client_400_Bad_Request:\n return 'bad_request';\n case HttpStatusCodes.Error_Client_401_Unauthorized:\n return 'unauthorized';\n case HttpStatusCodes.Error_Client_403_Forbidden:\n return 'forbidden';\n case HttpStatusCodes.Error_Client_404_Not_Found:\n return 'not_found';\n case HttpStatusCodes.Error_Client_408_Request_Timeout:\n return 'request_timeout';\n case HttpStatusCodes.Error_Client_409_Conflict:\n return 'conflict';\n case HttpStatusCodes.Error_Client_413_Payload_Too_Large:\n return 'payload_too_large';\n case HttpStatusCodes.Error_Client_422_Unprocessable_Entity:\n return 'unprocessable_content';\n case HttpStatusCodes.Error_Client_429_Too_Many_Requests:\n return 'rate_limited';\n default:\n if (status >= 500 && status < 600) {\n return 'server_error';\n }\n return 'http_error';\n }\n}\n\n/**\n * Custom error class for fetch-related failures.\n *\n * This error is returned in the `[null, FetchError]` tuple when a request fails.\n * It enriches the standard `Error` with the `response`, the parsed `data` body,\n * and the specific `reason` enum.\n *\n * @example\n * ```typescript\n * const [response, error] = await fetch('/api/endpoint');\n * if (error) {\n * if (error.reason === 'unauthorized') {\n * redirectToLogin();\n * } else if (error.reason === 'server_error') {\n * showToast('Server unavailable, please try again later');\n * }\n * }\n * ```\n */\nexport class FetchError extends Error {\n /**\n * The original `Response` object, if one was received.\n */\n public response?: Response;\n\n /**\n * The parsed body of the error response, if available (JSON object, string, etc.).\n */\n public data?: unknown;\n\n /**\n * The specific semantic reason for the fetch failure.\n */\n public reason: FetchErrorReason;\n\n /**\n * Helper getter for the HTTP status code.\n */\n get status(): number | undefined {\n return this.response?.status;\n }\n\n /**\n * Always `false` to indicate error status.\n */\n readonly ok: false = false;\n\n constructor(reason: FetchErrorReason, message: string, response?: Response, data?: unknown) {\n super(message);\n this.name = 'FetchError';\n this.reason = reason;\n this.response = response;\n this.data = data;\n }\n}\n",
6
- "import {MimeTypes, type HttpMethod} from '@alwatr/http-primer';\nimport {createLogger} from '@alwatr/logger';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {parseDuration} from '@alwatr/parse-duration';\n\nimport type {AlwatrFetchOptions_, FetchOptions, InternalFetchOptions_, QueryParams} from './type.js';\n\nexport const logger_ = createLogger('@alwatr/fetch');\n\nexport const globalThis_ = getGlobalThis();\n\n/**\n * Immutable default options for all fetch requests.\n */\nexport const defaultFetchOptions: Readonly<AlwatrFetchOptions_> = {\n method: 'GET',\n timeout: 8_000,\n retry: 3,\n retryDelay: 1_000,\n removeDuplicate: 'never',\n cacheStrategy: 'network_only',\n cacheStorageName: 'fetch_cache',\n // headers: {}, // --- IGNORED ---\n};\n\n/**\n * Normalizes any standard `HeadersInit` into a fresh, isolated lowercase string record.\n *\n * @param headers - User-provided headers (plain object, Headers instance, or entries array).\n * @param baseHeaders - Optional base headers to merge with the user-provided headers.\n * @returns An isolated `Record<string, string>`.\n */\nexport function normalizeHeaders_(\n headers?: HeadersInit,\n baseHeaders: Record<string, string> = {},\n): Record<string, string> {\n if (headers == null) {\n return baseHeaders;\n }\n\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n headers.forEach((value, key) => {\n baseHeaders[key.toLowerCase()] = value;\n });\n return baseHeaders;\n }\n\n if (Array.isArray(headers)) {\n for (const [key, value] of headers) {\n if (typeof key === 'string' && typeof value === 'string') {\n baseHeaders[key.toLowerCase()] = value;\n }\n }\n return baseHeaders;\n }\n\n if (typeof headers === 'object') {\n for (const key of Object.keys(headers)) {\n const val = (headers as Record<string, unknown>)[key];\n if (val != null) {\n baseHeaders[key.toLowerCase()] = String(val);\n }\n }\n }\n\n return baseHeaders;\n}\n\n/**\n * Serializes query parameters into a query string.\n *\n * @param queryParams - Dictionary of query parameters.\n * @returns Serialized URL query string (without leading `?` or `&`).\n */\nexport function serializeQueryParams_(queryParams: QueryParams): string {\n const parts: string[] = [];\n\n for (const key of Object.keys(queryParams)) {\n const value = queryParams[key];\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== null) {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);\n }\n }\n } else {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n }\n }\n\n return parts.join('&');\n}\n\n/**\n * Appends query parameters to a URL, correctly respecting existing query parameters and hash anchors.\n *\n * @param url - The target URL.\n * @param queryParams - Query parameters to append.\n * @returns The resulting URL string.\n */\nexport function appendQueryParams_(url: string, queryParams?: QueryParams): string {\n if (queryParams == null) {\n return url;\n }\n\n const queryString = serializeQueryParams_(queryParams);\n if (queryString.length === 0) {\n return url;\n }\n\n // Handle hash fragment if present in URL\n let baseUrl = url;\n let hashPart = '';\n const hashIndex = url.indexOf('#');\n\n if (hashIndex !== -1) {\n baseUrl = url.slice(0, hashIndex);\n hashPart = url.slice(hashIndex);\n }\n\n const separator = baseUrl.includes('?') ? '&' : '?';\n return `${baseUrl}${separator}${queryString}${hashPart}`;\n}\n\n/**\n * Processes, sanitizes, and normalizes user-provided fetch options into a complete, isolated options object.\n *\n * @param url - The target URL.\n * @param options - User-provided options.\n * @returns Internal, complete, and isolated fetch options.\n * @internal\n */\nexport function processOptions_(url: string, options: FetchOptions = {}): InternalFetchOptions_ {\n DEV_MODE && logger_.logMethod?.('processOptions_');\n\n const processedUrl = appendQueryParams_(url, options.queryParams);\n\n const options_: InternalFetchOptions_ = {\n ...defaultFetchOptions,\n ...options,\n headers: normalizeHeaders_(options.headers),\n url: processedUrl,\n method: (options.method?.toUpperCase() as HttpMethod) ?? defaultFetchOptions.method,\n timeout: parseDuration(options.timeout ?? defaultFetchOptions.timeout),\n retryDelay: parseDuration(options.retryDelay ?? defaultFetchOptions.retryDelay),\n retry:\n typeof options.retry === 'number' && Number.isFinite(options.retry) ?\n Math.max(1, Math.floor(options.retry))\n : defaultFetchOptions.retry,\n };\n\n options_.window ??= null;\n\n // Cache API Preconditions: requires Cache API runtime support and cacheable HTTP method (GET/HEAD)\n if (\n options_.cacheStrategy !== 'network_only'\n && (typeof caches === 'undefined' || (options_.method !== 'GET' && options_.method !== 'HEAD'))\n ) {\n DEV_MODE\n && logger_.incident?.('processOptions_', 'fetch_cache_strategy_unsupported', {\n method: options_.method,\n cacheStrategy: options_.cacheStrategy,\n hasCaches: typeof caches !== 'undefined',\n });\n options_.cacheStrategy = 'network_only';\n }\n\n // Deduplication auto selection\n if (options_.removeDuplicate === 'auto') {\n options_.removeDuplicate = typeof caches !== 'undefined' ? 'until_load' : 'always';\n }\n\n // JSON Body serialization\n if (options.bodyJson !== undefined) {\n options_.body = JSON.stringify(options.bodyJson);\n options_.headers['content-type'] = MimeTypes.JSON;\n }\n\n // Authorization header configuration\n if (options.bearerToken !== undefined) {\n options_.headers.authorization = `Bearer ${options.bearerToken}`;\n } else if (options.alwatrAuth !== undefined) {\n options_.headers.authorization = `Alwatr ${options.alwatrAuth.userId}:${options.alwatrAuth.userToken}`;\n }\n\n return options_;\n}\n",
6
+ "import {MimeTypes, type HttpMethod} from '@alwatr/http-primer';\nimport {createLogger} from '@alwatr/logger';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {parseDuration} from '@alwatr/parse-duration';\n\nimport type {AlwatrFetchOptions_, FetchOptions, InternalFetchOptions_, QueryParams} from './type.js';\n\nexport const logger_ = createLogger('@alwatr/fetch');\n\nexport const globalThis_ = getGlobalThis();\n\n/**\n * Immutable default options for all fetch requests.\n */\nexport const defaultFetchOptions: Readonly<AlwatrFetchOptions_> = {\n method: 'GET',\n timeout: 8_000,\n retry: 3,\n retryDelay: 1_000,\n removeDuplicate: 'never',\n cacheStrategy: 'network_only',\n cacheStorageName: 'fetch_cache',\n // headers: {}, // --- IGNORED ---\n};\n\n/**\n * Normalizes any standard `HeadersInit` into a fresh, isolated lowercase string record.\n *\n * @param headers - User-provided headers (plain object, Headers instance, or entries array).\n * @param baseHeaders - Optional base headers to merge with the user-provided headers.\n * @returns An isolated `Record<string, string>`.\n */\nexport function normalizeHeaders_(\n headers?: HeadersInit,\n baseHeaders: Record<string, string> = {},\n): Record<string, string> {\n if (headers == null) {\n return baseHeaders;\n }\n\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n headers.forEach((value, key) => {\n baseHeaders[key.toLowerCase()] = value;\n });\n return baseHeaders;\n }\n\n if (Array.isArray(headers)) {\n for (const [key, value] of headers) {\n if (typeof key === 'string' && typeof value === 'string') {\n baseHeaders[key.toLowerCase()] = value;\n }\n }\n return baseHeaders;\n }\n\n if (typeof headers === 'object') {\n for (const key of Object.keys(headers)) {\n const val = (headers as Record<string, unknown>)[key];\n if (val != null) {\n baseHeaders[key.toLowerCase()] = String(val);\n }\n }\n }\n\n return baseHeaders;\n}\n\n/**\n * Serializes query parameters into a query string.\n *\n * @param queryParams - Dictionary of query parameters.\n * @returns Serialized URL query string (without leading `?` or `&`).\n */\nexport function serializeQueryParams_(queryParams: QueryParams): string {\n const parts: string[] = [];\n\n for (const key of Object.keys(queryParams)) {\n const value = queryParams[key];\n if (value == null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item != null) {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);\n }\n }\n } else {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n }\n }\n\n return parts.join('&');\n}\n\n/**\n * Appends query parameters to a URL, correctly respecting existing query parameters and hash anchors.\n *\n * @param url - The target URL.\n * @param queryParams - Query parameters to append.\n * @returns The resulting URL string.\n */\nexport function appendQueryParams_(url: string, queryParams?: QueryParams): string {\n if (queryParams == null) {\n return url;\n }\n\n const queryString = serializeQueryParams_(queryParams);\n if (queryString.length === 0) {\n return url;\n }\n\n // Handle hash fragment if present in URL\n let baseUrl = url;\n let hashPart = '';\n const hashIndex = url.indexOf('#');\n\n if (hashIndex !== -1) {\n baseUrl = url.slice(0, hashIndex);\n hashPart = url.slice(hashIndex);\n }\n\n const separator = baseUrl.includes('?') ? '&' : '?';\n return `${baseUrl}${separator}${queryString}${hashPart}`;\n}\n\n/**\n * Processes, sanitizes, and normalizes user-provided fetch options into a complete, isolated options object.\n *\n * @param url - The target URL.\n * @param options - User-provided options.\n * @returns Internal, complete, and isolated fetch options.\n * @internal\n */\nexport function processOptions_(url: string, options: FetchOptions = {}): InternalFetchOptions_ {\n DEV_MODE && logger_.logMethod?.('processOptions_');\n\n const processedUrl = appendQueryParams_(url, options.queryParams);\n\n const options_: InternalFetchOptions_ = {\n ...defaultFetchOptions,\n ...options,\n headers: normalizeHeaders_(options.headers),\n url: processedUrl,\n method: (options.method?.toUpperCase() as HttpMethod) ?? defaultFetchOptions.method,\n timeout: parseDuration(options.timeout ?? defaultFetchOptions.timeout),\n retryDelay: parseDuration(options.retryDelay ?? defaultFetchOptions.retryDelay),\n retry:\n typeof options.retry === 'number' && Number.isFinite(options.retry) ?\n Math.max(1, Math.floor(options.retry))\n : defaultFetchOptions.retry,\n };\n\n options_.window ??= null;\n\n // Cache API Preconditions: requires Cache API runtime support and cacheable HTTP method (GET/HEAD)\n if (\n options_.cacheStrategy !== 'network_only'\n && (typeof caches === 'undefined' || (options_.method !== 'GET' && options_.method !== 'HEAD'))\n ) {\n DEV_MODE\n && logger_.incident?.('processOptions_', 'fetch_cache_strategy_unsupported', {\n method: options_.method,\n cacheStrategy: options_.cacheStrategy,\n hasCaches: typeof caches !== 'undefined',\n });\n options_.cacheStrategy = 'network_only';\n }\n\n // Deduplication auto selection\n if (options_.removeDuplicate === 'auto') {\n options_.removeDuplicate = typeof caches !== 'undefined' ? 'until_load' : 'always';\n }\n\n // JSON Body serialization\n if (options.bodyJson != null) {\n options_.body = JSON.stringify(options.bodyJson);\n options_.headers['content-type'] = MimeTypes.JSON;\n }\n\n // Authorization header configuration\n if (options.bearerToken != null) {\n options_.headers.authorization = `Bearer ${options.bearerToken}`;\n } else if (options.alwatrAuth != null) {\n options_.headers.authorization = `Alwatr ${options.alwatrAuth.userId}:${options.alwatrAuth.userToken}`;\n }\n\n return options_;\n}\n",
7
7
  "import {delay} from '@alwatr/delay';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {HttpStatusCodes} from '@alwatr/http-primer';\nimport {FetchError} from './error.js';\nimport {logger_} from './options.js';\nimport {handleTimeout_} from './timeout.js';\n\nimport type {InternalFetchOptions_} from './type.js';\n\nconst globalThis_ = getGlobalThis();\n\n/**\n * Checks whether an HTTP response status code is retryable.\n *\n * Retryable statuses:\n * - Any 5xx Server Error (500, 502, 503, 504, ...)\n * - 408 Request Timeout\n * - 429 Too Many Requests\n */\nexport function isRetryableStatus_(status: number): boolean {\n return (\n status >= HttpStatusCodes.Error_Server_500_Internal_Server_Error\n || status === HttpStatusCodes.Error_Client_408_Request_Timeout\n || status === HttpStatusCodes.Error_Client_429_Too_Many_Requests\n );\n}\n\n/**\n * Parses the `Retry-After` header value (in seconds or HTTP-date) if present.\n *\n * @param response - The HTTP Response object.\n * @returns Delay duration in milliseconds, or undefined if absent/invalid.\n */\nexport function parseRetryAfterHeader_(response?: Response): number | undefined {\n const retryAfter = response?.headers?.get('retry-after');\n if (!retryAfter) return undefined;\n\n const seconds = Number(retryAfter);\n if (!isNaN(seconds) && seconds > 0) {\n return seconds * 1000;\n }\n\n const dateMs = Date.parse(retryAfter);\n if (!isNaN(dateMs)) {\n const diff = dateMs - Date.now();\n return diff > 0 ? diff : 0;\n }\n\n return undefined;\n}\n\n/**\n * Executes a fetch request with automatic retries on transient errors (5xx, 429, 408, network failures, timeouts).\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to the final `Response` after retry cycles.\n * @internal\n */\nexport async function handleRetryPattern_(options: InternalFetchOptions_): Promise<Response> {\n if (options.retry <= 1) {\n return handleTimeout_(options);\n }\n\n DEV_MODE && logger_.logMethod?.('handleRetryPattern_');\n options.retry--;\n\n let response: Response;\n try {\n response = await handleTimeout_(options);\n\n if (response.ok || !isRetryableStatus_(response.status)) {\n return response;\n }\n } catch (err) {\n DEV_MODE && logger_.accident('fetch', 'fetch_failed_retry', err);\n\n // Never retry if the request was intentionally aborted\n if (options.signal?.aborted || (err instanceof FetchError && err.reason === 'aborted')) {\n throw err;\n }\n\n // Do not retry if the runtime is offline\n if (globalThis_.navigator?.onLine === false) {\n DEV_MODE && logger_.accident('handleRetryPattern_', 'offline', 'Skip retry because offline');\n throw err;\n }\n\n await delay.by(options.retryDelay);\n\n return handleRetryPattern_(options);\n }\n\n // Handle transient retryable HTTP status (5xx, 429, 408)\n DEV_MODE && logger_.accident('fetch', 'fetch_failed_retry', {status: response.status});\n\n if (globalThis_.navigator?.onLine === false) {\n DEV_MODE && logger_.accident('handleRetryPattern_', 'offline', 'Skip retry because offline');\n return response;\n }\n\n const retryDelay = parseRetryAfterHeader_(response) ?? options.retryDelay;\n\n await delay.by(retryDelay);\n\n return handleRetryPattern_(options);\n}\n",
8
- "import {getGlobalThis} from '@alwatr/global-this';\nimport {FetchError} from './error.js';\nimport {logger_} from './options.js';\n\nimport type {InternalFetchOptions_} from './type.js';\n\nconst globalThis_ = getGlobalThis();\n\n/**\n * Executes a native `fetch` wrapped with an `AbortController` timeout.\n *\n * Checks for pre-aborted external signals, respects external cancellation,\n * and guarantees listener and timer cleanup on completion.\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to the native `Response` or rejecting with `FetchError`.\n * @internal\n */\nexport function handleTimeout_(options: InternalFetchOptions_): Promise<Response> {\n const externalSignal = options.signal;\n\n // Immediate abort check: If signal is already aborted, reject immediately without network overhead\n if (externalSignal?.aborted) {\n DEV_MODE && logger_.incident?.('handleTimeout_', 'already_aborted', {reason: externalSignal.reason});\n return Promise.reject(new FetchError('aborted', 'The operation was aborted'));\n }\n\n // If timeout is disabled (0), invoke native fetch directly with external signal\n if (options.timeout === 0) {\n return globalThis_.fetch(options.url, options as RequestInit);\n }\n\n DEV_MODE && logger_.logMethod?.('handleTimeout_');\n\n return new Promise((resolve, reject) => {\n const abortController = typeof AbortController === 'function' ? new AbortController() : null;\n\n let onExternalAbort: (() => void) | undefined;\n\n if (abortController !== null) {\n options.signal = abortController.signal;\n\n if (externalSignal != null) {\n onExternalAbort = () => {\n abortController.abort(externalSignal.reason);\n };\n externalSignal.addEventListener('abort', onExternalAbort, {once: true});\n }\n }\n\n let timeoutFired = false;\n\n const timeoutId = setTimeout(() => {\n timeoutFired = true;\n abortController?.abort('fetch_timeout');\n reject(new FetchError('timeout', 'fetch_timeout'));\n }, options.timeout);\n\n globalThis_\n .fetch(options.url, options as RequestInit)\n .then((response) => {\n if (!timeoutFired) {\n resolve(response);\n }\n })\n .catch((err: unknown) => {\n if (timeoutFired) {\n return;\n }\n\n if (externalSignal?.aborted || (err instanceof Error && err.name === 'AbortError')) {\n reject(new FetchError('aborted', 'The operation was aborted'));\n } else {\n reject(err);\n }\n })\n .finally(() => {\n clearTimeout(timeoutId);\n options.signal = externalSignal;\n if (externalSignal != null && onExternalAbort !== undefined) {\n externalSignal.removeEventListener('abort', onExternalAbort);\n }\n });\n });\n}\n",
8
+ "import {getGlobalThis} from '@alwatr/global-this';\nimport {FetchError} from './error.js';\nimport {logger_} from './options.js';\n\nimport type {InternalFetchOptions_} from './type.js';\n\nconst globalThis_ = getGlobalThis();\n\n/**\n * Executes a native `fetch` wrapped with an `AbortController` timeout.\n *\n * Checks for pre-aborted external signals, respects external cancellation,\n * and guarantees listener and timer cleanup on completion.\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to the native `Response` or rejecting with `FetchError`.\n * @internal\n */\nexport function handleTimeout_(options: InternalFetchOptions_): Promise<Response> {\n const externalSignal = options.signal;\n\n // Immediate abort check: If signal is already aborted, reject immediately without network overhead\n if (externalSignal?.aborted) {\n DEV_MODE && logger_.incident?.('handleTimeout_', 'already_aborted', {reason: externalSignal.reason});\n return Promise.reject(new FetchError('aborted', 'The operation was aborted'));\n }\n\n // If timeout is disabled (0), invoke native fetch directly with external signal\n if (options.timeout === 0) {\n return globalThis_.fetch(options.url, options as RequestInit);\n }\n\n DEV_MODE && logger_.logMethod?.('handleTimeout_');\n\n return new Promise((resolve, reject) => {\n const abortController = typeof AbortController === 'function' ? new AbortController() : null;\n\n let onExternalAbort: (() => void) | undefined;\n\n if (abortController !== null) {\n options.signal = abortController.signal;\n\n if (externalSignal != null) {\n onExternalAbort = () => {\n abortController.abort(externalSignal.reason);\n };\n externalSignal.addEventListener('abort', onExternalAbort, {once: true});\n }\n }\n\n let timeoutFired = false;\n\n const timeoutId = setTimeout(() => {\n timeoutFired = true;\n abortController?.abort('fetch_timeout');\n reject(new FetchError('timeout', 'fetch_timeout'));\n }, options.timeout);\n\n globalThis_\n .fetch(options.url, options as RequestInit)\n .then((response) => {\n if (!timeoutFired) {\n resolve(response);\n }\n })\n .catch((err: unknown) => {\n if (timeoutFired) {\n return;\n }\n\n if (externalSignal?.aborted || (err instanceof Error && err.name === 'AbortError')) {\n reject(new FetchError('aborted', 'The operation was aborted'));\n } else {\n reject(err);\n }\n })\n .finally(() => {\n clearTimeout(timeoutId);\n options.signal = externalSignal;\n if (externalSignal != null && onExternalAbort != null) {\n externalSignal.removeEventListener('abort', onExternalAbort);\n }\n });\n });\n}\n",
9
9
  "import {logger_} from './options.js';\nimport {handleRetryPattern_} from './retry.js';\n\nimport type {InternalFetchOptions_} from './type.js';\n\n/**\n * Storage for tracking in-flight duplicate requests.\n */\nconst duplicateRequestStorage_: Map<string, Promise<Response>> = new Map();\n\n/**\n * Computes a secure cache key for request deduplication.\n * Includes method, full URL, authorization header, and request body.\n *\n * @param options - Processed internal fetch options.\n * @returns Unique string identifier for the request intent.\n */\nexport function computeDedupeKey_(options: InternalFetchOptions_): string {\n const bodyString = typeof options.body === 'string' ? options.body : '';\n const auth = options.headers['authorization'] ?? '';\n return `${options.method} ${options.url} [auth:${auth}] [body:${bodyString}]`;\n}\n\n/**\n * Handles duplicate parallel request coalescing.\n *\n * If an identical request is already in-flight, returns a cloned response of the existing\n * promise to avoid redundant network round-trips.\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to an independent cloned `Response`.\n * @internal\n */\nexport async function handleRemoveDuplicate_(options: InternalFetchOptions_): Promise<Response> {\n if (options.removeDuplicate === 'never') {\n return handleRetryPattern_(options);\n }\n\n DEV_MODE && logger_.logMethod?.('handleRemoveDuplicate_');\n\n const cacheKey = computeDedupeKey_(options);\n\n let requestAsync = duplicateRequestStorage_.get(cacheKey);\n if (requestAsync == null) {\n requestAsync = handleRetryPattern_(options);\n duplicateRequestStorage_.set(cacheKey, requestAsync);\n }\n\n try {\n const response = await requestAsync;\n\n // Clean up stored promise for 'until_load' or failed responses\n if (!response.ok || options.removeDuplicate === 'until_load') {\n duplicateRequestStorage_.delete(cacheKey);\n }\n\n // Return a clone so every concurrent caller can independently consume the body\n return response.clone();\n } catch (err) {\n // If request failed, remove from storage immediately\n duplicateRequestStorage_.delete(cacheKey);\n throw err;\n }\n}\n",
10
10
  "import {FetchError} from './error.js';\nimport {handleRemoveDuplicate_} from './dedupe.js';\nimport {logger_} from './options.js';\nimport {delay} from '@alwatr/delay';\n\nimport type {InternalFetchOptions_} from './type.js';\n\n/**\n * Executes the caching lifecycle according to `cacheStrategy`.\n *\n * Interacts safely with Cache API:\n * - Falls back to network when Cache API is unavailable or throws.\n * - Guards against caching non-GET requests.\n * - Clones responses before storing to keep response bodies consumable.\n *\n * @param options - Processed internal fetch options.\n * @returns A promise resolving to a cached or freshly fetched `Response`.\n * @internal\n */\nexport async function handleCacheStrategy_(options: InternalFetchOptions_): Promise<Response> {\n if (options.cacheStrategy === 'network_only') {\n return handleRemoveDuplicate_(options);\n }\n\n DEV_MODE && logger_.logMethod?.('handleCacheStrategy_');\n\n let cacheStorage: Cache;\n try {\n cacheStorage = await caches.open(options.cacheStorageName);\n } catch (err) {\n DEV_MODE && logger_.accident('handleCacheStrategy_', 'cache_open_failed', {err});\n options.cacheStrategy = 'network_only';\n return handleRemoveDuplicate_(options);\n }\n\n const request = new Request(options.url, options);\n\n switch (options.cacheStrategy) {\n case 'cache_first': {\n try {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse != null) {\n return cachedResponse;\n }\n } catch (err) {\n DEV_MODE && logger_.accident('handleCacheStrategy_', 'cache_match_failed', {err});\n }\n\n const response = await handleRemoveDuplicate_(options);\n if (response.ok) {\n try {\n await cacheStorage.put(request, response.clone());\n } catch {\n // ignore cache put failures\n }\n }\n return response;\n }\n\n case 'cache_only': {\n let cachedResponse: Response | undefined;\n try {\n cachedResponse = await cacheStorage.match(request);\n } catch (err) {\n DEV_MODE && logger_.accident('handleCacheStrategy_', 'cache_only_match_failed', {err});\n }\n\n if (cachedResponse == null) {\n throw new FetchError('cache_not_found', 'Resource not found in cache');\n }\n return cachedResponse;\n }\n\n case 'network_first': {\n try {\n const networkResponse = await handleRemoveDuplicate_(options);\n if (networkResponse.ok) {\n try {\n await cacheStorage.put(request, networkResponse.clone());\n } catch {\n // ignore cache put failures\n }\n }\n return networkResponse;\n } catch (err) {\n try {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse != null) {\n return cachedResponse;\n }\n } catch {\n // ignore cache match error and throw original error\n }\n throw err;\n }\n }\n\n case 'update_cache': {\n const networkResponse = await handleRemoveDuplicate_(options);\n if (networkResponse.ok) {\n try {\n await cacheStorage.put(request, networkResponse.clone());\n } catch {\n // ignore cache put failures\n }\n }\n return networkResponse;\n }\n\n case 'stale_while_revalidate': {\n let cachedResponse: Response | undefined;\n try {\n cachedResponse = await cacheStorage.match(request);\n } catch {\n // ignore cache match error\n }\n\n const fetchedResponsePromise = handleRemoveDuplicate_(options).then(async (networkResponse) => {\n if (networkResponse.ok) {\n try {\n await cacheStorage.put(request, networkResponse.clone());\n } catch {\n // ignore cache put failures\n }\n if (typeof options.revalidateCallback === 'function') {\n const callback = options.revalidateCallback;\n const revalidatePayload = networkResponse.clone();\n await delay.nextMacrotask();\n try {\n await callback(revalidatePayload);\n } catch (err) {\n DEV_MODE && logger_.accident('handleCacheStrategy_', 'revalidate_callback_failed', {err});\n }\n }\n }\n return networkResponse;\n });\n\n return cachedResponse ?? fetchedResponsePromise;\n }\n\n default: {\n return handleRemoveDuplicate_(options);\n }\n }\n}\n",
11
- "import {FetchError, httpStatusToErrorReason} from './error.js';\nimport {handleCacheStrategy_} from './cache.js';\nimport {processOptions_, logger_} from './options.js';\n\nimport type {FetchJsonOptions, FetchJsonResponse, FetchOptions, FetchResponse} from './type.js';\n\n/**\n * An enhanced wrapper for the native `fetch` function.\n *\n * Provides:\n * - **Deterministic Errors**: Semantic `FetchError` reasons (e.g. `unauthorized`, `forbidden`, `not_found`, `server_error`, `timeout`, `aborted`, `rate_limited`).\n * - **Go-Style Tuple Return**: Never throws, returns `[response, null]` on success or `[null, FetchError]` on failure.\n * - **Automatic Timeout**: Aborts the request if it exceeds `timeout` duration.\n * - **Configurable Retry**: Automatically retries transient 5xx, 429, 408, or network errors with `retryDelay` and `Retry-After` support.\n * - **Parallel Deduplication**: Collapses identical concurrent in-flight requests.\n * - **Cache Strategies**: Integrates with Cache API (`cache_first`, `stale_while_revalidate`, etc.).\n * - **Isolated Headers & Query Params**: Safely formats query parameters and authorization credentials without mutating caller objects.\n *\n * @param url - The URL to fetch.\n * @param options - Configuration options for the fetch request.\n * @returns A promise resolving to `[Response, null]` on success, or `[null, FetchError]` on failure.\n *\n * @example\n * ```typescript\n * import {fetch} from '@alwatr/fetch';\n *\n * const [response, error] = await fetch('/api/products', {\n * queryParams: { limit: 10 },\n * timeout: '5s',\n * });\n *\n * if (error) {\n * if (error.reason === 'not_found') {\n * console.warn('Product not found');\n * }\n * return;\n * }\n *\n * const data = await response.json();\n * ```\n */\nexport async function fetch(url: string, options: FetchOptions = {}): Promise<FetchResponse> {\n const options_ = processOptions_(url, options);\n DEV_MODE && logger_.logMethodArgs?.('fetch', options_);\n\n try {\n const response = await handleCacheStrategy_(options_);\n\n if (!response.ok) {\n const reason = httpStatusToErrorReason(response.status);\n throw new FetchError(reason, `HTTP error! status: ${response.status} ${response.statusText}`, response);\n }\n\n return [response, null];\n } catch (err) {\n let error: FetchError;\n\n if (err instanceof FetchError) {\n error = err;\n\n if (error.response !== undefined && error.data === undefined) {\n const bodyText = await error.response.text().catch(() => '');\n\n if (bodyText.trim().length > 0) {\n try {\n error.data = JSON.parse(bodyText);\n } catch {\n error.data = bodyText;\n }\n }\n }\n } else if (err instanceof Error) {\n if (err.name === 'AbortError') {\n error = new FetchError('aborted', err.message);\n } else {\n error = new FetchError('network_error', err.message);\n }\n } else {\n error = new FetchError('unknown_error', String(err ?? 'unknown_error'));\n }\n\n DEV_MODE && logger_.accident('fetch', error.reason, {error});\n return [null, error];\n }\n}\n\n/**\n * An enhanced wrapper for `fetch` that automatically parses JSON responses.\n *\n * Accepts unconstrained generic interfaces, DTOs, and arrays without requiring index signatures.\n *\n * @template T - The expected type of the JSON response payload.\n *\n * @param url - The URL to fetch.\n * @param options - Configuration options for the fetch request.\n * @returns A promise resolving to `[data, null]` where data is typed as `T`, or `[null, FetchError]`.\n *\n * @example\n * ```typescript\n * import {fetchJson} from '@alwatr/fetch';\n *\n * interface User {\n * id: string;\n * name: string;\n * }\n *\n * const [users, error] = await fetchJson<User[]>('/api/users');\n * if (error) {\n * console.error('Failed to load users:', error.reason);\n * return;\n * }\n * console.log('Users count:', users.length);\n * ```\n */\nexport async function fetchJson<T = unknown>(\n url: string,\n options: FetchJsonOptions = {},\n): Promise<FetchJsonResponse<T>> {\n DEV_MODE && logger_.logMethod?.('fetchJson');\n\n const [response, error] = await fetch(url, options);\n\n if (error) {\n return [null, error];\n }\n\n const bodyText = await response.text().catch(() => '');\n if (bodyText.trim().length === 0) {\n const parseError = new FetchError(\n 'json_parse_error',\n 'Response body is empty, cannot parse JSON',\n response,\n bodyText,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n\n try {\n const data = JSON.parse(bodyText) as T;\n\n if (\n options.requireJsonResponseWithOkTrue\n && (typeof data !== 'object' || data === null || (data as Record<string, unknown>).ok !== true)\n ) {\n const parseError = new FetchError(\n 'json_response_error',\n 'Response JSON \"ok\" property is not true',\n response,\n data,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n\n return [data, null];\n } catch (err) {\n const parseError = new FetchError(\n 'json_parse_error',\n err instanceof Error ? err.message : 'Failed to parse JSON response',\n response,\n bodyText,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n}\n\nfetchJson.version = fetch.version = __package_version__;\n"
11
+ "import {FetchError, httpStatusToErrorReason} from './error.js';\nimport {handleCacheStrategy_} from './cache.js';\nimport {processOptions_, logger_} from './options.js';\n\nimport type {FetchJsonOptions, FetchJsonResponse, FetchOptions, FetchResponse} from './type.js';\n\n/**\n * An enhanced wrapper for the native `fetch` function.\n *\n * Provides:\n * - **Deterministic Errors**: Semantic `FetchError` reasons (e.g. `unauthorized`, `forbidden`, `not_found`, `server_error`, `timeout`, `aborted`, `rate_limited`).\n * - **Go-Style Tuple Return**: Never throws, returns `[response, null]` on success or `[null, FetchError]` on failure.\n * - **Automatic Timeout**: Aborts the request if it exceeds `timeout` duration.\n * - **Configurable Retry**: Automatically retries transient 5xx, 429, 408, or network errors with `retryDelay` and `Retry-After` support.\n * - **Parallel Deduplication**: Collapses identical concurrent in-flight requests.\n * - **Cache Strategies**: Integrates with Cache API (`cache_first`, `stale_while_revalidate`, etc.).\n * - **Isolated Headers & Query Params**: Safely formats query parameters and authorization credentials without mutating caller objects.\n *\n * @param url - The URL to fetch.\n * @param options - Configuration options for the fetch request.\n * @returns A promise resolving to `[Response, null]` on success, or `[null, FetchError]` on failure.\n *\n * @example\n * ```typescript\n * import {fetch} from '@alwatr/fetch';\n *\n * const [response, error] = await fetch('/api/products', {\n * queryParams: { limit: 10 },\n * timeout: '5s',\n * });\n *\n * if (error) {\n * if (error.reason === 'not_found') {\n * console.warn('Product not found');\n * }\n * return;\n * }\n *\n * const data = await response.json();\n * ```\n */\nexport async function fetch(url: string, options: FetchOptions = {}): Promise<FetchResponse> {\n const options_ = processOptions_(url, options);\n DEV_MODE && logger_.logMethodArgs?.('fetch', options_);\n\n try {\n const response = await handleCacheStrategy_(options_);\n\n if (!response.ok) {\n const reason = httpStatusToErrorReason(response.status);\n throw new FetchError(reason, `HTTP error! status: ${response.status} ${response.statusText}`, response);\n }\n\n return [response, null];\n } catch (err) {\n let error: FetchError;\n\n if (err instanceof FetchError) {\n error = err;\n\n if (error.response != null && error.data == null) {\n const bodyText = await error.response.text().catch(() => '');\n\n if (bodyText.trim().length > 0) {\n try {\n error.data = JSON.parse(bodyText);\n } catch {\n error.data = bodyText;\n }\n }\n }\n } else if (err instanceof Error) {\n if (err.name === 'AbortError') {\n error = new FetchError('aborted', err.message);\n } else {\n error = new FetchError('network_error', err.message);\n }\n } else {\n error = new FetchError('unknown_error', String(err ?? 'unknown_error'));\n }\n\n DEV_MODE && logger_.accident('fetch', error.reason, {error});\n return [null, error];\n }\n}\n\n/**\n * An enhanced wrapper for `fetch` that automatically parses JSON responses.\n *\n * Accepts unconstrained generic interfaces, DTOs, and arrays without requiring index signatures.\n *\n * @template T - The expected type of the JSON response payload.\n *\n * @param url - The URL to fetch.\n * @param options - Configuration options for the fetch request.\n * @returns A promise resolving to `[data, null]` where data is typed as `T`, or `[null, FetchError]`.\n *\n * @example\n * ```typescript\n * import {fetchJson} from '@alwatr/fetch';\n *\n * interface User {\n * id: string;\n * name: string;\n * }\n *\n * const [users, error] = await fetchJson<User[]>('/api/users');\n * if (error) {\n * console.error('Failed to load users:', error.reason);\n * return;\n * }\n * console.log('Users count:', users.length);\n * ```\n */\nexport async function fetchJson<T = unknown>(\n url: string,\n options: FetchJsonOptions = {},\n): Promise<FetchJsonResponse<T>> {\n DEV_MODE && logger_.logMethod?.('fetchJson');\n\n const [response, error] = await fetch(url, options);\n\n if (error) {\n return [null, error];\n }\n\n const bodyText = await response.text().catch(() => '');\n if (bodyText.trim().length === 0) {\n const parseError = new FetchError(\n 'json_parse_error',\n 'Response body is empty, cannot parse JSON',\n response,\n bodyText,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n\n try {\n const data = JSON.parse(bodyText) as T;\n\n if (\n options.requireJsonResponseWithOkTrue\n && (typeof data !== 'object' || data === null || (data as Record<string, unknown>).ok !== true)\n ) {\n const parseError = new FetchError(\n 'json_response_error',\n 'Response JSON \"ok\" property is not true',\n response,\n data,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n\n return [data, null];\n } catch (err) {\n const parseError = new FetchError(\n 'json_parse_error',\n err instanceof Error ? err.message : 'Failed to parse JSON response',\n response,\n bodyText,\n );\n DEV_MODE && logger_.accident('fetchJson', parseError.reason, {error: parseError});\n return [null, parseError];\n }\n}\n\nfetchJson.version = fetch.version = __package_version__;\n"
12
12
  ],
13
- "mappings": "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",
14
- "debugId": "F20B725A9BE69DAA64756E2164756E21",
13
+ "mappings": "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",
14
+ "debugId": "CB669A3FF161DEFF64756E2164756E21",
15
15
  "names": []
16
16
  }
package/dist/type.d.ts CHANGED
@@ -89,14 +89,14 @@ export interface AlwatrFetchOptions_ {
89
89
  /**
90
90
  * A bearer token to be added to the 'Authorization' header.
91
91
  */
92
- bearerToken?: string;
92
+ bearerToken?: string | null;
93
93
  /**
94
94
  * Alwatr-specific authentication credentials.
95
95
  */
96
96
  alwatrAuth?: {
97
97
  userId: string;
98
98
  userToken: string;
99
- };
99
+ } | null;
100
100
  }
101
101
  /**
102
102
  * Combined type for fetch options, including standard RequestInit properties.
@@ -1 +1 @@
1
- {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alwatr/fetch",
3
- "version": "10.1.0",
3
+ "version": "10.1.1",
4
4
  "description": "`@alwatr/fetch` is an enhanced, lightweight, and dependency-free wrapper for the native `fetch` API. It provides modern features like caching strategies, request retries, timeouts, and intelligent duplicate request handling, all in a compact package.",
5
5
  "license": "MPL-2.0",
6
6
  "author": "S. Ali Mihandoost <ali.mihandoost@gmail.com> (https://ali.mihandoost.com)",
@@ -84,5 +84,5 @@
84
84
  "utility",
85
85
  "utils"
86
86
  ],
87
- "gitHead": "b9efc218052a99652c3cb0bc990496f26b5b18cf"
87
+ "gitHead": "7e2e248f48b2b6ce8b9a71efdf8eb65de52697df"
88
88
  }
package/src/fetch.ts CHANGED
@@ -58,7 +58,7 @@ export async function fetch(url: string, options: FetchOptions = {}): Promise<Fe
58
58
  if (err instanceof FetchError) {
59
59
  error = err;
60
60
 
61
- if (error.response !== undefined && error.data === undefined) {
61
+ if (error.response != null && error.data == null) {
62
62
  const bodyText = await error.response.text().catch(() => '');
63
63
 
64
64
  if (bodyText.trim().length > 0) {
package/src/options.ts CHANGED
@@ -77,13 +77,13 @@ export function serializeQueryParams_(queryParams: QueryParams): string {
77
77
 
78
78
  for (const key of Object.keys(queryParams)) {
79
79
  const value = queryParams[key];
80
- if (value === undefined || value === null) {
80
+ if (value == null) {
81
81
  continue;
82
82
  }
83
83
 
84
84
  if (Array.isArray(value)) {
85
85
  for (const item of value) {
86
- if (item !== undefined && item !== null) {
86
+ if (item != null) {
87
87
  parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);
88
88
  }
89
89
  }
@@ -175,15 +175,15 @@ export function processOptions_(url: string, options: FetchOptions = {}): Intern
175
175
  }
176
176
 
177
177
  // JSON Body serialization
178
- if (options.bodyJson !== undefined) {
178
+ if (options.bodyJson != null) {
179
179
  options_.body = JSON.stringify(options.bodyJson);
180
180
  options_.headers['content-type'] = MimeTypes.JSON;
181
181
  }
182
182
 
183
183
  // Authorization header configuration
184
- if (options.bearerToken !== undefined) {
184
+ if (options.bearerToken != null) {
185
185
  options_.headers.authorization = `Bearer ${options.bearerToken}`;
186
- } else if (options.alwatrAuth !== undefined) {
186
+ } else if (options.alwatrAuth != null) {
187
187
  options_.headers.authorization = `Alwatr ${options.alwatrAuth.userId}:${options.alwatrAuth.userToken}`;
188
188
  }
189
189
 
package/src/timeout.ts CHANGED
@@ -77,7 +77,7 @@ export function handleTimeout_(options: InternalFetchOptions_): Promise<Response
77
77
  .finally(() => {
78
78
  clearTimeout(timeoutId);
79
79
  options.signal = externalSignal;
80
- if (externalSignal != null && onExternalAbort !== undefined) {
80
+ if (externalSignal != null && onExternalAbort != null) {
81
81
  externalSignal.removeEventListener('abort', onExternalAbort);
82
82
  }
83
83
  });
package/src/type.ts CHANGED
@@ -112,7 +112,7 @@ export interface AlwatrFetchOptions_ {
112
112
  /**
113
113
  * A bearer token to be added to the 'Authorization' header.
114
114
  */
115
- bearerToken?: string;
115
+ bearerToken?: string | null;
116
116
 
117
117
  /**
118
118
  * Alwatr-specific authentication credentials.
@@ -120,7 +120,7 @@ export interface AlwatrFetchOptions_ {
120
120
  alwatrAuth?: {
121
121
  userId: string;
122
122
  userToken: string;
123
- };
123
+ } | null;
124
124
  }
125
125
 
126
126
  /**
@@ -203,7 +203,8 @@ export type FetchErrorReason =
203
203
  * @internal
204
204
  */
205
205
  export interface InternalFetchOptions_
206
- extends Omit<AlwatrFetchOptions_, 'headers' | 'method' | 'timeout' | 'retryDelay'>,
206
+ extends
207
+ Omit<AlwatrFetchOptions_, 'headers' | 'method' | 'timeout' | 'retryDelay'>,
207
208
  Omit<RequestInit, 'headers' | 'method'> {
208
209
  url: string;
209
210
  method: HttpMethod;