@alwatr/fetch 5.6.6 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.d.ts CHANGED
@@ -1,53 +1,57 @@
1
- import { cacheSupported } from './core.js';
2
- import type { FetchOptions, ResponseError } from './type.js';
1
+ /**
2
+ * @module @alwatr/fetch
3
+ *
4
+ * An enhanced, lightweight, and dependency-free wrapper for the native `fetch` API.
5
+ * It provides modern features like caching strategies, request retries, timeouts, and
6
+ * duplicate request handling.
7
+ */
8
+ import type { FetchOptions } from './type.js';
3
9
  export { cacheSupported };
4
10
  export type * from './type.js';
5
11
  /**
6
- * It's a wrapper around the browser's `fetch` function that adds retry pattern, timeout, cacheStrategy,
7
- * remove duplicates, etc.
8
- *
9
- * @see {@link FetchOptions}
10
- * @see {@link ResponseSuccess}
11
- * @see {@link ResponseError}
12
- *
13
- * @param options Fetch options.
14
- *
15
- * @returns A success or error response.
16
- *
17
- * @example
18
- * ```typescript
19
- * const responseJson = await fetchJson({
20
- * url: '/api/products',
21
- * queryParameters: {limit: 10},
22
- * timeout: 8_000,
23
- * retry: 3,
24
- * cacheStrategy: 'stale_while_revalidate',
25
- * cacheDuplicate: 'auto',
26
- * });
27
- * ```
12
+ * A boolean flag indicating whether the browser's Cache API is supported.
28
13
  */
29
- export declare function fetchJson<T extends JsonObject>(options: FetchOptions): Promise<T | ResponseError>;
14
+ declare const cacheSupported: boolean;
30
15
  /**
31
- * It's a wrapper around the browser's `fetch` function that adds retry pattern, timeout, cacheStrategy,
32
- * remove duplicates, etc.
16
+ * An enhanced wrapper for the native `fetch` function.
33
17
  *
34
- * @see {@link FetchOptions}
18
+ * This function extends the standard `fetch` with additional features such as:
19
+ * - **Timeout**: Aborts the request if it takes too long.
20
+ * - **Retry Pattern**: Automatically retries the request on failure (e.g., server errors or network issues).
21
+ * - **Duplicate Request Handling**: Prevents sending multiple identical requests in parallel.
22
+ * - **Cache Strategies**: Provides various caching mechanisms using the browser's Cache API.
23
+ * - **Simplified API**: Offers convenient options for adding query parameters, JSON bodies, and auth tokens.
35
24
  *
36
- * @param options Fetch options.
25
+ * @see {@link FetchOptions} for a detailed list of available options.
37
26
  *
38
- * @returns A promise that resolves to the Response to that request, whether it is successful or not.
27
+ * @param {string} url - The URL to fetch.
28
+ * @param {FetchOptions} options - Optional configuration for the fetch request.
29
+ * @returns {Promise<Response>} A promise that resolves to the `Response` object for the request.
39
30
  *
40
31
  * @example
41
32
  * ```typescript
42
- * const response = await fetch({
43
- * url: '/api/products',
44
- * queryParameters: {limit: 10},
45
- * timeout: 8_000,
46
- * retry: 3,
47
- * cacheStrategy: 'stale_while_revalidate',
48
- * cacheDuplicate: 'auto',
49
- * });
33
+ * async function fetchProducts() {
34
+ * try {
35
+ * const response = await fetch("/api/products", {
36
+ * queryParams: { limit: 10, category: "electronics" },
37
+ * timeout: 5_000, // 5 seconds
38
+ * retry: 3,
39
+ * cacheStrategy: "stale_while_revalidate",
40
+ * });
41
+ *
42
+ * if (!response.ok) {
43
+ * throw new Error(`HTTP error! status: ${response.status}`);
44
+ * }
45
+ *
46
+ * const data = await response.json();
47
+ * console.log("Products:", data);
48
+ * } catch (error) {
49
+ * console.error("Failed to fetch products:", error);
50
+ * }
51
+ * }
52
+ *
53
+ * fetchProducts();
50
54
  * ```
51
55
  */
52
- export declare function fetch(options: FetchOptions): Promise<Response>;
56
+ export declare function fetch(url: string, options: FetchOptions): Promise<Response>;
53
57
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiD,cAAc,EAAC,MAAM,WAAW,CAAC;AAEzF,OAAO,KAAK,EAAC,YAAY,EAAE,aAAa,EAAkB,MAAM,WAAW,CAAC;AAE5E,OAAO,EAAC,cAAc,EAAC,CAAC;AACxB,mBAAmB,WAAW,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,SAAS,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,CAAC,GAAG,aAAa,CAAC,CA4BvG;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAI9D"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAsB,YAAY,EAAC,MAAM,WAAW,CAAC;AAEjE,OAAO,EAAC,cAAc,EAAC,CAAC;AACxB,mBAAmB,WAAW,CAAC;AAO/B;;GAEG;AACH,QAAA,MAAM,cAAc,SAAuD,CAAC;AA8B5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CA8C3E"}
package/dist/main.mjs CHANGED
@@ -1,66 +1,70 @@
1
- /* @alwatr/fetch v5.6.6 */
1
+ /* @alwatr/fetch v6.0.0 */
2
2
 
3
3
  // src/main.ts
4
- import { HttpStatusCodes as HttpStatusCodes2 } from "@alwatr/http-primer";
5
-
6
- // src/core.ts
7
4
  import { delay } from "@alwatr/delay";
8
5
  import { getGlobalThis } from "@alwatr/global-this";
