@alwatr/fetch 6.0.11 → 6.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [6.0.12](https://github.com/Alwatr/nanolib/compare/@alwatr/fetch@6.0.11...@alwatr/fetch@6.0.12) (2025-09-21)
7
+
8
+ **Note:** Version bump only for package @alwatr/fetch
9
+
6
10
  ## [6.0.11](https://github.com/Alwatr/nanolib/compare/@alwatr/fetch@6.0.10...@alwatr/fetch@6.0.11) (2025-09-20)
7
11
 
8
12
  ### 🐛 Bug Fixes
package/dist/main.cjs CHANGED
@@ -1,3 +1,4 @@
1
- /** 📦 @alwatr/fetch v6.0.11 */ __dev_mode__: console.log("📦 @alwatr/fetch v6.0.11");
1
+ /** 📦 @alwatr/fetch v6.0.12 */
2
+ __dev_mode__: console.debug("📦 @alwatr/fetch v6.0.12");
2
3
  "use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var main_exports={};__export(main_exports,{cacheSupported:()=>cacheSupported,fetch:()=>fetch});module.exports=__toCommonJS(main_exports);var import_delay=require("@alwatr/delay");var import_global_this=require("@alwatr/global-this");var import_http_primer=require("@alwatr/http-primer");var import_logger=require("@alwatr/logger");var import_parse_duration=require("@alwatr/parse-duration");var logger_=(0,import_logger.createLogger)("@alwatr/fetch");var globalThis_=(0,import_global_this.getGlobalThis)();var cacheSupported=Object.hasOwn(globalThis_,"caches");var duplicateRequestStorage_={};var defaultFetchOptions={method:"GET",headers:{},timeout:8e3,retry:3,retryDelay:1e3,removeDuplicate:"never",cacheStrategy:"network_only",cacheStorageName:"fetch_cache"};function fetch(url,options){logger_.logMethodArgs?.("fetch",{url,options});const options_={...defaultFetchOptions,...options,url};options_.window??=null;if(options_.removeDuplicate==="auto"){options_.removeDuplicate=cacheSupported?"until_load":"always"}if(options_.url.lastIndexOf("?")===-1&&options_.queryParams!=null){const queryParams=options_.queryParams;const queryArray=Object.keys(queryParams).map(key=>`${encodeURIComponent(key)}=${encodeURIComponent(String(queryParams[key]))}`);if(queryArray.length>0){options_.url+="?"+queryArray.join("&")}}if(options_.bodyJson!==void 0){options_.body=JSON.stringify(options_.bodyJson);options_.headers["content-type"]=import_http_primer.MimeTypes.JSON}if(options_.bearerToken!==void 0){options_.headers.authorization=`Bearer ${options_.bearerToken}`}else if(options_.alwatrAuth!==void 0){options_.headers.authorization=`Alwatr ${options_.alwatrAuth.userId}:${options_.alwatrAuth.userToken}`}logger_.logProperty?.("fetch.options",options_);return handleCacheStrategy_(options_)}async function handleCacheStrategy_(options){if(options.cacheStrategy==="network_only"){return handleRemoveDuplicate_(options)}logger_.logMethod?.("handleCacheStrategy_");if(!cacheSupported){logger_.incident?.("fetch","fetch_cache_strategy_unsupported",{cacheSupported});options.cacheStrategy="network_only";return handleRemoveDuplicate_(options)}const cacheStorage=await caches.open(options.cacheStorageName);const request=new Request(options.url,options);switch(options.cacheStrategy){case"cache_first":{const cachedResponse=await cacheStorage.match(request);if(cachedResponse!=null){return cachedResponse}const response=await handleRemoveDuplicate_(options);if(response.ok){cacheStorage.put(request,response.clone())}return response}case"cache_only":{const cachedResponse=await cacheStorage.match(request);if(cachedResponse==null){logger_.accident("_handleCacheStrategy","fetch_cache_not_found",{url:request.url});throw new Error("fetch_cache_not_found")}return cachedResponse}case"network_first":{try{const networkResponse=await handleRemoveDuplicate_(options);if(networkResponse.ok){cacheStorage.put(request,networkResponse.clone())}return networkResponse}catch(err){const cachedResponse=await cacheStorage.match(request);if(cachedResponse!=null){return cachedResponse}throw err}}case"update_cache":{const networkResponse=await handleRemoveDuplicate_(options);if(networkResponse.ok){cacheStorage.put(request,networkResponse.clone())}return networkResponse}case"stale_while_revalidate":{const cachedResponse=await cacheStorage.match(request);const fetchedResponsePromise=handleRemoveDuplicate_(options).then(networkResponse=>{if(networkResponse.ok){cacheStorage.put(request,networkResponse.clone());if(typeof options.revalidateCallback==="function"){setTimeout(options.revalidateCallback,0,networkResponse.clone())}}return networkResponse});return cachedResponse??fetchedResponsePromise}default:{return handleRemoveDuplicate_(options)}}}async function handleRemoveDuplicate_(options){if(options.removeDuplicate==="never"){return handleRetryPattern_(options)}logger_.logMethod?.("handleRemoveDuplicate_");const bodyString=typeof options.body==="string"?options.body:"";const cacheKey=`${options.method} ${options.url} ${bodyString}`;duplicateRequestStorage_[cacheKey]??=handleRetryPattern_(options);try{const response=await duplicateRequestStorage_[cacheKey];if(duplicateRequestStorage_[cacheKey]!=null){if(response.ok!==true||options.removeDuplicate==="until_load"){delete duplicateRequestStorage_[cacheKey]}}return response.clone()}catch(err){delete duplicateRequestStorage_[cacheKey];throw err}}async function handleRetryPattern_(options){if(!(options.retry>1)){return handleTimeout_(options)}logger_.logMethod?.("handleRetryPattern_");options.retry--;const externalAbortSignal=options.signal;try{const response=await handleTimeout_(options);if(response.status<import_http_primer.HttpStatusCodes.Error_Server_500_Internal_Server_Error){return response}throw new Error("fetch_server_error")}catch(err){logger_.accident("fetch","fetch_failed_retry",err);if(globalThis_.navigator?.onLine===false){logger_.accident("handleRetryPattern_","offline","Skip retry because offline");throw err}await import_delay.delay.by(options.retryDelay);options.signal=externalAbortSignal;return handleRetryPattern_(options)}}function handleTimeout_(options){if(options.timeout===0){return globalThis_.fetch(options.url,options)}logger_.logMethod?.("handleTimeout_");return new Promise((resolved,reject)=>{const abortController=typeof AbortController==="function"?new AbortController:null;const externalAbortSignal=options.signal;options.signal=abortController?.signal;if(abortController!==null&&externalAbortSignal!=null){externalAbortSignal.addEventListener("abort",()=>abortController.abort(),{once:true})}const timeoutId=setTimeout(()=>{reject(new Error("fetch_timeout"));abortController?.abort("fetch_timeout")},(0,import_parse_duration.parseDuration)(options.timeout));globalThis_.fetch(options.url,options).then(response=>resolved(response)).catch(reason=>reject(reason)).finally(()=>{clearTimeout(timeoutId)})})}0&&(module.exports={cacheSupported,fetch});
3
4
  //# sourceMappingURL=main.cjs.map
package/dist/main.cjs.map CHANGED
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/main.ts"],
4
4
  "sourcesContent": ["/**\n * @module @alwatr/fetch\n *\n * An enhanced, lightweight, and dependency-free wrapper for the native `fetch` API.\n * It provides modern features like caching strategies, request retries, timeouts, and\n * duplicate request handling.\n */\n\nimport {delay} from '@alwatr/delay';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {HttpStatusCodes, MimeTypes} from '@alwatr/http-primer';\nimport {createLogger} from '@alwatr/logger';\nimport {parseDuration} from '@alwatr/parse-duration';\n\nimport type {AlwatrFetchOptions_, FetchOptions} from './type.js';\n\nexport {cacheSupported};\nexport type * from './type.js';\n\nconst logger_ = createLogger('@alwatr/fetch');\nconst globalThis_ = getGlobalThis();\n\n/**\n * A boolean flag indicating whether the browser's Cache API is supported.\n */\nconst cacheSupported = Object.hasOwn(globalThis_, 'caches');\n\n/**\n * A simple in-memory storage for tracking and managing duplicate in-flight requests.\n * The key is a unique identifier for the request (e.g., method + URL + body),\n * and the value is the promise of the ongoing fetch operation.\n */\nconst duplicateRequestStorage_: Record<string, Promise<Response>> = {};\n\n/**\n * Default options for all fetch requests. These can be overridden by passing\n * a custom `options` object to the `fetch` function.\n */\nconst defaultFetchOptions: AlwatrFetchOptions_ = {\n method: 'GET',\n headers: {},\n timeout: 8_000,\n retry: 3,\n retryDelay: 1_000,\n removeDuplicate: 'never',\n cacheStrategy: 'network_only',\n cacheStorageName: 'fetch_cache',\n};\n\n/**\n * Internal-only fetch options type, which includes the URL and ensures all\n * optional properties from AlwatrFetchOptions_ are present.\n */\ntype FetchOptions__ = AlwatrFetchOptions_ & Omit<RequestInit, 'headers'> & {url: string};\n\n/**\n * An enhanced wrapper for the native `fetch` function.\n *\n * This function extends the standard `fetch` with additional features such as:\n * - **Timeout**: Aborts the request if it takes too long.\n * - **Retry Pattern**: Automatically retries the request on failure (e.g., server errors or network issues).\n * - **Duplicate Request Handling**: Prevents sending multiple identical requests in parallel.\n * - **Cache Strategies**: Provides various caching mechanisms using the browser's Cache API.\n * - **Simplified API**: Offers convenient options for adding query parameters, JSON bodies, and auth tokens.\n *\n * @see {@link FetchOptions} for a detailed list of available options.\n *\n * @param {string} url - The URL to fetch.\n * @param {FetchOptions} options - Optional configuration for the fetch request.\n * @returns {Promise<Response>} A promise that resolves to the `Response` object for the request.\n *\n * @example\n * ```typescript\n * async function fetchProducts() {\n * try {\n * const response = await fetch(\"/api/products\", {\n * queryParams: { limit: 10, category: \"electronics\" },\n * timeout: 5_000, // 5 seconds\n * retry: 3,\n * cacheStrategy: \"stale_while_revalidate\",\n * });\n *\n * if (!response.ok) {\n * throw new Error(`HTTP error! status: ${response.status}`);\n * }\n *\n * const data = await response.json();\n * console.log(\"Products:\", data);\n * } catch (error) {\n * console.error(\"Failed to fetch products:\", error);\n * }\n * }\n *\n * fetchProducts();\n * ```\n */\nexport function fetch(url: string, options: FetchOptions): Promise<Response> {\n logger_.logMethodArgs?.('fetch', {url, options});\n\n const options_: FetchOptions__ = {\n ...defaultFetchOptions,\n ...options,\n url,\n };\n\n options_.window ??= null;\n\n if (options_.removeDuplicate === 'auto') {\n options_.removeDuplicate = cacheSupported ? 'until_load' : 'always';\n }\n\n // Append query parameters to the URL if they are provided and the URL doesn't already have them.\n if (options_.url.lastIndexOf('?') === -1 && options_.queryParams != null) {\n const queryParams = options_.queryParams;\n // prettier-ignore\n const queryArray = Object\n .keys(queryParams)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(String(queryParams[key]))}`);\n\n if (queryArray.length > 0) {\n options_.url += '?' + queryArray.join('&');\n }\n }\n\n // If `bodyJson` is provided, stringify it and set the appropriate 'Content-Type' header.\n if (options_.bodyJson !== undefined) {\n options_.body = JSON.stringify(options_.bodyJson);\n options_.headers['content-type'] = MimeTypes.JSON;\n }\n\n // Set the 'Authorization' header for bearer tokens or Alwatr's authentication scheme.\n if (options_.bearerToken !== undefined) {\n options_.headers.authorization = `Bearer ${options_.bearerToken}`;\n }\n else if (options_.alwatrAuth !== undefined) {\n options_.headers.authorization = `Alwatr ${options_.alwatrAuth.userId}:${options_.alwatrAuth.userToken}`;\n }\n\n logger_.logProperty?.('fetch.options', options_);\n\n // Start the fetch lifecycle, beginning with the cache strategy.\n return handleCacheStrategy_(options_);\n}\n\n/**\n * Manages caching strategies for the fetch request.\n * If the strategy is `network_only`, it bypasses caching and proceeds to the next step.\n * Otherwise, it interacts with the browser's Cache API based on the selected strategy.\n *\n * @param {FetchOptions__} options - The fully configured fetch options.\n * @returns {Promise<Response>} A promise resolving to a `Response` object, either from the cache or the network.\n * @private\n */\nasync function handleCacheStrategy_(options: FetchOptions__): Promise<Response> {\n if (options.cacheStrategy === 'network_only') {\n return handleRemoveDuplicate_(options);\n }\n // else\n\n logger_.logMethod?.('handleCacheStrategy_');\n\n if (!cacheSupported) {\n logger_.incident?.('fetch', 'fetch_cache_strategy_unsupported', {\n cacheSupported,\n });\n // Fallback to network_only if Cache API is not available.\n options.cacheStrategy = 'network_only';\n return handleRemoveDuplicate_(options);\n }\n // else\n\n const cacheStorage = await caches.open(options.cacheStorageName);\n\n const request = new Request(options.url, options);\n\n switch (options.cacheStrategy) {\n case 'cache_first': {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse != null) {\n return cachedResponse;\n }\n // else\n\n const response = await handleRemoveDuplicate_(options);\n if (response.ok) {\n cacheStorage.put(request, response.clone());\n }\n return response;\n }\n\n case 'cache_only': {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse == null) {\n logger_.accident('_handleCacheStrategy', 'fetch_cache_not_found', {url: request.url});\n throw new Error('fetch_cache_not_found');\n }\n // else\n\n return cachedResponse;\n }\n\n case 'network_first': {\n try {\n const networkResponse = await handleRemoveDuplicate_(options);\n if (networkResponse.ok) {\n cacheStorage.put(request, networkResponse.clone());\n }\n return networkResponse;\n }\n catch (err) {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse != null) {\n return cachedResponse;\n }\n // else\n\n throw err;\n }\n }\n\n case 'update_cache': {\n const networkResponse = await handleRemoveDuplicate_(options);\n if (networkResponse.ok) {\n cacheStorage.put(request, networkResponse.clone());\n }\n return networkResponse;\n }\n\n case 'stale_while_revalidate': {\n const cachedResponse = await cacheStorage.match(request);\n const fetchedResponsePromise = handleRemoveDuplicate_(options).then((networkResponse) => {\n if (networkResponse.ok) {\n cacheStorage.put(request, networkResponse.clone());\n if (typeof options.revalidateCallback === 'function') {\n setTimeout(options.revalidateCallback, 0, networkResponse.clone());\n }\n }\n return networkResponse;\n });\n\n return cachedResponse ?? fetchedResponsePromise;\n }\n\n default: {\n return handleRemoveDuplicate_(options);\n }\n }\n}\n\n/**\n * Handles duplicate request elimination.\n *\n * It creates a unique key based on the request method, URL, and body. If a request with the\n * same key is already in flight, it returns the promise of the existing request instead of\n * creating a new one. This prevents redundant network calls for identical parallel requests.\n *\n * @param {FetchOptions__} options - The fully configured fetch options.\n * @returns {Promise<Response>} A promise resolving to a cloned `Response` object.\n * @private\n */\nasync function handleRemoveDuplicate_(options: FetchOptions__): Promise<Response> {\n if (options.removeDuplicate === 'never') {\n return handleRetryPattern_(options);\n }\n // else\n\n logger_.logMethod?.('handleRemoveDuplicate_');\n\n // Create a unique key for the request. Including the body is crucial to differentiate\n // between requests to the same URL but with different payloads (e.g., POST requests).\n const bodyString = typeof options.body === 'string' ? options.body : '';\n const cacheKey = `${options.method} ${options.url} ${bodyString}`;\n\n // If a request with the same key doesn't exist, create it and store its promise.\n duplicateRequestStorage_[cacheKey] ??= handleRetryPattern_(options);\n\n try {\n // Await the shared promise to get the response.\n const response = await duplicateRequestStorage_[cacheKey];\n\n // Clean up the stored promise based on the removal strategy.\n if (duplicateRequestStorage_[cacheKey] != null) {\n if (response.ok !== true || options.removeDuplicate === 'until_load') {\n // Remove after completion for 'until_load' or if the request failed.\n delete duplicateRequestStorage_[cacheKey];\n }\n }\n\n // Return a clone of the response, so each caller can consume the body independently.\n return response.clone();\n }\n catch (err) {\n // If the request fails, remove it from storage to allow for retries.\n delete duplicateRequestStorage_[cacheKey];\n throw err;\n }\n}\n\n/**\n * Implements a retry mechanism for the fetch request.\n * If the request fails due to a server error (status >= 500) or a timeout,\n * it will be retried up to the specified number of times.\n *\n * @param {FetchOptions__} options - The fully configured fetch options.\n * @returns {Promise<Response>} A promise that resolves to the final `Response` after all retries.\n * @private\n */\nasync function handleRetryPattern_(options: FetchOptions__): Promise<Response> {\n if (!(options.retry > 1)) {\n return handleTimeout_(options);\n }\n // else\n\n logger_.logMethod?.('handleRetryPattern_');\n options.retry--;\n\n const externalAbortSignal = options.signal;\n\n try {\n const response = await handleTimeout_(options);\n\n // Only retry on server errors (5xx). Client errors (4xx) are not retried.\n if (response.status < HttpStatusCodes.Error_Server_500_Internal_Server_Error) {\n return response;\n }\n // else\n\n throw new Error('fetch_server_error');\n }\n catch (err) {\n logger_.accident('fetch', 'fetch_failed_retry', err);\n\n // Do not retry if the browser is offline.\n if (globalThis_.navigator?.onLine === false) {\n logger_.accident('handleRetryPattern_', 'offline', 'Skip retry because offline');\n throw err;\n }\n\n await delay.by(options.retryDelay);\n\n // Restore the original signal for the next attempt.\n options.signal = externalAbortSignal;\n return handleRetryPattern_(options);\n }\n}\n\n/**\n * Wraps the native fetch call with a timeout mechanism.\n *\n * It uses an `AbortController` to abort the request if it does not complete\n * within the specified `timeout` duration. It also respects external abort signals.\n *\n * @param {FetchOptions__} options - The fully configured fetch options.\n * @returns {Promise<Response>} A promise that resolves with the `Response` or rejects on timeout.\n * @private\n */\nfunction handleTimeout_(options: FetchOptions__): Promise<Response> {\n if (options.timeout === 0) {\n // If timeout is disabled, call fetch directly.\n return globalThis_.fetch(options.url, options);\n }\n\n logger_.logMethod?.('handleTimeout_');\n\n return new Promise((resolved, reject) => {\n const abortController = typeof AbortController === 'function' ? new AbortController() : null;\n const externalAbortSignal = options.signal;\n options.signal = abortController?.signal;\n\n // If an external AbortSignal is provided, listen to it and propagate the abort.\n if (abortController !== null && externalAbortSignal != null) {\n externalAbortSignal.addEventListener('abort', () => abortController.abort(), {once: true});\n }\n\n const timeoutId = setTimeout(() => {\n reject(new Error('fetch_timeout'));\n abortController?.abort('fetch_timeout');\n }, parseDuration(options.timeout!));\n\n globalThis_\n .fetch(options.url, options)\n .then((response) => resolved(response))\n .catch((reason) => reject(reason))\n .finally(() => {\n // Clean up the timeout to prevent it from firing after the request has completed.\n clearTimeout(timeoutId);\n });\n });\n}\n"],
5
- "mappings": "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",
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/main.mjs CHANGED
@@ -1,3 +1,4 @@
1
- /** 📦 @alwatr/fetch v6.0.11 */ __dev_mode__: console.log("📦 @alwatr/fetch v6.0.11");
1
+ /** 📦 @alwatr/fetch v6.0.12 */
2
+ __dev_mode__: console.debug("📦 @alwatr/fetch v6.0.12");
2
3
  import{delay}from"@alwatr/delay";import{getGlobalThis}from"@alwatr/global-this";import{HttpStatusCodes,MimeTypes}from"@alwatr/http-primer";import{createLogger}from"@alwatr/logger";import{parseDuration}from"@alwatr/parse-duration";var logger_=createLogger("@alwatr/fetch");var globalThis_=getGlobalThis();var cacheSupported=Object.hasOwn(globalThis_,"caches");var duplicateRequestStorage_={};var defaultFetchOptions={method:"GET",headers:{},timeout:8e3,retry:3,retryDelay:1e3,removeDuplicate:"never",cacheStrategy:"network_only",cacheStorageName:"fetch_cache"};function fetch(url,options){logger_.logMethodArgs?.("fetch",{url,options});const options_={...defaultFetchOptions,...options,url};options_.window??=null;if(options_.removeDuplicate==="auto"){options_.removeDuplicate=cacheSupported?"until_load":"always"}if(options_.url.lastIndexOf("?")===-1&&options_.queryParams!=null){const queryParams=options_.queryParams;const queryArray=Object.keys(queryParams).map(key=>`${encodeURIComponent(key)}=${encodeURIComponent(String(queryParams[key]))}`);if(queryArray.length>0){options_.url+="?"+queryArray.join("&")}}if(options_.bodyJson!==void 0){options_.body=JSON.stringify(options_.bodyJson);options_.headers["content-type"]=MimeTypes.JSON}if(options_.bearerToken!==void 0){options_.headers.authorization=`Bearer ${options_.bearerToken}`}else if(options_.alwatrAuth!==void 0){options_.headers.authorization=`Alwatr ${options_.alwatrAuth.userId}:${options_.alwatrAuth.userToken}`}logger_.logProperty?.("fetch.options",options_);return handleCacheStrategy_(options_)}async function handleCacheStrategy_(options){if(options.cacheStrategy==="network_only"){return handleRemoveDuplicate_(options)}logger_.logMethod?.("handleCacheStrategy_");if(!cacheSupported){logger_.incident?.("fetch","fetch_cache_strategy_unsupported",{cacheSupported});options.cacheStrategy="network_only";return handleRemoveDuplicate_(options)}const cacheStorage=await caches.open(options.cacheStorageName);const request=new Request(options.url,options);switch(options.cacheStrategy){case"cache_first":{const cachedResponse=await cacheStorage.match(request);if(cachedResponse!=null){return cachedResponse}const response=await handleRemoveDuplicate_(options);if(response.ok){cacheStorage.put(request,response.clone())}return response}case"cache_only":{const cachedResponse=await cacheStorage.match(request);if(cachedResponse==null){logger_.accident("_handleCacheStrategy","fetch_cache_not_found",{url:request.url});throw new Error("fetch_cache_not_found")}return cachedResponse}case"network_first":{try{const networkResponse=await handleRemoveDuplicate_(options);if(networkResponse.ok){cacheStorage.put(request,networkResponse.clone())}return networkResponse}catch(err){const cachedResponse=await cacheStorage.match(request);if(cachedResponse!=null){return cachedResponse}throw err}}case"update_cache":{const networkResponse=await handleRemoveDuplicate_(options);if(networkResponse.ok){cacheStorage.put(request,networkResponse.clone())}return networkResponse}case"stale_while_revalidate":{const cachedResponse=await cacheStorage.match(request);const fetchedResponsePromise=handleRemoveDuplicate_(options).then(networkResponse=>{if(networkResponse.ok){cacheStorage.put(request,networkResponse.clone());if(typeof options.revalidateCallback==="function"){setTimeout(options.revalidateCallback,0,networkResponse.clone())}}return networkResponse});return cachedResponse??fetchedResponsePromise}default:{return handleRemoveDuplicate_(options)}}}async function handleRemoveDuplicate_(options){if(options.removeDuplicate==="never"){return handleRetryPattern_(options)}logger_.logMethod?.("handleRemoveDuplicate_");const bodyString=typeof options.body==="string"?options.body:"";const cacheKey=`${options.method} ${options.url} ${bodyString}`;duplicateRequestStorage_[cacheKey]??=handleRetryPattern_(options);try{const response=await duplicateRequestStorage_[cacheKey];if(duplicateRequestStorage_[cacheKey]!=null){if(response.ok!==true||options.removeDuplicate==="until_load"){delete duplicateRequestStorage_[cacheKey]}}return response.clone()}catch(err){delete duplicateRequestStorage_[cacheKey];throw err}}async function handleRetryPattern_(options){if(!(options.retry>1)){return handleTimeout_(options)}logger_.logMethod?.("handleRetryPattern_");options.retry--;const externalAbortSignal=options.signal;try{const response=await handleTimeout_(options);if(response.status<HttpStatusCodes.Error_Server_500_Internal_Server_Error){return response}throw new Error("fetch_server_error")}catch(err){logger_.accident("fetch","fetch_failed_retry",err);if(globalThis_.navigator?.onLine===false){logger_.accident("handleRetryPattern_","offline","Skip retry because offline");throw err}await delay.by(options.retryDelay);options.signal=externalAbortSignal;return handleRetryPattern_(options)}}function handleTimeout_(options){if(options.timeout===0){return globalThis_.fetch(options.url,options)}logger_.logMethod?.("handleTimeout_");return new Promise((resolved,reject)=>{const abortController=typeof AbortController==="function"?new AbortController:null;const externalAbortSignal=options.signal;options.signal=abortController?.signal;if(abortController!==null&&externalAbortSignal!=null){externalAbortSignal.addEventListener("abort",()=>abortController.abort(),{once:true})}const timeoutId=setTimeout(()=>{reject(new Error("fetch_timeout"));abortController?.abort("fetch_timeout")},parseDuration(options.timeout));globalThis_.fetch(options.url,options).then(response=>resolved(response)).catch(reason=>reject(reason)).finally(()=>{clearTimeout(timeoutId)})})}export{cacheSupported,fetch};
3
4
  //# sourceMappingURL=main.mjs.map
package/dist/main.mjs.map CHANGED
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/main.ts"],
4
4
  "sourcesContent": ["/**\n * @module @alwatr/fetch\n *\n * An enhanced, lightweight, and dependency-free wrapper for the native `fetch` API.\n * It provides modern features like caching strategies, request retries, timeouts, and\n * duplicate request handling.\n */\n\nimport {delay} from '@alwatr/delay';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {HttpStatusCodes, MimeTypes} from '@alwatr/http-primer';\nimport {createLogger} from '@alwatr/logger';\nimport {parseDuration} from '@alwatr/parse-duration';\n\nimport type {AlwatrFetchOptions_, FetchOptions} from './type.js';\n\nexport {cacheSupported};\nexport type * from './type.js';\n\nconst logger_ = createLogger('@alwatr/fetch');\nconst globalThis_ = getGlobalThis();\n\n/**\n * A boolean flag indicating whether the browser's Cache API is supported.\n */\nconst cacheSupported = Object.hasOwn(globalThis_, 'caches');\n\n/**\n * A simple in-memory storage for tracking and managing duplicate in-flight requests.\n * The key is a unique identifier for the request (e.g., method + URL + body),\n * and the value is the promise of the ongoing fetch operation.\n */\nconst duplicateRequestStorage_: Record<string, Promise<Response>> = {};\n\n/**\n * Default options for all fetch requests. These can be overridden by passing\n * a custom `options` object to the `fetch` function.\n */\nconst defaultFetchOptions: AlwatrFetchOptions_ = {\n method: 'GET',\n headers: {},\n timeout: 8_000,\n retry: 3,\n retryDelay: 1_000,\n removeDuplicate: 'never',\n cacheStrategy: 'network_only',\n cacheStorageName: 'fetch_cache',\n};\n\n/**\n * Internal-only fetch options type, which includes the URL and ensures all\n * optional properties from AlwatrFetchOptions_ are present.\n */\ntype FetchOptions__ = AlwatrFetchOptions_ & Omit<RequestInit, 'headers'> & {url: string};\n\n/**\n * An enhanced wrapper for the native `fetch` function.\n *\n * This function extends the standard `fetch` with additional features such as:\n * - **Timeout**: Aborts the request if it takes too long.\n * - **Retry Pattern**: Automatically retries the request on failure (e.g., server errors or network issues).\n * - **Duplicate Request Handling**: Prevents sending multiple identical requests in parallel.\n * - **Cache Strategies**: Provides various caching mechanisms using the browser's Cache API.\n * - **Simplified API**: Offers convenient options for adding query parameters, JSON bodies, and auth tokens.\n *\n * @see {@link FetchOptions} for a detailed list of available options.\n *\n * @param {string} url - The URL to fetch.\n * @param {FetchOptions} options - Optional configuration for the fetch request.\n * @returns {Promise<Response>} A promise that resolves to the `Response` object for the request.\n *\n * @example\n * ```typescript\n * async function fetchProducts() {\n * try {\n * const response = await fetch(\"/api/products\", {\n * queryParams: { limit: 10, category: \"electronics\" },\n * timeout: 5_000, // 5 seconds\n * retry: 3,\n * cacheStrategy: \"stale_while_revalidate\",\n * });\n *\n * if (!response.ok) {\n * throw new Error(`HTTP error! status: ${response.status}`);\n * }\n *\n * const data = await response.json();\n * console.log(\"Products:\", data);\n * } catch (error) {\n * console.error(\"Failed to fetch products:\", error);\n * }\n * }\n *\n * fetchProducts();\n * ```\n */\nexport function fetch(url: string, options: FetchOptions): Promise<Response> {\n logger_.logMethodArgs?.('fetch', {url, options});\n\n const options_: FetchOptions__ = {\n ...defaultFetchOptions,\n ...options,\n url,\n };\n\n options_.window ??= null;\n\n if (options_.removeDuplicate === 'auto') {\n options_.removeDuplicate = cacheSupported ? 'until_load' : 'always';\n }\n\n // Append query parameters to the URL if they are provided and the URL doesn't already have them.\n if (options_.url.lastIndexOf('?') === -1 && options_.queryParams != null) {\n const queryParams = options_.queryParams;\n // prettier-ignore\n const queryArray = Object\n .keys(queryParams)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(String(queryParams[key]))}`);\n\n if (queryArray.length > 0) {\n options_.url += '?' + queryArray.join('&');\n }\n }\n\n // If `bodyJson` is provided, stringify it and set the appropriate 'Content-Type' header.\n if (options_.bodyJson !== undefined) {\n options_.body = JSON.stringify(options_.bodyJson);\n options_.headers['content-type'] = MimeTypes.JSON;\n }\n\n // Set the 'Authorization' header for bearer tokens or Alwatr's authentication scheme.\n if (options_.bearerToken !== undefined) {\n options_.headers.authorization = `Bearer ${options_.bearerToken}`;\n }\n else if (options_.alwatrAuth !== undefined) {\n options_.headers.authorization = `Alwatr ${options_.alwatrAuth.userId}:${options_.alwatrAuth.userToken}`;\n }\n\n logger_.logProperty?.('fetch.options', options_);\n\n // Start the fetch lifecycle, beginning with the cache strategy.\n return handleCacheStrategy_(options_);\n}\n\n/**\n * Manages caching strategies for the fetch request.\n * If the strategy is `network_only`, it bypasses caching and proceeds to the next step.\n * Otherwise, it interacts with the browser's Cache API based on the selected strategy.\n *\n * @param {FetchOptions__} options - The fully configured fetch options.\n * @returns {Promise<Response>} A promise resolving to a `Response` object, either from the cache or the network.\n * @private\n */\nasync function handleCacheStrategy_(options: FetchOptions__): Promise<Response> {\n if (options.cacheStrategy === 'network_only') {\n return handleRemoveDuplicate_(options);\n }\n // else\n\n logger_.logMethod?.('handleCacheStrategy_');\n\n if (!cacheSupported) {\n logger_.incident?.('fetch', 'fetch_cache_strategy_unsupported', {\n cacheSupported,\n });\n // Fallback to network_only if Cache API is not available.\n options.cacheStrategy = 'network_only';\n return handleRemoveDuplicate_(options);\n }\n // else\n\n const cacheStorage = await caches.open(options.cacheStorageName);\n\n const request = new Request(options.url, options);\n\n switch (options.cacheStrategy) {\n case 'cache_first': {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse != null) {\n return cachedResponse;\n }\n // else\n\n const response = await handleRemoveDuplicate_(options);\n if (response.ok) {\n cacheStorage.put(request, response.clone());\n }\n return response;\n }\n\n case 'cache_only': {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse == null) {\n logger_.accident('_handleCacheStrategy', 'fetch_cache_not_found', {url: request.url});\n throw new Error('fetch_cache_not_found');\n }\n // else\n\n return cachedResponse;\n }\n\n case 'network_first': {\n try {\n const networkResponse = await handleRemoveDuplicate_(options);\n if (networkResponse.ok) {\n cacheStorage.put(request, networkResponse.clone());\n }\n return networkResponse;\n }\n catch (err) {\n const cachedResponse = await cacheStorage.match(request);\n if (cachedResponse != null) {\n return cachedResponse;\n }\n // else\n\n throw err;\n }\n }\n\n case 'update_cache': {\n const networkResponse = await handleRemoveDuplicate_(options);\n if (networkResponse.ok) {\n cacheStorage.put(request, networkResponse.clone());\n }\n return networkResponse;\n }\n\n case 'stale_while_revalidate': {\n const cachedResponse = await cacheStorage.match(request);\n const fetchedResponsePromise = handleRemoveDuplicate_(options).then((networkResponse) => {\n if (networkResponse.ok) {\n cacheStorage.put(request, networkResponse.clone());\n if (typeof options.revalidateCallback === 'function') {\n setTimeout(options.revalidateCallback, 0, networkResponse.clone());\n }\n }\n return networkResponse;\n });\n\n return cachedResponse ?? fetchedResponsePromise;\n }\n\n default: {\n return handleRemoveDuplicate_(options);\n }\n }\n}\n\n/**\n * Handles duplicate request elimination.\n *\n * It creates a unique key based on the request method, URL, and body. If a request with the\n * same key is already in flight, it returns the promise of the existing request instead of\n * creating a new one. This prevents redundant network calls for identical parallel requests.\n *\n * @param {FetchOptions__} options - The fully configured fetch options.\n * @returns {Promise<Response>} A promise resolving to a cloned `Response` object.\n * @private\n */\nasync function handleRemoveDuplicate_(options: FetchOptions__): Promise<Response> {\n if (options.removeDuplicate === 'never') {\n return handleRetryPattern_(options);\n }\n // else\n\n logger_.logMethod?.('handleRemoveDuplicate_');\n\n // Create a unique key for the request. Including the body is crucial to differentiate\n // between requests to the same URL but with different payloads (e.g., POST requests).\n const bodyString = typeof options.body === 'string' ? options.body : '';\n const cacheKey = `${options.method} ${options.url} ${bodyString}`;\n\n // If a request with the same key doesn't exist, create it and store its promise.\n duplicateRequestStorage_[cacheKey] ??= handleRetryPattern_(options);\n\n try {\n // Await the shared promise to get the response.\n const response = await duplicateRequestStorage_[cacheKey];\n\n // Clean up the stored promise based on the removal strategy.\n if (duplicateRequestStorage_[cacheKey] != null) {\n if (response.ok !== true || options.removeDuplicate === 'until_load') {\n // Remove after completion for 'until_load' or if the request failed.\n delete duplicateRequestStorage_[cacheKey];\n }\n }\n\n // Return a clone of the response, so each caller can consume the body independently.\n return response.clone();\n }\n catch (err) {\n // If the request fails, remove it from storage to allow for retries.\n delete duplicateRequestStorage_[cacheKey];\n throw err;\n }\n}\n\n/**\n * Implements a retry mechanism for the fetch request.\n * If the request fails due to a server error (status >= 500) or a timeout,\n * it will be retried up to the specified number of times.\n *\n * @param {FetchOptions__} options - The fully configured fetch options.\n * @returns {Promise<Response>} A promise that resolves to the final `Response` after all retries.\n * @private\n */\nasync function handleRetryPattern_(options: FetchOptions__): Promise<Response> {\n if (!(options.retry > 1)) {\n return handleTimeout_(options);\n }\n // else\n\n logger_.logMethod?.('handleRetryPattern_');\n options.retry--;\n\n const externalAbortSignal = options.signal;\n\n try {\n const response = await handleTimeout_(options);\n\n // Only retry on server errors (5xx). Client errors (4xx) are not retried.\n if (response.status < HttpStatusCodes.Error_Server_500_Internal_Server_Error) {\n return response;\n }\n // else\n\n throw new Error('fetch_server_error');\n }\n catch (err) {\n logger_.accident('fetch', 'fetch_failed_retry', err);\n\n // Do not retry if the browser is offline.\n if (globalThis_.navigator?.onLine === false) {\n logger_.accident('handleRetryPattern_', 'offline', 'Skip retry because offline');\n throw err;\n }\n\n await delay.by(options.retryDelay);\n\n // Restore the original signal for the next attempt.\n options.signal = externalAbortSignal;\n return handleRetryPattern_(options);\n }\n}\n\n/**\n * Wraps the native fetch call with a timeout mechanism.\n *\n * It uses an `AbortController` to abort the request if it does not complete\n * within the specified `timeout` duration. It also respects external abort signals.\n *\n * @param {FetchOptions__} options - The fully configured fetch options.\n * @returns {Promise<Response>} A promise that resolves with the `Response` or rejects on timeout.\n * @private\n */\nfunction handleTimeout_(options: FetchOptions__): Promise<Response> {\n if (options.timeout === 0) {\n // If timeout is disabled, call fetch directly.\n return globalThis_.fetch(options.url, options);\n }\n\n logger_.logMethod?.('handleTimeout_');\n\n return new Promise((resolved, reject) => {\n const abortController = typeof AbortController === 'function' ? new AbortController() : null;\n const externalAbortSignal = options.signal;\n options.signal = abortController?.signal;\n\n // If an external AbortSignal is provided, listen to it and propagate the abort.\n if (abortController !== null && externalAbortSignal != null) {\n externalAbortSignal.addEventListener('abort', () => abortController.abort(), {once: true});\n }\n\n const timeoutId = setTimeout(() => {\n reject(new Error('fetch_timeout'));\n abortController?.abort('fetch_timeout');\n }, parseDuration(options.timeout!));\n\n globalThis_\n .fetch(options.url, options)\n .then((response) => resolved(response))\n .catch((reason) => reject(reason))\n .finally(() => {\n // Clean up the timeout to prevent it from firing after the request has completed.\n clearTimeout(timeoutId);\n });\n });\n}\n"],
5
- "mappings": "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",
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@alwatr/fetch",
3
3
  "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.",
4
- "version": "6.0.11",
4
+ "version": "6.0.12",
5
5
  "author": "S. Ali Mihandoost <ali.mihandoost@gmail.com>",
6
6
  "bugs": "https://github.com/Alwatr/nanolib/issues",
7
7
  "dependencies": {
8
- "@alwatr/delay": "6.0.7",
9
- "@alwatr/global-this": "5.5.16",
10
- "@alwatr/http-primer": "6.0.7",
11
- "@alwatr/logger": "6.0.4",
12
- "@alwatr/parse-duration": "5.5.16"
8
+ "@alwatr/delay": "6.0.8",
9
+ "@alwatr/global-this": "5.5.17",
10
+ "@alwatr/http-primer": "6.0.8",
11
+ "@alwatr/logger": "6.0.5",
12
+ "@alwatr/parse-duration": "5.5.17"
13
13
  },
14
14
  "devDependencies": {
15
- "@alwatr/nano-build": "6.3.0",
15
+ "@alwatr/nano-build": "6.3.1",
16
16
  "@alwatr/prettier-config": "5.0.4",
17
17
  "@alwatr/tsconfig-base": "6.0.2",
18
18
  "@alwatr/type-helper": "6.1.1",
@@ -85,5 +85,5 @@
85
85
  "sideEffects": false,
86
86
  "type": "module",
87
87
  "types": "./dist/main.d.ts",
88
- "gitHead": "44d9eb76cd9ea59d39b2b00467bea42873155f31"
88
+ "gitHead": "912cbccc4aae450a2cd2bbb401b898e00af05386"
89
89
  }