9
6
  import { HttpStatusCodes, MimeTypes } from "@alwatr/http-primer";
10
7
  import { createLogger } from "@alwatr/logger";
11
8
  import { packageTracer } from "@alwatr/package-tracer";
12
9
  import { parseDuration } from "@alwatr/parse-duration";
13
- __dev_mode__: packageTracer.add("@alwatr/fetch", "5.6.6");
10
+ __dev_mode__: packageTracer.add("@alwatr/fetch", "6.0.0");
14
11
  var logger_ = /* @__PURE__ */ createLogger("@alwatr/fetch");
15
12
  var globalThis_ = /* @__PURE__ */ getGlobalThis();
16
- var cacheStorage_;
17
13
  var cacheSupported = /* @__PURE__ */ Object.hasOwn(globalThis_, "caches");
18
14
  var duplicateRequestStorage_ = {};
19
- function processOptions_(options) {
20
- options.method ??= "GET";
21
- options.window ??= null;
22
- options.timeout ??= 8e3;
23
- options.retry ??= 3;
24
- options.retryDelay ??= 1e3;
25
- options.cacheStrategy ??= "network_only";
26
- options.removeDuplicate ??= "never";
27
- options.headers ??= {};
28
- if (options.cacheStrategy !== "network_only" && cacheSupported !== true) {
29
- logger_.incident?.("fetch", "fetch_cache_strategy_unsupported", {
30
- cacheSupported
31
- });
32
- options.cacheStrategy = "network_only";
33
- }
34
- if (options.removeDuplicate === "auto") {
35
- options.removeDuplicate = cacheSupported ? "until_load" : "always";
15
+ var defaultFetchOptions = {
16
+ method: "GET",
17
+ headers: {},
18
+ timeout: 8e3,
19
+ retry: 3,
20
+ retryDelay: 1e3,
21
+ removeDuplicate: "never",
22
+ cacheStrategy: "network_only",
23
+ cacheStorageName: "fetch_cache"
24
+ };
25
+ function fetch(url, options) {
26
+ logger_.logMethodArgs?.("fetch", { url, options });
27
+ const options_ = {
28
+ ...defaultFetchOptions,
29
+ ...options,
30
+ url
31
+ };
32
+ options_.window ??= null;
33
+ if (options_.removeDuplicate === "auto") {
34
+ options_.removeDuplicate = cacheSupported ? "until_load" : "always";
36
35
  }
37
- if (options.url.lastIndexOf("?") === -1 && options.queryParams != null) {
38
- const queryParams = options.queryParams;
39
- const queryArray = Object.keys(queryParams).map((key) => `${key}=${String(queryParams[key])}`);
36
+ if (options_.url.lastIndexOf("?") === -1 && options_.queryParams != null) {
37
+ const queryParams = options_.queryParams;
38
+ const queryArray = Object.keys(queryParams).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(String(queryParams[key]))}`);
40
39
  if (queryArray.length > 0) {
41
- options.url += "?" + queryArray.join("&");
40
+ options_.url += "?" + queryArray.join("&");
42
41
  }
43
42
  }
44
- if (options.bodyJson !== void 0) {
45
- options.body = JSON.stringify(options.bodyJson);
46
- options.headers["content-type"] = MimeTypes.JSON;
43
+ if (options_.bodyJson !== void 0) {
44
+ options_.body = JSON.stringify(options_.bodyJson);
45
+ options_.headers["content-type"] = MimeTypes.JSON;
47
46
  }
48
- if (options.bearerToken !== void 0) {
49
- options.headers.authorization = `Bearer ${options.bearerToken}`;
50
- } else if (options.alwatrAuth !== void 0) {
51
- options.headers.authorization = `Alwatr ${options.alwatrAuth.userId}:${options.alwatrAuth.userToken}`;
47
+ if (options_.bearerToken !== void 0) {
48
+ options_.headers.authorization = `Bearer ${options_.bearerToken}`;
49
+ } else if (options_.alwatrAuth !== void 0) {
50
+ options_.headers.authorization = `Alwatr ${options_.alwatrAuth.userId}:${options_.alwatrAuth.userToken}`;
52
51
  }
53
- return options;
52
+ logger_.logProperty?.("fetch.options", options_);
53
+ return handleCacheStrategy_(options_);
54
54
  }
55
55
  async function handleCacheStrategy_(options) {
56
56
  if (options.cacheStrategy === "network_only") {
57
57
  return handleRemoveDuplicate_(options);
58
58
  }
59
- logger_.logMethod?.("_handleCacheStrategy");
60
- if (cacheStorage_ == null && options.cacheStorageName == null) {
61
- cacheStorage_ = await caches.open("fetch_cache");
59
+ logger_.logMethod?.("handleCacheStrategy_");
60
+ if (!cacheSupported) {
61
+ logger_.incident?.("fetch", "fetch_cache_strategy_unsupported", {
62
+ cacheSupported
63
+ });
64
+ options.cacheStrategy = "network_only";
65
+ return handleRemoveDuplicate_(options);
62
66
  }
63
- const cacheStorage = options.cacheStorageName != null ? await caches.open(options.cacheStorageName) : cacheStorage_;
67
+ const cacheStorage = await caches.open(options.cacheStorageName);
64
68
  const request = new Request(options.url, options);
65
69
  switch (options.cacheStrategy) {
66
70
  case "cache_first": {
@@ -123,9 +127,12 @@ async function handleCacheStrategy_(options) {
123
127
  }
124
128
  }
125
129
  async function handleRemoveDuplicate_(options) {
126
- if (options.removeDuplicate === "never") return handleRetryPattern_(options);
130
+ if (options.removeDuplicate === "never") {
131
+ return handleRetryPattern_(options);
132
+ }
127
133
  logger_.logMethod?.("handleRemoveDuplicate_");
128
- const cacheKey = options.method + " " + options.url;
134
+ const bodyString = typeof options.body === "string" ? options.body : "";
135
+ const cacheKey = `${options.method} ${options.url} ${bodyString}`;
129
136
  duplicateRequestStorage_[cacheKey] ??= handleRetryPattern_(options);
130
137
  try {
131
138
  const response = await duplicateRequestStorage_[cacheKey];
@@ -141,8 +148,10 @@ async function handleRemoveDuplicate_(options) {
141
148
  }
142
149
  }
143
150
  async function handleRetryPattern_(options) {
144
- if (!(options.retry > 1)) return handleTimeout_(options);
145
- logger_.logMethod?.("_handleRetryPattern");
151
+ if (!(options.retry > 1)) {
152
+ return handleTimeout_(options);
153
+ }
154
+ logger_.logMethod?.("handleRetryPattern_");
146
155
  options.retry--;
147
156
  const externalAbortSignal = options.signal;
148
157
  try {
@@ -179,46 +188,12 @@ function handleTimeout_(options) {
179
188
  abortController?.abort("fetch_timeout");
180
189
  }, parseDuration(options.timeout));
181
190
  globalThis_.fetch(options.url, options).then((response) => resolved(response)).catch((reason) => reject(reason)).finally(() => {
182
- delete options.signal;
183
191
  clearTimeout(timeoutId);
184
192
  });
185
193
  });
186
194
  }
187
-
188
- // src/main.ts
189
- async function fetchJson(options) {
190
- let response;
191
- let responseText;
192
- let responseJson;
193
- try {
194
- response = await fetch(options);
195
- responseText = await response.text();
196
- responseJson = JSON.parse(responseText);
197
- if (responseJson.ok === false) {
198
- throw new Error(`fetch_response_nok`);
199
- }
200
- return responseJson;
201
- } catch (error) {
202
- const responseError = {
203
- ...responseJson,
204
- ok: false,
205
- statusCode: response?.status ?? HttpStatusCodes2.Error_Server_500_Internal_Server_Error,
206
- errorCode: responseJson?.errorCode ?? error.message,
207
- errorMessage: responseJson?.errorMessage ?? error.message
208
- // responseText,
209
- };
210
- logger_.accident("fetchJson", "fetch_json_failed", { responseError, error, responseText });
211
- return responseError;
212
- }
213
- }
214
- function fetch(options) {
215
- options = processOptions_(options);
216
- logger_.logMethodArgs?.("fetch", { options });
217
- return handleCacheStrategy_(options);
218
- }
219
195
  export {
220
196
  cacheSupported,
221
- fetch,
222
- fetchJson
197
+ fetch
223
198
  };
224
199
  //# sourceMappingURL=main.mjs.map
package/dist/main.mjs.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/main.ts", "../src/core.ts"],
4
- "sourcesContent": ["import {HttpStatusCodes, type HttpStatusCode} from '@alwatr/http-primer';\n\nimport {handleCacheStrategy_, logger_, processOptions_, cacheSupported} from './core.js';\n\nimport type {FetchOptions, ResponseError, ResponseSuccess} from './type.js';\n\nexport {cacheSupported};\nexport type * from './type.js';\n\n/**\n * It's a wrapper around the browser's `fetch` function that adds retry pattern, timeout, cacheStrategy,\n * remove duplicates, etc.\n *\n * @see {@link FetchOptions}\n * @see {@link ResponseSuccess}\n * @see {@link ResponseError}\n *\n * @param options Fetch options.\n *\n * @returns A success or error response.\n *\n * @example\n * ```typescript\n * const responseJson = await fetchJson({\n * url: '/api/products',\n * queryParameters: {limit: 10},\n * timeout: 8_000,\n * retry: 3,\n * cacheStrategy: 'stale_while_revalidate',\n * cacheDuplicate: 'auto',\n * });\n * ```\n */\nexport async function fetchJson<T extends JsonObject>(options: FetchOptions): Promise<T | ResponseError> {\n let response;\n let responseText;\n let responseJson;\n\n try {\n response = await fetch(options);\n responseText = await response.text();\n responseJson = JSON.parse(responseText) as (ResponseError | ResponseSuccess<T>);\n if (responseJson.ok === false) {\n throw new Error(`fetch_response_nok`);\n }\n // responseJson.statusCode ??= response.status as HttpStatusCode;\n return responseJson;\n }\n catch (error) {\n const responseError: ResponseError = {\n ...responseJson,\n ok: false,\n statusCode: (response?.status as HttpStatusCode) ?? HttpStatusCodes.Error_Server_500_Internal_Server_Error,\n errorCode: (responseJson?.errorCode as string) ?? (error as Error).message,\n errorMessage: (responseJson?.errorMessage as string) ?? (error as Error).message,\n // responseText,\n };\n\n logger_.accident('fetchJson', 'fetch_json_failed', {responseError, error, responseText});\n return responseError;\n }\n}\n\n/**\n * It's a wrapper around the browser's `fetch` function that adds retry pattern, timeout, cacheStrategy,\n * remove duplicates, etc.\n *\n * @see {@link FetchOptions}\n *\n * @param options Fetch options.\n *\n * @returns A promise that resolves to the Response to that request, whether it is successful or not.\n *\n * @example\n * ```typescript\n * const response = await fetch({\n * url: '/api/products',\n * queryParameters: {limit: 10},\n * timeout: 8_000,\n * retry: 3,\n * cacheStrategy: 'stale_while_revalidate',\n * cacheDuplicate: 'auto',\n * });\n * ```\n */\nexport function fetch(options: FetchOptions): Promise<Response> {\n options = processOptions_(options);\n logger_.logMethodArgs?.('fetch', {options});\n return handleCacheStrategy_(options as Required<FetchOptions>);\n}\n", "import {delay} from '@alwatr/delay';\nimport {getGlobalThis} from '@alwatr/global-this';\nimport {HttpStatusCodes, MimeTypes} from '@alwatr/http-primer';\nimport {createLogger} from '@alwatr/logger';\nimport {packageTracer} from '@alwatr/package-tracer';\nimport {parseDuration} from '@alwatr/parse-duration';\n\nimport type {FetchOptions} from './type.js';\n\n__dev_mode__: packageTracer.add(__package_name__, __package_version__);\n\nexport const logger_ = /* #__PURE__ */ createLogger('@alwatr/fetch');\n\nconst globalThis_ = /* #__PURE__ */ getGlobalThis();\n\nlet cacheStorage_: Cache;\nexport const cacheSupported = /* #__PURE__ */ Object.hasOwn(globalThis_, 'caches');\n\nconst duplicateRequestStorage_: Record<string, Promise<Response>> = {};\n\n/**\n * Process fetch options and set defaults, etc.\n *\n * @param options Fetch options.\n *\n * @returns Required fetch options.\n */\nexport function processOptions_(options: FetchOptions): Required<FetchOptions> {\n options.method ??= 'GET';\n options.window ??= null;\n\n options.timeout ??= 8_000;\n options.retry ??= 3;\n options.retryDelay ??= 1_000;\n options.cacheStrategy ??= 'network_only';\n options.removeDuplicate ??= 'never';\n options.headers ??= {};\n\n if (options.cacheStrategy !== 'network_only' && cacheSupported !== true) {\n logger_.incident?.('fetch', 'fetch_cache_strategy_unsupported', {\n cacheSupported,\n });\n options.cacheStrategy = 'network_only';\n }\n\n if (options.removeDuplicate === 'auto') {\n options.removeDuplicate = cacheSupported ? 'until_load' : 'always';\n }\n\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) => `${key}=${String(queryParams[key])}`);\n\n if (queryArray.length > 0) {\n options.url += '?' + queryArray.join('&');\n }\n }\n\n if (options.bodyJson !== undefined) {\n options.body = JSON.stringify(options.bodyJson);\n options.headers['content-type'] = MimeTypes.JSON;\n }\n\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 return options as Required<FetchOptions>;\n}\n\n/**\n * Handle Cache Strategy over `handleRemoveDuplicate_`.\n */\nexport async function handleCacheStrategy_(options: Required<FetchOptions>): Promise<Response> {\n if (options.cacheStrategy === 'network_only') {\n return handleRemoveDuplicate_(options);\n }\n // else handle cache strategies!\n logger_.logMethod?.('_handleCacheStrategy');\n\n if (cacheStorage_ == null && options.cacheStorageName == null) {\n cacheStorage_ = await caches.open('fetch_cache');\n }\n\n const cacheStorage = options.cacheStorageName != null ? await caches.open(options.cacheStorageName) : cacheStorage_;\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 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 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 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 * Handle Remove Duplicates over `_handleRetryPattern`.\n */\nexport async function handleRemoveDuplicate_(options: Required<FetchOptions>): Promise<Response> {\n if (options.removeDuplicate === 'never') return handleRetryPattern_(options);\n\n logger_.logMethod?.('handleRemoveDuplicate_');\n\n const cacheKey = options.method + ' ' + options.url;\n\n // We must cache fetch promise without await for handle other parallel requests.\n duplicateRequestStorage_[cacheKey] ??= handleRetryPattern_(options);\n\n try {\n // For all requests need to await for clone responses.\n const response = await duplicateRequestStorage_[cacheKey];\n\n if (duplicateRequestStorage_[cacheKey] != null) {\n if (response.ok !== true || options.removeDuplicate === 'until_load') {\n delete duplicateRequestStorage_[cacheKey];\n }\n }\n\n return response.clone();\n }\n catch (err) {\n // clean cache on any error.\n delete duplicateRequestStorage_[cacheKey];\n throw err;\n }\n}\n\n/**\n * Handle retry pattern over `handleTimeout_`.\n */\nexport async function handleRetryPattern_(options: Required<FetchOptions>): Promise<Response> {\n if (!(options.retry > 1)) return handleTimeout_(options);\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 if (response.status < HttpStatusCodes.Error_Server_500_Internal_Server_Error) {\n return response;\n }\n // else\n throw new Error('fetch_server_error');\n }\n catch (err) {\n logger_.accident('fetch', 'fetch_failed_retry', err);\n\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 options.signal = externalAbortSignal;\n return handleRetryPattern_(options);\n }\n}\n\n/**\n * It's a wrapper around the browser's `fetch` with timeout.\n */\nexport function handleTimeout_(options: FetchOptions): Promise<Response> {\n if (options.timeout === 0) {\n return globalThis_.fetch(options.url, options);\n }\n // else\n logger_.logMethod?.('handleTimeout_');\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 (abortController !== null && externalAbortSignal != null) {\n // Respect external abort signal\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 // abortController.signal.addEventListener('abort', () => {\n // logger.incident('fetch', 'fetch_abort_signal', {\n // reason: abortController.signal.reason,\n // });\n // });\n\n globalThis_\n .fetch(options.url, options)\n .then((response) => resolved(response))\n .catch((reason) => reject(reason))\n .finally(() => {\n delete options.signal; // try to avoid memory leak in nodejs!\n clearTimeout(timeoutId);\n });\n });\n}\n"],
5
- "mappings": "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",
6
- "names": ["HttpStatusCodes", "HttpStatusCodes"]
3
+ "sources": ["../src/main.ts"],
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 {packageTracer} from '@alwatr/package-tracer';\nimport {parseDuration} from '@alwatr/parse-duration';\n\nimport type {AlwatrFetchOptions_, FetchOptions} from './type.js';\n\nexport {cacheSupported};\nexport type * from './type.js';\n\n__dev_mode__: packageTracer.add(__package_name__, __package_version__);\n\nconst logger_ = /* #__PURE__ */ createLogger('@alwatr/fetch');\nconst globalThis_ = /* #__PURE__ */ getGlobalThis();\n\n/**\n * A boolean flag indicating whether the browser's Cache API is supported.\n */\nconst cacheSupported = /* #__PURE__ */ 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": ";;;AAQA,SAAQ,aAAY;AACpB,SAAQ,qBAAoB;AAC5B,SAAQ,iBAAiB,iBAAgB;AACzC,SAAQ,oBAAmB;AAC3B,SAAQ,qBAAoB;AAC5B,SAAQ,qBAAoB;AAO5B,aAAc,eAAc,IAAI,iBAAkB,OAAmB;AAErE,IAAM,UAA0B,6BAAa,eAAe;AAC5D,IAAM,cAA8B,8BAAc;AAKlD,IAAM,iBAAiC,uBAAO,OAAO,aAAa,QAAQ;AAO1E,IAAM,2BAA8D,CAAC;AAMrE,IAAM,sBAA2C;AAAA,EAC/C,QAAQ;AAAA,EACR,SAAS,CAAC;AAAA,EACV,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,kBAAkB;AACpB;AAiDO,SAAS,MAAM,KAAa,SAA0C;AAC3E,UAAQ,gBAAgB,SAAS,EAAC,KAAK,QAAO,CAAC;AAE/C,QAAM,WAA2B;AAAA,IAC/B,GAAG;AAAA,IACH,GAAG;AAAA,IACH;AAAA,EACF;AAEA,WAAS,WAAW;AAEpB,MAAI,SAAS,oBAAoB,QAAQ;AACvC,aAAS,kBAAkB,iBAAiB,eAAe;AAAA,EAC7D;AAGA,MAAI,SAAS,IAAI,YAAY,GAAG,MAAM,MAAM,SAAS,eAAe,MAAM;AACxE,UAAM,cAAc,SAAS;AAE7B,UAAM,aAAa,OAChB,KAAK,WAAW,EAChB,IAAI,SAAO,GAAG,mBAAmB,GAAG,CAAC,IAAI,mBAAmB,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE;AAE1F,QAAI,WAAW,SAAS,GAAG;AACzB,eAAS,OAAO,MAAM,WAAW,KAAK,GAAG;AAAA,IAC3C;AAAA,EACF;AAGA,MAAI,SAAS,aAAa,QAAW;AACnC,aAAS,OAAO,KAAK,UAAU,SAAS,QAAQ;AAChD,aAAS,QAAQ,cAAc,IAAI,UAAU;AAAA,EAC/C;AAGA,MAAI,SAAS,gBAAgB,QAAW;AACtC,aAAS,QAAQ,gBAAgB,UAAU,SAAS,WAAW;AAAA,EACjE,WACS,SAAS,eAAe,QAAW;AAC1C,aAAS,QAAQ,gBAAgB,UAAU,SAAS,WAAW,MAAM,IAAI,SAAS,WAAW,SAAS;AAAA,EACxG;AAEA,UAAQ,cAAc,iBAAiB,QAAQ;AAG/C,SAAO,qBAAqB,QAAQ;AACtC;AAWA,eAAe,qBAAqB,SAA4C;AAC9E,MAAI,QAAQ,kBAAkB,gBAAgB;AAC5C,WAAO,uBAAuB,OAAO;AAAA,EACvC;AAGA,UAAQ,YAAY,sBAAsB;AAE1C,MAAI,CAAC,gBAAgB;AACnB,YAAQ,WAAW,SAAS,oCAAoC;AAAA,MAC9D;AAAA,IACF,CAAC;AAED,YAAQ,gBAAgB;AACxB,WAAO,uBAAuB,OAAO;AAAA,EACvC;AAGA,QAAM,eAAe,MAAM,OAAO,KAAK,QAAQ,gBAAgB;AAE/D,QAAM,UAAU,IAAI,QAAQ,QAAQ,KAAK,OAAO;AAEhD,UAAQ,QAAQ,eAAe;AAAA,IAC7B,KAAK,eAAe;AAClB,YAAM,iBAAiB,MAAM,aAAa,MAAM,OAAO;AACvD,UAAI,kBAAkB,MAAM;AAC1B,eAAO;AAAA,MACT;AAGA,YAAM,WAAW,MAAM,uBAAuB,OAAO;AACrD,UAAI,SAAS,IAAI;AACf,qBAAa,IAAI,SAAS,SAAS,MAAM,CAAC;AAAA,MAC5C;AACA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,cAAc;AACjB,YAAM,iBAAiB,MAAM,aAAa,MAAM,OAAO;AACvD,UAAI,kBAAkB,MAAM;AAC1B,gBAAQ,SAAS,wBAAwB,yBAAyB,EAAC,KAAK,QAAQ,IAAG,CAAC;AACpF,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAGA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,iBAAiB;AACpB,UAAI;AACF,cAAM,kBAAkB,MAAM,uBAAuB,OAAO;AAC5D,YAAI,gBAAgB,IAAI;AACtB,uBAAa,IAAI,SAAS,gBAAgB,MAAM,CAAC;AAAA,QACnD;AACA,eAAO;AAAA,MACT,SACO,KAAK;AACV,cAAM,iBAAiB,MAAM,aAAa,MAAM,OAAO;AACvD,YAAI,kBAAkB,MAAM;AAC1B,iBAAO;AAAA,QACT;AAGA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,kBAAkB,MAAM,uBAAuB,OAAO;AAC5D,UAAI,gBAAgB,IAAI;AACtB,qBAAa,IAAI,SAAS,gBAAgB,MAAM,CAAC;AAAA,MACnD;AACA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,0BAA0B;AAC7B,YAAM,iBAAiB,MAAM,aAAa,MAAM,OAAO;AACvD,YAAM,yBAAyB,uBAAuB,OAAO,EAAE,KAAK,CAAC,oBAAoB;AACvF,YAAI,gBAAgB,IAAI;AACtB,uBAAa,IAAI,SAAS,gBAAgB,MAAM,CAAC;AACjD,cAAI,OAAO,QAAQ,uBAAuB,YAAY;AACpD,uBAAW,QAAQ,oBAAoB,GAAG,gBAAgB,MAAM,CAAC;AAAA,UACnE;AAAA,QACF;AACA,eAAO;AAAA,MACT,CAAC;AAED,aAAO,kBAAkB;AAAA,IAC3B;AAAA,IAEA,SAAS;AACP,aAAO,uBAAuB,OAAO;AAAA,IACvC;AAAA,EACF;AACF;AAaA,eAAe,uBAAuB,SAA4C;AAChF,MAAI,QAAQ,oBAAoB,SAAS;AACvC,WAAO,oBAAoB,OAAO;AAAA,EACpC;AAGA,UAAQ,YAAY,wBAAwB;AAI5C,QAAM,aAAa,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AACrE,QAAM,WAAW,GAAG,QAAQ,MAAM,IAAI,QAAQ,GAAG,IAAI,UAAU;AAG/D,2BAAyB,QAAQ,MAAM,oBAAoB,OAAO;AAElE,MAAI;AAEF,UAAM,WAAW,MAAM,yBAAyB,QAAQ;AAGxD,QAAI,yBAAyB,QAAQ,KAAK,MAAM;AAC9C,UAAI,SAAS,OAAO,QAAQ,QAAQ,oBAAoB,cAAc;AAEpE,eAAO,yBAAyB,QAAQ;AAAA,MAC1C;AAAA,IACF;AAGA,WAAO,SAAS,MAAM;AAAA,EACxB,SACO,KAAK;AAEV,WAAO,yBAAyB,QAAQ;AACxC,UAAM;AAAA,EACR;AACF;AAWA,eAAe,oBAAoB,SAA4C;AAC7E,MAAI,EAAE,QAAQ,QAAQ,IAAI;AACxB,WAAO,eAAe,OAAO;AAAA,EAC/B;AAGA,UAAQ,YAAY,qBAAqB;AACzC,UAAQ;AAER,QAAM,sBAAsB,QAAQ;AAEpC,MAAI;AACF,UAAM,WAAW,MAAM,eAAe,OAAO;AAG7C,QAAI,SAAS,SAAS,gBAAgB,wCAAwC;AAC5E,aAAO;AAAA,IACT;AAGA,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC,SACO,KAAK;AACV,YAAQ,SAAS,SAAS,sBAAsB,GAAG;AAGnD,QAAI,YAAY,WAAW,WAAW,OAAO;AAC3C,cAAQ,SAAS,uBAAuB,WAAW,4BAA4B;AAC/E,YAAM;AAAA,IACR;AAEA,UAAM,MAAM,GAAG,QAAQ,UAAU;AAGjC,YAAQ,SAAS;AACjB,WAAO,oBAAoB,OAAO;AAAA,EACpC;AACF;AAYA,SAAS,eAAe,SAA4C;AAClE,MAAI,QAAQ,YAAY,GAAG;AAEzB,WAAO,YAAY,MAAM,QAAQ,KAAK,OAAO;AAAA,EAC/C;AAEA,UAAQ,YAAY,gBAAgB;AAEpC,SAAO,IAAI,QAAQ,CAAC,UAAU,WAAW;AACvC,UAAM,kBAAkB,OAAO,oBAAoB,aAAa,IAAI,gBAAgB,IAAI;AACxF,UAAM,sBAAsB,QAAQ;AACpC,YAAQ,SAAS,iBAAiB;AAGlC,QAAI,oBAAoB,QAAQ,uBAAuB,MAAM;AAC3D,0BAAoB,iBAAiB,SAAS,MAAM,gBAAgB,MAAM,GAAG,EAAC,MAAM,KAAI,CAAC;AAAA,IAC3F;AAEA,UAAM,YAAY,WAAW,MAAM;AACjC,aAAO,IAAI,MAAM,eAAe,CAAC;AACjC,uBAAiB,MAAM,eAAe;AAAA,IACxC,GAAG,cAAc,QAAQ,OAAQ,CAAC;AAElC,gBACG,MAAM,QAAQ,KAAK,OAAO,EAC1B,KAAK,CAAC,aAAa,SAAS,QAAQ,CAAC,EACrC,MAAM,CAAC,WAAW,OAAO,MAAM,CAAC,EAChC,QAAQ,MAAM;AAEb,mBAAa,SAAS;AAAA,IACxB,CAAC;AAAA,EACL,CAAC;AACH;",
6
+ "names": []
7
7
  }
package/dist/type.d.ts CHANGED
@@ -1,129 +1,103 @@
1
- import type { HttpMethod, HttpRequestHeaders, HttpStatusCode } from '@alwatr/http-primer';
1
+ import type { HttpMethod, HttpRequestHeaders } from '@alwatr/http-primer';
2
2
  import type { Duration } from '@alwatr/parse-duration';
3
3
  /**
4
- * Represents a dictionary of query parameters.
5
- * The keys are strings and the values can be strings, numbers, or booleans.
4
+ * A dictionary of query parameters.
5
+ * Keys are strings, and values can be strings, numbers, or booleans.
6
6
  */
7
7
  export type QueryParams = DictionaryOpt<string | number | boolean>;
8
8
  /**
9
- * Represents the cache strategy for fetching data.
9
+ * Defines the caching strategy for a fetch request.
10
10
  *
11
- * - 'network_only': Fetches data from the network only.
12
- * - 'network_first': Tries to fetch data from the network first, and falls back to the cache if the network request fails.
13
- * - 'cache_only': Fetches data from the cache only.
14
- * - 'cache_first': Tries to fetch data from the cache first, and falls back to the network if the cache request fails.
15
- * - 'update_cache': Fetches data from the network and updates the cache with the new data.
16
- * - 'stale_while_revalidate': Returns the stale data from the cache while fetching updated data from the network.
11
+ * - `network_only`: Always fetches from the network.
12
+ * - `network_first`: Tries the network first, then falls back to the cache.
13
+ * - `cache_only`: Only fetches from the cache; fails if not found.
14
+ * - `cache_first`: Tries the cache first, then falls back to the network.
15
+ * - `update_cache`: Fetches from the network and updates the cache.
16
+ * - `stale_while_revalidate`: Serves from cache while revalidating in the background.
17
17
  */
18
18
  export type CacheStrategy = 'network_only' | 'network_first' | 'cache_only' | 'cache_first' | 'update_cache' | 'stale_while_revalidate';
19
19
  /**
20
- * Represents the caching behavior for duplicate requests.
21
- * - 'never': The response will not be cached.
22
- * - 'always': The response will always be cached.
23
- * - 'until_load': The response will be cached until the page is reloaded.
24
- * - 'auto': The caching behavior will be determined automatically.
20
+ * Defines the caching behavior for identical, parallel requests.
21
+ * - `never`: No deduplication is performed.
22
+ * - `always`: The response is cached for the lifetime of the application.
23
+ * - `until_load`: The response is cached until the initial request is complete.
24
+ * - `auto`: Automatically selects the best strategy (`until_load` in browsers, `always` otherwise).
25
25
  */
26
26
  export type CacheDuplicate = 'never' | 'always' | 'until_load' | 'auto';
27
27
  /**
28
- * Options for the fetch request.
28
+ * Defines the options for an Alwatr fetch request.
29
29
  */
30
- export interface FetchOptions extends RequestInit {
30
+ export interface AlwatrFetchOptions_ {
31
31
  /**
32
- * Request URL.
33
- */
34
- url: string;
35
- /**
36
- * A string to set the request's method.
37
- *
32
+ * The HTTP request method.
38
33
  * @default 'GET'
39
34
  */
40
- method?: HttpMethod;
35
+ method: HttpMethod;
41
36
  /**
42
- * A Headers object to set the request's headers.
37
+ * An object of request headers.
43
38
  */
44
- headers?: Record<string, string> & HttpRequestHeaders;
39
+ headers: HttpRequestHeaders & DictionaryReq<string>;
45
40
  /**
46
- * A timeout for the fetch request.
47
- * Set `0` to disable it.
48
- *
49
- * Use with caution, as it may cause memory leaks in Node.js.
50
- *
41
+ * Request timeout duration. Can be a number (milliseconds) or a string (e.g., '5s').
42
+ * Set to `0` to disable.
51
43
  * @default '8s'
52
44
  */
53
- timeout?: Duration;
45
+ timeout: Duration;
54
46
  /**
55
- * If the fetch response is not acceptable or timed out, it will retry the request.
56
- *
47
+ * Number of times to retry a failed request.
48
+ * Retries occur on network errors, timeouts, or 5xx server responses.
57
49
  * @default 3
58
50
  */
59
- retry?: number;
51
+ retry: number;
60
52
  /**
61
- * Delay before each retry.
62
- *
53
+ * Delay before each retry attempt. Can be a number (milliseconds) or a string (e.g., '2s').
63
54
  * @default '1s'
64
55
  */
65
- retryDelay?: Duration;
56
+ retryDelay: Duration;
66
57
  /**
67
- * Simple memory caching to remove duplicate/parallel requests.
68
- *
69
- * - `never`: Never use memory caching.
70
- * - `always`: Always use memory caching and remove all duplicate requests.
71
- * - `until_load`: Cache parallel requests until the request is completed (it will be removed after the promise is resolved).
72
- * - `auto`: If CacheStorage is supported, use `until_load` strategy; otherwise, use `always`.
73
- *
58
+ * Strategy for handling duplicate parallel requests.
59
+ * Uniqueness is determined by method, URL, and request body.
74
60
  * @default 'never'
75
61
  */
76
- removeDuplicate?: CacheDuplicate;
62
+ removeDuplicate: CacheDuplicate;
77
63
  /**
78
- * Strategies for caching.
79
- *
80
- * - `network_only`: Only network request without any cache.
81
- * - `network_first`: Network first, falling back to cache.
82
- * - `cache_only`: Cache only without any network request.
83
- * - `cache_first`: Cache first, falling back to network.
84
- * - `update_cache`: Like `network_only` but with update cache.
85
- * - `stale_while_revalidate`: Fastest strategy, use cached first but always request network to update the cache.
86
- *
64
+ * The caching strategy to use for the request.
65
+ * Requires a browser environment with Cache API support.
87
66
  * @default 'network_only'
88
67
  */
89
- cacheStrategy?: CacheStrategy;
68
+ cacheStrategy: CacheStrategy;
90
69
  /**
91
- * Revalidate callback for `stale_while_revalidate` cache strategy.
70
+ * A callback function that is executed with the fresh response when using the 'stale_while_revalidate' cache strategy.
92
71
  */
93
72
  revalidateCallback?: (response: Response) => void | Promise<void>;
94
73
  /**
95
- * Custom name for the cache storage.
74
+ * Custom name for the CacheStorage instance.
75
+ * @default 'fetch_cache'
96
76
  */
97
- cacheStorageName?: string;
77
+ cacheStorageName: string;
98
78
  /**
99
- * Body as a JavaScript object.
79
+ * A JavaScript object to be sent as the request's JSON body.
80
+ * Automatically sets the 'Content-Type' header to 'application/json'.
100
81
  */
101
82
  bodyJson?: Json;
102
83
  /**
103
- * URL query parameters as a JavaScript object.
84
+ * A JavaScript object of query parameters to be appended to the request URL.
104
85
  */
105
86
  queryParams?: QueryParams;
106
87
  /**
107
- * Add token to the Authentication bearer header.
88
+ * A bearer token to be added to the 'Authorization' header.
108
89
  */
109
90
  bearerToken?: string;
110
91
  /**
111
- * Alwatr token scheme
92
+ * Alwatr-specific authentication credentials.
112
93
  */
113
94
  alwatrAuth?: {
114
95
  userId: string;
115
96
  userToken: string;
116
97
  };
117
98
  }
118
- export type ResponseSuccess<T extends JsonObject> = T & {
119
- ok: true;
120
- statusCode: HttpStatusCode;
121
- };
122
- export type ResponseError = {
123
- ok: false;
124
- statusCode: HttpStatusCode;
125
- errorCode: string;
126
- errorMessage: string;
127
- meta?: Json;
128
- };
99
+ /**
100
+ * Combined type for fetch options, including standard RequestInit properties.
101
+ */
102
+ export type FetchOptions = Partial<AlwatrFetchOptions_> & Omit<RequestInit, 'headers'>;
129
103
  //# sourceMappingURL=type.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACxF,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,eAAe,GAAG,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,wBAAwB,CAAC;AAExI;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,MAAM,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,kBAAkB,CAAC;IAEtD;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC;IAEnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;OAIG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC;IAEtB;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,cAAc,CAAC;IAEjC;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;OAEG;IACH,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,EAAE,IAAI,CAAC;IAEhB;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,CAAC,EAAE;QACX,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,GAAG;IACtD,EAAE,EAAE,IAAI,CAAC;IACT,UAAU,EAAE,cAAc,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,KAAK,CAAC;IACV,UAAU,EAAE,cAAc,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IAErB,IAAI,CAAC,EAAE,IAAI,CAAC;CACb,CAAC"}
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,kBAAkB,EAAC,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,eAAe,GAAG,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,wBAAwB,CAAC;AAExI;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,MAAM,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,MAAM,EAAE,UAAU,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,kBAAkB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAEpD;;;;OAIG;IACH,OAAO,EAAE,QAAQ,CAAC;IAElB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,UAAU,EAAE,QAAQ,CAAC;IAErB;;;;OAIG;IACH,eAAe,EAAE,cAAc,CAAC;IAEhC;;;;OAIG;IACH,aAAa,EAAE,aAAa,CAAC;IAE7B;;OAEG;IACH,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,IAAI,CAAC;IAEhB;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,CAAC,EAAE;QACX,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@alwatr/fetch",
3
- "description": "Enhanced fetch API with cache strategy, retry pattern, timeout, helper methods and enhanced types.",
4
- "version": "5.6.6",
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.0",
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": "5.5.9",
9
- "@alwatr/global-this": "5.5.7",
10
- "@alwatr/http-primer": "5.5.7",
11
- "@alwatr/logger": "5.5.7",
12
- "@alwatr/package-tracer": "5.5.7",
13
- "@alwatr/parse-duration": "5.5.8"
8
+ "@alwatr/delay": "5.5.10",
9
+ "@alwatr/global-this": "5.5.8",
10
+ "@alwatr/http-primer": "6.0.0",
11
+ "@alwatr/logger": "5.5.8",
12
+ "@alwatr/package-tracer": "5.5.8",
13
+ "@alwatr/parse-duration": "5.5.9"
14
14
  },
15
15
  "devDependencies": {
16
- "@alwatr/nano-build": "6.0.2",
16
+ "@alwatr/nano-build": "6.0.3",
17
17
  "@alwatr/prettier-config": "5.0.2",
18
18
  "@alwatr/tsconfig-base": "5.0.2",
19
19
  "@alwatr/type-helper": "5.4.4",
20
- "jest": "^30.1.2",
20
+ "jest": "^30.1.3",
21
21
  "typescript": "^5.9.2"
22
22
  },
23
23
  "exports": {
@@ -85,5 +85,5 @@
85
85
  },
86
86
  "type": "module",
87
87
  "types": "./dist/main.d.ts",
88
- "gitHead": "6f70c2ae343582774a7fa8694684fabb4c5ce63c"
88
+ "gitHead": "aa66746a2c490dbdb1a401b520946cc45bf51eaf"
89
89
  }