@enegalan/request-manager 1.0.10 → 1.1.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/README.md CHANGED
@@ -71,7 +71,7 @@ Pick the **dedicated helper** for your HTTP client. Use `request()` only when no
71
71
  | Client | Use this | Why |
72
72
  | --------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------ |
73
73
  | `fetch` | **`fetch(url, options)`** | Creates the AbortSignal and passes it to `fetch` for you |
74
- | `axios` | **`axios(url, options, axiosInstance?)`** | Creates axios `CancelToken` and wires cancel for you |
74
+ | `axios` | **`axios(url, options, axiosInstance?)`** | Creates an `AbortSignal` and wires cancel for you (axios ≥ 0.22) |
75
75
  | jQuery `.ajax`, Ext.Ajax, similar | **`ajax(ajaxFunction, url, options)`** | Runs your ajax function, then wires abort for you (`req.abort`, `Ext.Ajax.abort(req)`, or `xhr.abort`) |
76
76
  | Raw `XMLHttpRequest` | **`xhr(url, options)`** | Owns open/send and abort lifecycle |
77
77
  | Custom / already-started Promise | **`request(url, promiseOrFn, options)`** | Escape hatch — **you** must pass `signal` / `cancelToken` / `addAbortListener` |
@@ -427,7 +427,7 @@ Executes an HTTP request using axios, cancelling any previous request with the s
427
427
 
428
428
  **Returns:** Promise that resolves/rejects based on the most recent request
429
429
 
430
- **Note:** This method automatically creates a CancelToken for axios cancellation. The request ID is automatically generated from the cleaned URL unless `requestKey` is specified. When `noCancel` is true, a unique ID is generated for each request.
430
+ **Note:** This method automatically creates an AbortController and passes its `signal` in the axios config, so cancellation requires axios ≥ 0.22. The request ID is automatically generated from the cleaned URL unless `requestKey` is specified. When `noCancel` is true, a unique ID is generated for each request.
431
431
 
432
432
  **Example:**
433
433
 
@@ -13,7 +13,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
13
13
  class RequestManager {
14
14
  constructor(options = {}) {
15
15
  /**
16
- * Map to store active requests by their unique identifier.
17
16
  * @type {Map<string, import('./index.d.ts').ActiveRequest>}
18
17
  */
19
18
  this.activeRequests = new Map();
@@ -101,15 +100,14 @@ class RequestManager {
101
100
  * @returns {Promise} A Promise that resolves/rejects based on the most recent request
102
101
  * @example
103
102
  * // Request with Promise
104
- * requestManager.request('/api/users', axios.get('/api/users', { cancelToken: axios.CancelToken.source().token }));
103
+ * requestManager.request('/api/users', axios.get('/api/users'));
105
104
  * @example
106
105
  * // Request with Function
107
106
  * requestManager.request('/api/users', ({ options }) => fetch('/api/users', { signal: options.signal, ...options }));
108
107
  * @example
109
108
  * // Request with Promise and custom cancellation grouping with requestKey
110
109
  * const options = {
111
- * requestKey: 'get-users',
112
- * cancelToken: axios.CancelToken.source().cancel
110
+ * requestKey: 'get-users'
113
111
  * }
114
112
  * requestManager.request('/api/users', axios.get('/api/users', options), options);
115
113
  */
@@ -170,12 +168,11 @@ class RequestManager {
170
168
  */
171
169
  axios(url, options = {}, axiosInstance = null) {
172
170
  const axiosLib = axiosInstance || axios;
173
- const cancelToken = axiosLib.CancelToken.source();
174
- const requestId = this.getRequestId(url, options);
175
- return this.#_request(requestId, axiosLib({ url, cancelToken: cancelToken.token, ...options }), {
176
- cancelToken: cancelToken,
177
- ...options,
178
- });
171
+ return this.#_request(
172
+ this.getRequestId(url, options),
173
+ ({ options: requestOptions }) => axiosLib({ url, ...requestOptions }),
174
+ options
175
+ );
179
176
  }
180
177
 
181
178
  /**
@@ -244,14 +241,13 @@ class RequestManager {
244
241
  let response = xhr.response;
245
242
  if (
246
243
  options.responseType === 'json' ||
247
- (xhr.getResponseHeader('Content-Type') &&
248
- xhr.getResponseHeader('Content-Type').includes('application/json'))
244
+ ((!options.responseType || options.responseType === 'text') &&
245
+ xhr.getResponseHeader('Content-Type')?.includes('application/json') &&
246
+ typeof response === 'string')
249
247
  ) {
250
248
  try {
251
- response = JSON.parse(xhr.responseText);
252
- } catch {
253
- response = xhr.responseText;
254
- }
249
+ response = JSON.parse(response);
250
+ } catch {}
255
251
  }
256
252
  resolve({
257
253
  data: response,
@@ -1 +1 @@
1
- {"version":3,"file":"request-manager.cjs.js","sources":["../main.js"],"sourcesContent":["/**\n * RequestManager - A library for managing and regulating HTTP requests efficiently.\n * @license MIT\n * @author Eneko Galan <enekogalanelorza@gmail.com>\n * This library allows you to manage HTTP requests from any library (ajax, Ext.Ajax, axios, fetch, etc.)\n * by accepting Promises as parameters. When a request is repeated with the same identifier,\n * the previous request is automatically cancelled and the new one is executed, giving priority to the most recent requests.\n */\nclass RequestManager {\n constructor(options = {}) {\n /**\n * Map to store active requests by their unique identifier.\n * @type {Map<string, import('./index.d.ts').ActiveRequest>}\n */\n this.activeRequests = new Map();\n /**\n * @type {import('./index.d.ts').Options}\n */\n this.options = options;\n /**\n * One-shot AbortController for getSignal()/getAbortController() handoff.\n * Consumed by the next request that does not pass options.abortController.\n * @type {AbortController|null}\n */\n this.abortController = null;\n }\n\n /**\n * Gets the manager options\n * @returns {import('./index.d.ts').Options} Manager options\n */\n getOptions() {\n return this.options;\n }\n\n /**\n * Sets the manager options\n * @param {import('./index.d.ts').Options} options - The options to set\n */\n setOptions(options) {\n this.options = options;\n }\n\n /**\n * Creates a new AbortController and returns its signal for the next request()\n * (one getSignal → one request). Do not use for parallel requests; use fetch(),\n * axios(), or request(url, ({ options }) => ...) instead — they create their own signal.\n * @returns {AbortSignal} The signal from a new AbortController\n * @example\n * const signal = requestManager.getSignal();\n * requestManager.request('/api/users', fetch('/api/users', { signal }));\n */\n getSignal() {\n return this.getAbortController().signal;\n }\n\n /**\n * Creates a new AbortController for the next request handoff.\n * Always returns a fresh controller (never reuses one from another in-flight request).\n * @returns {AbortController} A new AbortController instance\n */\n getAbortController() {\n this.abortController = new AbortController();\n return this.abortController;\n }\n\n /**\n * Checks if a request with the given identifier is currently active.\n * @param {string} requestId - The unique identifier to check\n * @returns {boolean} True if the request is active, false otherwise\n */\n isActive(requestId) {\n return this.activeRequests.has(requestId);\n }\n\n /**\n * Gets the number of active requests.\n * @returns {number} The number of currently active requests\n */\n getActiveCount() {\n return this.activeRequests.size;\n }\n\n /**\n * Clears all active requests without cancelling them.\n * Use with caution - this will not cancel the underlying HTTP requests.\n */\n clear() {\n this.activeRequests.clear();\n }\n\n /**\n * Executes an HTTP request, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {Promise|import('./index.d.ts').RequestFunction|string} requestPromise - The request promise or function that returns a promise\n * @param {import('./index.d.ts').RequestOptions} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Request with Promise\n * requestManager.request('/api/users', axios.get('/api/users', { cancelToken: axios.CancelToken.source().token }));\n * @example\n * // Request with Function\n * requestManager.request('/api/users', ({ options }) => fetch('/api/users', { signal: options.signal, ...options }));\n * @example\n * // Request with Promise and custom cancellation grouping with requestKey\n * const options = {\n * requestKey: 'get-users',\n * cancelToken: axios.CancelToken.source().cancel\n * }\n * requestManager.request('/api/users', axios.get('/api/users', options), options);\n */\n request(url, requestPromise, options = {}) {\n return this.#_request(this.getRequestId(url, options), requestPromise, options);\n }\n\n /**\n * Executes an HTTP request using fetch, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to fetch\n * @param {import('./index.d.ts').FetchOptions} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.fetch('/api/users');\n * @example\n * // POST request with options\n * requestManager.fetch('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.fetch('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n fetch(url, options = {}) {\n return this.#_request(this.getRequestId(url, options), url, options);\n }\n\n /**\n * Executes an HTTP request using axios, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').AxiosRequestOptions} options - Optional configuration\n * @param {import('./index.d.ts').AxiosInstance|import('./index.d.ts').AxiosStatic|null} axiosInstance - Optional axios instance to use. If not provided, uses global axios.\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request (uses global axios)\n * requestManager.axios('/api/users');\n * @example\n * // With custom axios instance\n * const myAxios = axios.create({ baseURL: 'https://api.example.com' });\n * requestManager.axios('/users', {}, myAxios);\n * @example\n * // POST request with options\n * requestManager.axios('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.axios('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n axios(url, options = {}, axiosInstance = null) {\n const axiosLib = axiosInstance || axios;\n const cancelToken = axiosLib.CancelToken.source();\n const requestId = this.getRequestId(url, options);\n return this.#_request(requestId, axiosLib({ url, cancelToken: cancelToken.token, ...options }), {\n cancelToken: cancelToken,\n ...options,\n });\n }\n\n /**\n * Executes an HTTP request using jQuery.ajax, cancelling any previous request with the same identifier.\n * @param {import('./index.d.ts').AjaxFunction} ajaxFunction - A function that receives { url, ...options } and returns a Promise\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').BaseRequestOptions & Record<string, any>} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.ajax(ajaxFunction, '/api/users');\n * @example\n * // POST request with options\n * requestManager.ajax(ajaxFunction, '/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.ajax(ajaxFunction, '/api/users', {\n * requestKey: 'get-users'\n * });\n */\n ajax(ajaxFunction, url, options = {}) {\n if (typeof ajaxFunction !== 'function') throw new Error('ajaxFunction parameter must be a function');\n return this.#_request(\n this.getRequestId(url, options),\n ({ options: requestOptions }) => ajaxFunction({ url, ...requestOptions }),\n options\n );\n }\n\n /**\n * Executes an HTTP request using XMLHttpRequest, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').XhrOptions} options - Optional configuration\n * @returns {Promise<import('./index.d.ts').XhrResponse>} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.xhr('/api/users');\n * @example\n * // POST request with options\n * requestManager.xhr('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping\n * requestManager.xhr('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n xhr(url, options = {}) {\n const requestId = this.getRequestId(url, options);\n /** @type {import('./index.d.ts').RequestFunction<import('./index.d.ts').XhrResponse>} */\n const xhrFunction = ({ options: fetchOptions }) => {\n // Create XMLHttpRequest\n const xhr = new XMLHttpRequest();\n const method = (options.method || 'GET').toUpperCase();\n // Create a promise that wraps the XHR request\n const xhrPromise = new Promise((resolve, reject) => {\n xhr.onload = function () {\n if (xhr.status >= 200 && xhr.status < 300) {\n let response = xhr.response;\n if (\n options.responseType === 'json' ||\n (xhr.getResponseHeader('Content-Type') &&\n xhr.getResponseHeader('Content-Type').includes('application/json'))\n ) {\n try {\n response = JSON.parse(xhr.responseText);\n } catch {\n response = xhr.responseText;\n }\n }\n resolve({\n data: response,\n status: xhr.status,\n statusText: xhr.statusText,\n headers: xhr.getAllResponseHeaders(),\n xhr: xhr,\n });\n } else {\n reject({\n message: `Request failed with status ${xhr.status}`,\n status: xhr.status,\n statusText: xhr.statusText,\n xhr: xhr,\n });\n }\n };\n xhr.onerror = function () {\n reject({\n message: 'Network error',\n xhr: xhr,\n });\n };\n xhr.ontimeout = function () {\n reject({\n message: 'Request timeout',\n xhr: xhr,\n });\n };\n\n // Open the request\n xhr.open(method, url, true);\n\n // Set response type\n if (options.responseType) xhr.responseType = options.responseType;\n // Set withCredentials\n if (options.withCredentials !== undefined) xhr.withCredentials = options.withCredentials;\n // Set timeout\n if (options.timeout !== undefined) xhr.timeout = options.timeout;\n // Set headers\n if (options.headers)\n Object.keys(options.headers).forEach((key) => {\n xhr.setRequestHeader(key, options.headers[key]);\n });\n\n // Connect abort signal to xhr.abort()\n if (fetchOptions.signal) fetchOptions.signal.addEventListener('abort', () => xhr.abort());\n\n // Send the request\n xhr.send(options.body || null);\n });\n return xhrPromise;\n };\n return this.#_request(requestId, xhrFunction, options);\n }\n\n /**\n * Returns the request identifier for a URL and options.\n * @param {string} url - The URL used when starting the request\n * @param {import('./index.d.ts').BaseRequestOptions} options - Same options used for the request\n * @returns {string} The request identifier\n * @example\n * requestManager.fetch('/api/users');\n * const id = requestManager.getRequestId('/api/users');\n * requestManager.cancel(id);\n */\n getRequestId(url, options = {}) {\n let requestKey = options.requestKey;\n\n const prefix = 'request_';\n\n // Generate a unique identifier to prevent cancellation for non cancelable requests\n if (options.noCancel) {\n return `${prefix}${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n }\n\n // Handle function requestKey\n if (typeof requestKey === 'function') {\n try {\n requestKey = requestKey();\n } catch {\n requestKey = null;\n }\n }\n if (requestKey !== null && requestKey !== undefined) return `${prefix}${String(requestKey)}`;\n\n // Use cleaned URL as key as fallback\n let cleanedUrl = url || '';\n if (cleanedUrl.includes('://')) cleanedUrl = cleanedUrl.split('://')[1];\n if (cleanedUrl.includes('#')) cleanedUrl = cleanedUrl.split('#')[0];\n if (!options.includeQuery && cleanedUrl.includes('?')) cleanedUrl = cleanedUrl.split('?')[0];\n return `${prefix}${cleanedUrl}`;\n }\n\n /**\n * Cancels a specific request by its identifier.\n * @param {string} requestId - The unique identifier of the request to cancel\n * @returns {boolean} True if the request was found and cancelled, false otherwise\n */\n cancel(requestId) {\n /** @type {import('./index.d.ts').ActiveRequest|undefined} */\n const requestInfo = this.activeRequests.get(requestId);\n if (!requestInfo) return false;\n\n requestInfo.isCancelled = true; // Mark as cancelled\n\n // Try to abort using AbortController (for fetch)\n if (requestInfo.abortController && !requestInfo.abortController.signal.aborted) {\n try {\n requestInfo.abortController.abort('Request was cancelled');\n } catch (error) {}\n }\n\n // Try to cancel using cancel token/function (for axios and others)\n if (requestInfo.cancelToken) {\n try {\n if (typeof requestInfo.cancelToken === 'function') requestInfo.cancelToken();\n else if (requestInfo.cancelToken.cancel) requestInfo.cancelToken.cancel();\n } catch (error) {}\n }\n\n // Reject the wrapper promise\n this.#_deleteRequest(\n requestId,\n requestInfo.rejectWrapper,\n this.getOptions().verbose ? new Error(`Request ${requestId} was cancelled`) : null\n );\n return true;\n }\n\n /**\n * Link abort signal with HTTP client abort method.\n * Useful for custom HTTP clients that only support the abort method to cancel requests.\n * @param {Function} abortMethod - The abort method to call when the signal is aborted\n * @param {AbortSignal} signal - The signal to listen to\n */\n addAbortListener(abortMethod, signal) {\n if (!abortMethod || !signal) return;\n signal.addEventListener('abort', () => {\n if (typeof abortMethod === 'function') {\n try {\n abortMethod();\n } catch (error) {}\n }\n });\n }\n\n /**\n * Cancels all active requests.\n * @returns {number} The number of requests that were cancelled\n */\n cancelAll() {\n const requestIds = Array.from(this.activeRequests.keys());\n let cancelledCount = 0;\n requestIds.forEach((requestId) => {\n if (this.cancel(requestId)) cancelledCount++;\n });\n return cancelledCount;\n }\n\n /**\n * Resolves the AbortController for a request: explicit option, pending handoff, or new.\n * Clears the pending handoff so concurrent requests do not share it.\n * @param {AbortController|undefined} provided - Optional AbortController from options\n * @returns {AbortController}\n * @private\n */\n #_resolveAbortController(provided) {\n const abortController = provided || this.abortController || new AbortController();\n this.abortController = null;\n return abortController;\n }\n\n /**\n * Picks the best abort callback for a client request object.\n * @param {Object} req - The request object\n * @returns {Function|null}\n * @private\n */\n #_resolveAbortMethod(req) {\n if (!req) return null;\n if (typeof req.abort === 'function') return () => req.abort();\n const ExtAjax =\n typeof globalThis !== 'undefined' && globalThis.Ext && globalThis.Ext.Ajax ? globalThis.Ext.Ajax : null;\n if (req.xhr && ExtAjax && typeof ExtAjax.abort === 'function') {\n return () => ExtAjax.abort(req);\n }\n if (req.xhr && typeof req.xhr.abort === 'function') return () => req.xhr.abort();\n return null;\n }\n\n /**\n * Prepares request options by merging options and removing custom properties\n * @param {import('./index.d.ts').RequestOptions} options - Configuration options\n * @param {AbortSignal} signal - Abort signal to add to request options\n * @returns {Object} Prepared request options\n * @private\n */\n #_prepareRequestOptions(options, signal) {\n const requestOptions = {};\n const customOptions = ['abortController', 'cancelToken', 'requestKey', 'noCancel', 'includeQuery'];\n Object.keys(options).forEach((key) => {\n if (customOptions.includes(key)) return;\n requestOptions[key] = options[key];\n });\n requestOptions.signal = signal;\n return requestOptions;\n }\n\n /**\n * Deletes a request from the active requests map and rejects the wrapper promise\n * @param {string} requestId - The unique identifier of the request\n * @param {Function} rejectWrapper - The function to reject the wrapper promise\n * @param {*} error - The error to reject the wrapper promise with; the wrapper is not rejected if null/undefined\n * @private\n */\n #_deleteRequest(requestId, rejectWrapper, error) {\n this.activeRequests.delete(requestId);\n if (error !== null && error !== undefined) {\n rejectWrapper(error);\n }\n }\n\n /**\n * Completes a request by deleting it from the active requests map and resolving the wrapper promise\n * @param {string} requestId - The unique identifier of the request\n * @param {Function} resolveWrapper - The function to resolve the wrapper promise\n * @param {Promise} requestPromise - The request promise\n * @param {boolean} isCancelled - Whether the request was cancelled\n * @private\n */\n #_completeRequest(requestId, resolveWrapper, requestPromise, isCancelled) {\n this.activeRequests.delete(requestId);\n if (!isCancelled) {\n resolveWrapper(requestPromise);\n }\n }\n\n /**\n * Internal method that handles the core request logic.\n * @param {string} requestId - Unique identifier for the request\n * @param {Promise|import('./index.d.ts').RequestFunction|string} requestPromise - The request promise, function, or URL string\n * @param {import('./index.d.ts').BaseRequestOptions} options - Configuration options\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @private\n */\n #_request(requestId, requestPromise, options = {}) {\n const abortController = this.#_resolveAbortController(options.abortController);\n\n // Handle different types of requestPromise inputs\n // Priority: Function (Custom logic) > String (URL) > Promise (axios, fetch, etc.)\n if (typeof requestPromise === 'function') {\n // Function: custom logic for any library (axios, ajax, etc.)\n try {\n requestPromise = requestPromise({\n options: this.#_prepareRequestOptions(options, abortController.signal),\n });\n } catch (error) {\n return Promise.reject(error);\n }\n } else if (typeof requestPromise === 'string') {\n // String (URL): make fetch internally\n try {\n requestPromise = fetch(requestPromise, this.#_prepareRequestOptions(options, abortController.signal));\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n // Link the request object's abort method (Ext.Ajax, XHR, etc.) to the cancellation signal\n this.addAbortListener(this.#_resolveAbortMethod(requestPromise), abortController.signal);\n\n // Cancel previous request with the same identifier if it exists\n if (!options.noCancel) this.cancel(requestId);\n\n // Create a wrapper promise that will be resolved/rejected based on the request\n let resolveWrapper, rejectWrapper;\n const wrapperPromise = new Promise((resolve, reject) => {\n resolveWrapper = resolve;\n rejectWrapper = reject;\n });\n\n /**\n * @type {import('./index.d.ts').ActiveRequest}\n */\n const requestInfo = {\n promise: requestPromise,\n abortController: abortController,\n cancelToken: options.cancelToken || null,\n resolveWrapper: resolveWrapper,\n rejectWrapper: rejectWrapper,\n isCancelled: false,\n };\n\n this.activeRequests.set(requestId, requestInfo);\n\n // Handle request promise completion\n if (requestPromise && typeof requestPromise.then === 'function') {\n try {\n let req = requestPromise.then((result) => {\n if (this.activeRequests.get(requestId) !== requestInfo) return;\n this.#_completeRequest(requestId, resolveWrapper, result, requestInfo.isCancelled);\n });\n if (req.catch)\n req.catch((error) => {\n onError(this, error);\n });\n } catch (error) {\n onError(this, error);\n }\n function onError(scope, error) {\n // Check if this requestInfo is still the active one, or if it was cancelled\n if (scope.activeRequests.get(requestId) !== requestInfo) return;\n if (requestInfo.isCancelled) {\n // Already cancelled: let cancel() handle cleanup and reject the wrapper promise\n scope.cancel(requestId);\n return;\n }\n // Only delete if this is still the active request\n scope.#_deleteRequest(requestId, rejectWrapper, error);\n }\n } else {\n // Non-promise (Ext.Ajax request object, raw XHR, etc.). Keep tracked until the\n // underlying XHR finishes so a later duplicate can still cancel it.\n const xhr =\n requestPromise &&\n (requestPromise.xhr ||\n (typeof XMLHttpRequest !== 'undefined' && requestPromise instanceof XMLHttpRequest\n ? requestPromise\n : null));\n const finish = () => {\n if (this.activeRequests.get(requestId) !== requestInfo) return;\n this.#_completeRequest(requestId, resolveWrapper, requestPromise, requestInfo.isCancelled);\n };\n if (xhr && typeof xhr.addEventListener === 'function') {\n xhr.addEventListener('loadend', finish);\n } else {\n setTimeout(finish, 0);\n }\n }\n return wrapperPromise;\n }\n}\n\nexport default RequestManager;\n\nexport { RequestManager };\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request-manager.cjs.js","sources":["../main.js"],"sourcesContent":["/**\n * RequestManager - A library for managing and regulating HTTP requests efficiently.\n * @license MIT\n * @author Eneko Galan <enekogalanelorza@gmail.com>\n * This library allows you to manage HTTP requests from any library (ajax, Ext.Ajax, axios, fetch, etc.)\n * by accepting Promises as parameters. When a request is repeated with the same identifier,\n * the previous request is automatically cancelled and the new one is executed, giving priority to the most recent requests.\n */\nclass RequestManager {\n constructor(options = {}) {\n /**\n * @type {Map<string, import('./index.d.ts').ActiveRequest>}\n */\n this.activeRequests = new Map();\n /**\n * @type {import('./index.d.ts').Options}\n */\n this.options = options;\n /**\n * One-shot AbortController for getSignal()/getAbortController() handoff.\n * Consumed by the next request that does not pass options.abortController.\n * @type {AbortController|null}\n */\n this.abortController = null;\n }\n\n /**\n * Gets the manager options\n * @returns {import('./index.d.ts').Options} Manager options\n */\n getOptions() {\n return this.options;\n }\n\n /**\n * Sets the manager options\n * @param {import('./index.d.ts').Options} options - The options to set\n */\n setOptions(options) {\n this.options = options;\n }\n\n /**\n * Creates a new AbortController and returns its signal for the next request()\n * (one getSignal → one request). Do not use for parallel requests; use fetch(),\n * axios(), or request(url, ({ options }) => ...) instead — they create their own signal.\n * @returns {AbortSignal} The signal from a new AbortController\n * @example\n * const signal = requestManager.getSignal();\n * requestManager.request('/api/users', fetch('/api/users', { signal }));\n */\n getSignal() {\n return this.getAbortController().signal;\n }\n\n /**\n * Creates a new AbortController for the next request handoff.\n * Always returns a fresh controller (never reuses one from another in-flight request).\n * @returns {AbortController} A new AbortController instance\n */\n getAbortController() {\n this.abortController = new AbortController();\n return this.abortController;\n }\n\n /**\n * Checks if a request with the given identifier is currently active.\n * @param {string} requestId - The unique identifier to check\n * @returns {boolean} True if the request is active, false otherwise\n */\n isActive(requestId) {\n return this.activeRequests.has(requestId);\n }\n\n /**\n * Gets the number of active requests.\n * @returns {number} The number of currently active requests\n */\n getActiveCount() {\n return this.activeRequests.size;\n }\n\n /**\n * Clears all active requests without cancelling them.\n * Use with caution - this will not cancel the underlying HTTP requests.\n */\n clear() {\n this.activeRequests.clear();\n }\n\n /**\n * Executes an HTTP request, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {Promise|import('./index.d.ts').RequestFunction|string} requestPromise - The request promise or function that returns a promise\n * @param {import('./index.d.ts').RequestOptions} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Request with Promise\n * requestManager.request('/api/users', axios.get('/api/users'));\n * @example\n * // Request with Function\n * requestManager.request('/api/users', ({ options }) => fetch('/api/users', { signal: options.signal, ...options }));\n * @example\n * // Request with Promise and custom cancellation grouping with requestKey\n * const options = {\n * requestKey: 'get-users'\n * }\n * requestManager.request('/api/users', axios.get('/api/users', options), options);\n */\n request(url, requestPromise, options = {}) {\n return this.#_request(this.getRequestId(url, options), requestPromise, options);\n }\n\n /**\n * Executes an HTTP request using fetch, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to fetch\n * @param {import('./index.d.ts').FetchOptions} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.fetch('/api/users');\n * @example\n * // POST request with options\n * requestManager.fetch('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.fetch('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n fetch(url, options = {}) {\n return this.#_request(this.getRequestId(url, options), url, options);\n }\n\n /**\n * Executes an HTTP request using axios, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').AxiosRequestOptions} options - Optional configuration\n * @param {import('./index.d.ts').AxiosInstance|import('./index.d.ts').AxiosStatic|null} axiosInstance - Optional axios instance to use. If not provided, uses global axios.\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request (uses global axios)\n * requestManager.axios('/api/users');\n * @example\n * // With custom axios instance\n * const myAxios = axios.create({ baseURL: 'https://api.example.com' });\n * requestManager.axios('/users', {}, myAxios);\n * @example\n * // POST request with options\n * requestManager.axios('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.axios('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n axios(url, options = {}, axiosInstance = null) {\n const axiosLib = axiosInstance || axios;\n return this.#_request(\n this.getRequestId(url, options),\n ({ options: requestOptions }) => axiosLib({ url, ...requestOptions }),\n options\n );\n }\n\n /**\n * Executes an HTTP request using jQuery.ajax, cancelling any previous request with the same identifier.\n * @param {import('./index.d.ts').AjaxFunction} ajaxFunction - A function that receives { url, ...options } and returns a Promise\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').BaseRequestOptions & Record<string, any>} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.ajax(ajaxFunction, '/api/users');\n * @example\n * // POST request with options\n * requestManager.ajax(ajaxFunction, '/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.ajax(ajaxFunction, '/api/users', {\n * requestKey: 'get-users'\n * });\n */\n ajax(ajaxFunction, url, options = {}) {\n if (typeof ajaxFunction !== 'function') throw new Error('ajaxFunction parameter must be a function');\n return this.#_request(\n this.getRequestId(url, options),\n ({ options: requestOptions }) => ajaxFunction({ url, ...requestOptions }),\n options\n );\n }\n\n /**\n * Executes an HTTP request using XMLHttpRequest, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').XhrOptions} options - Optional configuration\n * @returns {Promise<import('./index.d.ts').XhrResponse>} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.xhr('/api/users');\n * @example\n * // POST request with options\n * requestManager.xhr('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping\n * requestManager.xhr('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n xhr(url, options = {}) {\n const requestId = this.getRequestId(url, options);\n /** @type {import('./index.d.ts').RequestFunction<import('./index.d.ts').XhrResponse>} */\n const xhrFunction = ({ options: fetchOptions }) => {\n // Create XMLHttpRequest\n const xhr = new XMLHttpRequest();\n const method = (options.method || 'GET').toUpperCase();\n // Create a promise that wraps the XHR request\n const xhrPromise = new Promise((resolve, reject) => {\n xhr.onload = function () {\n if (xhr.status >= 200 && xhr.status < 300) {\n let response = xhr.response;\n if (\n options.responseType === 'json' ||\n ((!options.responseType || options.responseType === 'text') &&\n xhr.getResponseHeader('Content-Type')?.includes('application/json') &&\n typeof response === 'string')\n ) {\n try {\n response = JSON.parse(response);\n } catch {}\n }\n resolve({\n data: response,\n status: xhr.status,\n statusText: xhr.statusText,\n headers: xhr.getAllResponseHeaders(),\n xhr: xhr,\n });\n } else {\n reject({\n message: `Request failed with status ${xhr.status}`,\n status: xhr.status,\n statusText: xhr.statusText,\n xhr: xhr,\n });\n }\n };\n xhr.onerror = function () {\n reject({\n message: 'Network error',\n xhr: xhr,\n });\n };\n xhr.ontimeout = function () {\n reject({\n message: 'Request timeout',\n xhr: xhr,\n });\n };\n\n // Open the request\n xhr.open(method, url, true);\n\n // Set response type\n if (options.responseType) xhr.responseType = options.responseType;\n // Set withCredentials\n if (options.withCredentials !== undefined) xhr.withCredentials = options.withCredentials;\n // Set timeout\n if (options.timeout !== undefined) xhr.timeout = options.timeout;\n // Set headers\n if (options.headers)\n Object.keys(options.headers).forEach((key) => {\n xhr.setRequestHeader(key, options.headers[key]);\n });\n\n // Connect abort signal to xhr.abort()\n if (fetchOptions.signal) fetchOptions.signal.addEventListener('abort', () => xhr.abort());\n\n // Send the request\n xhr.send(options.body || null);\n });\n return xhrPromise;\n };\n return this.#_request(requestId, xhrFunction, options);\n }\n\n /**\n * Returns the request identifier for a URL and options.\n * @param {string} url - The URL used when starting the request\n * @param {import('./index.d.ts').BaseRequestOptions} options - Same options used for the request\n * @returns {string} The request identifier\n * @example\n * requestManager.fetch('/api/users');\n * const id = requestManager.getRequestId('/api/users');\n * requestManager.cancel(id);\n */\n getRequestId(url, options = {}) {\n let requestKey = options.requestKey;\n\n const prefix = 'request_';\n\n // Generate a unique identifier to prevent cancellation for non cancelable requests\n if (options.noCancel) {\n return `${prefix}${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n }\n\n // Handle function requestKey\n if (typeof requestKey === 'function') {\n try {\n requestKey = requestKey();\n } catch {\n requestKey = null;\n }\n }\n if (requestKey !== null && requestKey !== undefined) return `${prefix}${String(requestKey)}`;\n\n // Use cleaned URL as key as fallback\n let cleanedUrl = url || '';\n if (cleanedUrl.includes('://')) cleanedUrl = cleanedUrl.split('://')[1];\n if (cleanedUrl.includes('#')) cleanedUrl = cleanedUrl.split('#')[0];\n if (!options.includeQuery && cleanedUrl.includes('?')) cleanedUrl = cleanedUrl.split('?')[0];\n return `${prefix}${cleanedUrl}`;\n }\n\n /**\n * Cancels a specific request by its identifier.\n * @param {string} requestId - The unique identifier of the request to cancel\n * @returns {boolean} True if the request was found and cancelled, false otherwise\n */\n cancel(requestId) {\n /** @type {import('./index.d.ts').ActiveRequest|undefined} */\n const requestInfo = this.activeRequests.get(requestId);\n if (!requestInfo) return false;\n\n requestInfo.isCancelled = true; // Mark as cancelled\n\n // Try to abort using AbortController (for fetch)\n if (requestInfo.abortController && !requestInfo.abortController.signal.aborted) {\n try {\n requestInfo.abortController.abort('Request was cancelled');\n } catch (error) {}\n }\n\n // Try to cancel using cancel token/function (for axios and others)\n if (requestInfo.cancelToken) {\n try {\n if (typeof requestInfo.cancelToken === 'function') requestInfo.cancelToken();\n else if (requestInfo.cancelToken.cancel) requestInfo.cancelToken.cancel();\n } catch (error) {}\n }\n\n // Reject the wrapper promise\n this.#_deleteRequest(\n requestId,\n requestInfo.rejectWrapper,\n this.getOptions().verbose ? new Error(`Request ${requestId} was cancelled`) : null\n );\n return true;\n }\n\n /**\n * Link abort signal with HTTP client abort method.\n * Useful for custom HTTP clients that only support the abort method to cancel requests.\n * @param {Function} abortMethod - The abort method to call when the signal is aborted\n * @param {AbortSignal} signal - The signal to listen to\n */\n addAbortListener(abortMethod, signal) {\n if (!abortMethod || !signal) return;\n signal.addEventListener('abort', () => {\n if (typeof abortMethod === 'function') {\n try {\n abortMethod();\n } catch (error) {}\n }\n });\n }\n\n /**\n * Cancels all active requests.\n * @returns {number} The number of requests that were cancelled\n */\n cancelAll() {\n const requestIds = Array.from(this.activeRequests.keys());\n let cancelledCount = 0;\n requestIds.forEach((requestId) => {\n if (this.cancel(requestId)) cancelledCount++;\n });\n return cancelledCount;\n }\n\n /**\n * Resolves the AbortController for a request: explicit option, pending handoff, or new.\n * Clears the pending handoff so concurrent requests do not share it.\n * @param {AbortController|undefined} provided - Optional AbortController from options\n * @returns {AbortController}\n * @private\n */\n #_resolveAbortController(provided) {\n const abortController = provided || this.abortController || new AbortController();\n this.abortController = null;\n return abortController;\n }\n\n /**\n * Picks the best abort callback for a client request object.\n * @param {Object} req - The request object\n * @returns {Function|null}\n * @private\n */\n #_resolveAbortMethod(req) {\n if (!req) return null;\n if (typeof req.abort === 'function') return () => req.abort();\n const ExtAjax =\n typeof globalThis !== 'undefined' && globalThis.Ext && globalThis.Ext.Ajax ? globalThis.Ext.Ajax : null;\n if (req.xhr && ExtAjax && typeof ExtAjax.abort === 'function') {\n return () => ExtAjax.abort(req);\n }\n if (req.xhr && typeof req.xhr.abort === 'function') return () => req.xhr.abort();\n return null;\n }\n\n /**\n * Prepares request options by merging options and removing custom properties\n * @param {import('./index.d.ts').RequestOptions} options - Configuration options\n * @param {AbortSignal} signal - Abort signal to add to request options\n * @returns {Object} Prepared request options\n * @private\n */\n #_prepareRequestOptions(options, signal) {\n const requestOptions = {};\n const customOptions = ['abortController', 'cancelToken', 'requestKey', 'noCancel', 'includeQuery'];\n Object.keys(options).forEach((key) => {\n if (customOptions.includes(key)) return;\n requestOptions[key] = options[key];\n });\n requestOptions.signal = signal;\n return requestOptions;\n }\n\n /**\n * Deletes a request from the active requests map and rejects the wrapper promise\n * @param {string} requestId - The unique identifier of the request\n * @param {Function} rejectWrapper - The function to reject the wrapper promise\n * @param {*} error - The error to reject the wrapper promise with; the wrapper is not rejected if null/undefined\n * @private\n */\n #_deleteRequest(requestId, rejectWrapper, error) {\n this.activeRequests.delete(requestId);\n if (error !== null && error !== undefined) {\n rejectWrapper(error);\n }\n }\n\n /**\n * Completes a request by deleting it from the active requests map and resolving the wrapper promise\n * @param {string} requestId - The unique identifier of the request\n * @param {Function} resolveWrapper - The function to resolve the wrapper promise\n * @param {Promise} requestPromise - The request promise\n * @param {boolean} isCancelled - Whether the request was cancelled\n * @private\n */\n #_completeRequest(requestId, resolveWrapper, requestPromise, isCancelled) {\n this.activeRequests.delete(requestId);\n if (!isCancelled) {\n resolveWrapper(requestPromise);\n }\n }\n\n /**\n * Internal method that handles the core request logic.\n * @param {string} requestId - Unique identifier for the request\n * @param {Promise|import('./index.d.ts').RequestFunction|string} requestPromise - The request promise, function, or URL string\n * @param {import('./index.d.ts').BaseRequestOptions} options - Configuration options\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @private\n */\n #_request(requestId, requestPromise, options = {}) {\n const abortController = this.#_resolveAbortController(options.abortController);\n\n // Handle different types of requestPromise inputs\n // Priority: Function (Custom logic) > String (URL) > Promise (axios, fetch, etc.)\n if (typeof requestPromise === 'function') {\n // Function: custom logic for any library (axios, ajax, etc.)\n try {\n requestPromise = requestPromise({\n options: this.#_prepareRequestOptions(options, abortController.signal),\n });\n } catch (error) {\n return Promise.reject(error);\n }\n } else if (typeof requestPromise === 'string') {\n // String (URL): make fetch internally\n try {\n requestPromise = fetch(requestPromise, this.#_prepareRequestOptions(options, abortController.signal));\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n // Link the request object's abort method (Ext.Ajax, XHR, etc.) to the cancellation signal\n this.addAbortListener(this.#_resolveAbortMethod(requestPromise), abortController.signal);\n\n // Cancel previous request with the same identifier if it exists\n if (!options.noCancel) this.cancel(requestId);\n\n // Create a wrapper promise that will be resolved/rejected based on the request\n let resolveWrapper, rejectWrapper;\n const wrapperPromise = new Promise((resolve, reject) => {\n resolveWrapper = resolve;\n rejectWrapper = reject;\n });\n\n /**\n * @type {import('./index.d.ts').ActiveRequest}\n */\n const requestInfo = {\n promise: requestPromise,\n abortController: abortController,\n cancelToken: options.cancelToken || null,\n resolveWrapper: resolveWrapper,\n rejectWrapper: rejectWrapper,\n isCancelled: false,\n };\n\n this.activeRequests.set(requestId, requestInfo);\n\n // Handle request promise completion\n if (requestPromise && typeof requestPromise.then === 'function') {\n try {\n let req = requestPromise.then((result) => {\n if (this.activeRequests.get(requestId) !== requestInfo) return;\n this.#_completeRequest(requestId, resolveWrapper, result, requestInfo.isCancelled);\n });\n if (req.catch)\n req.catch((error) => {\n onError(this, error);\n });\n } catch (error) {\n onError(this, error);\n }\n function onError(scope, error) {\n // Check if this requestInfo is still the active one, or if it was cancelled\n if (scope.activeRequests.get(requestId) !== requestInfo) return;\n if (requestInfo.isCancelled) {\n // Already cancelled: let cancel() handle cleanup and reject the wrapper promise\n scope.cancel(requestId);\n return;\n }\n // Only delete if this is still the active request\n scope.#_deleteRequest(requestId, rejectWrapper, error);\n }\n } else {\n // Non-promise (Ext.Ajax request object, raw XHR, etc.). Keep tracked until the\n // underlying XHR finishes so a later duplicate can still cancel it.\n const xhr =\n requestPromise &&\n (requestPromise.xhr ||\n (typeof XMLHttpRequest !== 'undefined' && requestPromise instanceof XMLHttpRequest\n ? requestPromise\n : null));\n const finish = () => {\n if (this.activeRequests.get(requestId) !== requestInfo) return;\n this.#_completeRequest(requestId, resolveWrapper, requestPromise, requestInfo.isCancelled);\n };\n if (xhr && typeof xhr.addEventListener === 'function') {\n xhr.addEventListener('loadend', finish);\n } else {\n setTimeout(finish, 0);\n }\n }\n return wrapperPromise;\n }\n}\n\nexport default RequestManager;\n\nexport { RequestManager };\n"],"names":[],"mappings":"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"}
@@ -7,5 +7,5 @@
7
7
  * by accepting Promises as parameters. When a request is repeated with the same identifier,
8
8
  * the previous request is automatically cancelled and the new one is executed, giving priority to the most recent requests.
9
9
  */
10
- class e{constructor(e={}){this.activeRequests=new Map,this.options=e,this.abortController=null}getOptions(){return this.options}setOptions(e){this.options=e}getSignal(){return this.getAbortController().signal}getAbortController(){return this.abortController=new AbortController,this.abortController}isActive(e){return this.activeRequests.has(e)}getActiveCount(){return this.activeRequests.size}clear(){this.activeRequests.clear()}request(e,t,s={}){return this.#e(this.getRequestId(e,s),t,s)}fetch(e,t={}){return this.#e(this.getRequestId(e,t),e,t)}axios(e,t={},s=null){const r=s||axios,n=r.CancelToken.source(),o=this.getRequestId(e,t);return this.#e(o,r({url:e,cancelToken:n.token,...t}),{cancelToken:n,...t})}ajax(e,t,s={}){if("function"!=typeof e)throw new Error("ajaxFunction parameter must be a function");return this.#e(this.getRequestId(t,s),({options:s})=>e({url:t,...s}),s)}xhr(e,t={}){const s=this.getRequestId(e,t);return this.#e(s,({options:s})=>{const r=new XMLHttpRequest,n=(t.method||"GET").toUpperCase();return new Promise((o,i)=>{r.onload=function(){if(r.status>=200&&r.status<300){let e=r.response;if("json"===t.responseType||r.getResponseHeader("Content-Type")&&r.getResponseHeader("Content-Type").includes("application/json"))try{e=JSON.parse(r.responseText)}catch{e=r.responseText}o({data:e,status:r.status,statusText:r.statusText,headers:r.getAllResponseHeaders(),xhr:r})}else i({message:`Request failed with status ${r.status}`,status:r.status,statusText:r.statusText,xhr:r})},r.onerror=function(){i({message:"Network error",xhr:r})},r.ontimeout=function(){i({message:"Request timeout",xhr:r})},r.open(n,e,!0),t.responseType&&(r.responseType=t.responseType),void 0!==t.withCredentials&&(r.withCredentials=t.withCredentials),void 0!==t.timeout&&(r.timeout=t.timeout),t.headers&&Object.keys(t.headers).forEach(e=>{r.setRequestHeader(e,t.headers[e])}),s.signal&&s.signal.addEventListener("abort",()=>r.abort()),r.send(t.body||null)})},t)}getRequestId(e,t={}){let s=t.requestKey;const r="request_";if(t.noCancel)return`${r}${Date.now()}_${Math.random().toString(36).slice(2,11)}`;if("function"==typeof s)try{s=s()}catch{s=null}if(null!=s)return`${r}${String(s)}`;let n=e||"";return n.includes("://")&&(n=n.split("://")[1]),n.includes("#")&&(n=n.split("#")[0]),!t.includeQuery&&n.includes("?")&&(n=n.split("?")[0]),`${r}${n}`}cancel(e){const t=this.activeRequests.get(e);if(!t)return!1;if(t.isCancelled=!0,t.abortController&&!t.abortController.signal.aborted)try{t.abortController.abort("Request was cancelled")}catch(e){}if(t.cancelToken)try{"function"==typeof t.cancelToken?t.cancelToken():t.cancelToken.cancel&&t.cancelToken.cancel()}catch(e){}return this.#t(e,t.rejectWrapper,this.getOptions().verbose?new Error(`Request ${e} was cancelled`):null),!0}addAbortListener(e,t){e&&t&&t.addEventListener("abort",()=>{if("function"==typeof e)try{e()}catch(e){}})}cancelAll(){const e=Array.from(this.activeRequests.keys());let t=0;return e.forEach(e=>{this.cancel(e)&&t++}),t}#s(e){const t=e||this.abortController||new AbortController;return this.abortController=null,t}#r(e){if(!e)return null;if("function"==typeof e.abort)return()=>e.abort();const t="undefined"!=typeof globalThis&&globalThis.Ext&&globalThis.Ext.Ajax?globalThis.Ext.Ajax:null;return e.xhr&&t&&"function"==typeof t.abort?()=>t.abort(e):e.xhr&&"function"==typeof e.xhr.abort?()=>e.xhr.abort():null}#n(e,t){const s={},r=["abortController","cancelToken","requestKey","noCancel","includeQuery"];return Object.keys(e).forEach(t=>{r.includes(t)||(s[t]=e[t])}),s.signal=t,s}#t(e,t,s){this.activeRequests.delete(e),null!=s&&t(s)}#o(e,t,s,r){this.activeRequests.delete(e),r||t(s)}#e(e,t,s={}){const r=this.#s(s.abortController);if("function"==typeof t)try{t=t({options:this.#n(s,r.signal)})}catch(a){return Promise.reject(a)}else if("string"==typeof t)try{t=fetch(t,this.#n(s,r.signal))}catch(c){return Promise.reject(c)}let n,o;this.addAbortListener(this.#r(t),r.signal),s.noCancel||this.cancel(e);const i=new Promise((e,t)=>{n=e,o=t}),l={promise:t,abortController:r,cancelToken:s.cancelToken||null,resolveWrapper:n,rejectWrapper:o,isCancelled:!1};if(this.activeRequests.set(e,l),t&&"function"==typeof t.then){try{let h=t.then(t=>{this.activeRequests.get(e)===l&&this.#o(e,n,t,l.isCancelled)});h.catch&&h.catch(e=>{u(this,e)})}catch(p){u(this,p)}function u(t,s){t.activeRequests.get(e)===l&&(l.isCancelled?t.cancel(e):t.#t(e,o,s))}}else{const d=t&&(t.xhr||("undefined"!=typeof XMLHttpRequest&&t instanceof XMLHttpRequest?t:null)),f=()=>{this.activeRequests.get(e)===l&&this.#o(e,n,t,l.isCancelled)};d&&"function"==typeof d.addEventListener?d.addEventListener("loadend",f):setTimeout(f,0)}return i}}exports.RequestManager=e,exports.default=e;
10
+ class e{constructor(e={}){this.activeRequests=new Map,this.options=e,this.abortController=null}getOptions(){return this.options}setOptions(e){this.options=e}getSignal(){return this.getAbortController().signal}getAbortController(){return this.abortController=new AbortController,this.abortController}isActive(e){return this.activeRequests.has(e)}getActiveCount(){return this.activeRequests.size}clear(){this.activeRequests.clear()}request(e,t,s={}){return this.#e(this.getRequestId(e,s),t,s)}fetch(e,t={}){return this.#e(this.getRequestId(e,t),e,t)}axios(e,t={},s=null){const r=s||axios;return this.#e(this.getRequestId(e,t),({options:t})=>r({url:e,...t}),t)}ajax(e,t,s={}){if("function"!=typeof e)throw new Error("ajaxFunction parameter must be a function");return this.#e(this.getRequestId(t,s),({options:s})=>e({url:t,...s}),s)}xhr(e,t={}){const s=this.getRequestId(e,t);return this.#e(s,({options:s})=>{const r=new XMLHttpRequest,n=(t.method||"GET").toUpperCase();return new Promise((o,i)=>{r.onload=function(){if(r.status>=200&&r.status<300){let e=r.response;if("json"===t.responseType||(!t.responseType||"text"===t.responseType)&&r.getResponseHeader("Content-Type")?.includes("application/json")&&"string"==typeof e)try{e=JSON.parse(e)}catch{}o({data:e,status:r.status,statusText:r.statusText,headers:r.getAllResponseHeaders(),xhr:r})}else i({message:`Request failed with status ${r.status}`,status:r.status,statusText:r.statusText,xhr:r})},r.onerror=function(){i({message:"Network error",xhr:r})},r.ontimeout=function(){i({message:"Request timeout",xhr:r})},r.open(n,e,!0),t.responseType&&(r.responseType=t.responseType),void 0!==t.withCredentials&&(r.withCredentials=t.withCredentials),void 0!==t.timeout&&(r.timeout=t.timeout),t.headers&&Object.keys(t.headers).forEach(e=>{r.setRequestHeader(e,t.headers[e])}),s.signal&&s.signal.addEventListener("abort",()=>r.abort()),r.send(t.body||null)})},t)}getRequestId(e,t={}){let s=t.requestKey;const r="request_";if(t.noCancel)return`${r}${Date.now()}_${Math.random().toString(36).slice(2,11)}`;if("function"==typeof s)try{s=s()}catch{s=null}if(null!=s)return`${r}${String(s)}`;let n=e||"";return n.includes("://")&&(n=n.split("://")[1]),n.includes("#")&&(n=n.split("#")[0]),!t.includeQuery&&n.includes("?")&&(n=n.split("?")[0]),`${r}${n}`}cancel(e){const t=this.activeRequests.get(e);if(!t)return!1;if(t.isCancelled=!0,t.abortController&&!t.abortController.signal.aborted)try{t.abortController.abort("Request was cancelled")}catch(e){}if(t.cancelToken)try{"function"==typeof t.cancelToken?t.cancelToken():t.cancelToken.cancel&&t.cancelToken.cancel()}catch(e){}return this.#t(e,t.rejectWrapper,this.getOptions().verbose?new Error(`Request ${e} was cancelled`):null),!0}addAbortListener(e,t){e&&t&&t.addEventListener("abort",()=>{if("function"==typeof e)try{e()}catch(e){}})}cancelAll(){const e=Array.from(this.activeRequests.keys());let t=0;return e.forEach(e=>{this.cancel(e)&&t++}),t}#s(e){const t=e||this.abortController||new AbortController;return this.abortController=null,t}#r(e){if(!e)return null;if("function"==typeof e.abort)return()=>e.abort();const t="undefined"!=typeof globalThis&&globalThis.Ext&&globalThis.Ext.Ajax?globalThis.Ext.Ajax:null;return e.xhr&&t&&"function"==typeof t.abort?()=>t.abort(e):e.xhr&&"function"==typeof e.xhr.abort?()=>e.xhr.abort():null}#n(e,t){const s={},r=["abortController","cancelToken","requestKey","noCancel","includeQuery"];return Object.keys(e).forEach(t=>{r.includes(t)||(s[t]=e[t])}),s.signal=t,s}#t(e,t,s){this.activeRequests.delete(e),null!=s&&t(s)}#o(e,t,s,r){this.activeRequests.delete(e),r||t(s)}#e(e,t,s={}){const r=this.#s(s.abortController);if("function"==typeof t)try{t=t({options:this.#n(s,r.signal)})}catch(a){return Promise.reject(a)}else if("string"==typeof t)try{t=fetch(t,this.#n(s,r.signal))}catch(u){return Promise.reject(u)}let n,o;this.addAbortListener(this.#r(t),r.signal),s.noCancel||this.cancel(e);const i=new Promise((e,t)=>{n=e,o=t}),l={promise:t,abortController:r,cancelToken:s.cancelToken||null,resolveWrapper:n,rejectWrapper:o,isCancelled:!1};if(this.activeRequests.set(e,l),t&&"function"==typeof t.then){try{let h=t.then(t=>{this.activeRequests.get(e)===l&&this.#o(e,n,t,l.isCancelled)});h.catch&&h.catch(e=>{c(this,e)})}catch(p){c(this,p)}function c(t,s){t.activeRequests.get(e)===l&&(l.isCancelled?t.cancel(e):t.#t(e,o,s))}}else{const d=t&&(t.xhr||("undefined"!=typeof XMLHttpRequest&&t instanceof XMLHttpRequest?t:null)),f=()=>{this.activeRequests.get(e)===l&&this.#o(e,n,t,l.isCancelled)};d&&"function"==typeof d.addEventListener?d.addEventListener("loadend",f):setTimeout(f,0)}return i}}exports.RequestManager=e,exports.default=e;
11
11
  //# sourceMappingURL=request-manager.cjs.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-manager.cjs.min.js","sources":["../main.js"],"sourcesContent":["/**\n * RequestManager - A library for managing and regulating HTTP requests efficiently.\n * @license MIT\n * @author Eneko Galan <enekogalanelorza@gmail.com>\n * This library allows you to manage HTTP requests from any library (ajax, Ext.Ajax, axios, fetch, etc.)\n * by accepting Promises as parameters. When a request is repeated with the same identifier,\n * the previous request is automatically cancelled and the new one is executed, giving priority to the most recent requests.\n */\nclass RequestManager {\n constructor(options = {}) {\n /**\n * Map to store active requests by their unique identifier.\n * @type {Map<string, import('./index.d.ts').ActiveRequest>}\n */\n this.activeRequests = new Map();\n /**\n * @type {import('./index.d.ts').Options}\n */\n this.options = options;\n /**\n * One-shot AbortController for getSignal()/getAbortController() handoff.\n * Consumed by the next request that does not pass options.abortController.\n * @type {AbortController|null}\n */\n this.abortController = null;\n }\n\n /**\n * Gets the manager options\n * @returns {import('./index.d.ts').Options} Manager options\n */\n getOptions() {\n return this.options;\n }\n\n /**\n * Sets the manager options\n * @param {import('./index.d.ts').Options} options - The options to set\n */\n setOptions(options) {\n this.options = options;\n }\n\n /**\n * Creates a new AbortController and returns its signal for the next request()\n * (one getSignal → one request). Do not use for parallel requests; use fetch(),\n * axios(), or request(url, ({ options }) => ...) instead — they create their own signal.\n * @returns {AbortSignal} The signal from a new AbortController\n * @example\n * const signal = requestManager.getSignal();\n * requestManager.request('/api/users', fetch('/api/users', { signal }));\n */\n getSignal() {\n return this.getAbortController().signal;\n }\n\n /**\n * Creates a new AbortController for the next request handoff.\n * Always returns a fresh controller (never reuses one from another in-flight request).\n * @returns {AbortController} A new AbortController instance\n */\n getAbortController() {\n this.abortController = new AbortController();\n return this.abortController;\n }\n\n /**\n * Checks if a request with the given identifier is currently active.\n * @param {string} requestId - The unique identifier to check\n * @returns {boolean} True if the request is active, false otherwise\n */\n isActive(requestId) {\n return this.activeRequests.has(requestId);\n }\n\n /**\n * Gets the number of active requests.\n * @returns {number} The number of currently active requests\n */\n getActiveCount() {\n return this.activeRequests.size;\n }\n\n /**\n * Clears all active requests without cancelling them.\n * Use with caution - this will not cancel the underlying HTTP requests.\n */\n clear() {\n this.activeRequests.clear();\n }\n\n /**\n * Executes an HTTP request, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {Promise|import('./index.d.ts').RequestFunction|string} requestPromise - The request promise or function that returns a promise\n * @param {import('./index.d.ts').RequestOptions} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Request with Promise\n * requestManager.request('/api/users', axios.get('/api/users', { cancelToken: axios.CancelToken.source().token }));\n * @example\n * // Request with Function\n * requestManager.request('/api/users', ({ options }) => fetch('/api/users', { signal: options.signal, ...options }));\n * @example\n * // Request with Promise and custom cancellation grouping with requestKey\n * const options = {\n * requestKey: 'get-users',\n * cancelToken: axios.CancelToken.source().cancel\n * }\n * requestManager.request('/api/users', axios.get('/api/users', options), options);\n */\n request(url, requestPromise, options = {}) {\n return this.#_request(this.getRequestId(url, options), requestPromise, options);\n }\n\n /**\n * Executes an HTTP request using fetch, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to fetch\n * @param {import('./index.d.ts').FetchOptions} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.fetch('/api/users');\n * @example\n * // POST request with options\n * requestManager.fetch('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.fetch('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n fetch(url, options = {}) {\n return this.#_request(this.getRequestId(url, options), url, options);\n }\n\n /**\n * Executes an HTTP request using axios, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').AxiosRequestOptions} options - Optional configuration\n * @param {import('./index.d.ts').AxiosInstance|import('./index.d.ts').AxiosStatic|null} axiosInstance - Optional axios instance to use. If not provided, uses global axios.\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request (uses global axios)\n * requestManager.axios('/api/users');\n * @example\n * // With custom axios instance\n * const myAxios = axios.create({ baseURL: 'https://api.example.com' });\n * requestManager.axios('/users', {}, myAxios);\n * @example\n * // POST request with options\n * requestManager.axios('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.axios('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n axios(url, options = {}, axiosInstance = null) {\n const axiosLib = axiosInstance || axios;\n const cancelToken = axiosLib.CancelToken.source();\n const requestId = this.getRequestId(url, options);\n return this.#_request(requestId, axiosLib({ url, cancelToken: cancelToken.token, ...options }), {\n cancelToken: cancelToken,\n ...options,\n });\n }\n\n /**\n * Executes an HTTP request using jQuery.ajax, cancelling any previous request with the same identifier.\n * @param {import('./index.d.ts').AjaxFunction} ajaxFunction - A function that receives { url, ...options } and returns a Promise\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').BaseRequestOptions & Record<string, any>} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.ajax(ajaxFunction, '/api/users');\n * @example\n * // POST request with options\n * requestManager.ajax(ajaxFunction, '/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.ajax(ajaxFunction, '/api/users', {\n * requestKey: 'get-users'\n * });\n */\n ajax(ajaxFunction, url, options = {}) {\n if (typeof ajaxFunction !== 'function') throw new Error('ajaxFunction parameter must be a function');\n return this.#_request(\n this.getRequestId(url, options),\n ({ options: requestOptions }) => ajaxFunction({ url, ...requestOptions }),\n options\n );\n }\n\n /**\n * Executes an HTTP request using XMLHttpRequest, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').XhrOptions} options - Optional configuration\n * @returns {Promise<import('./index.d.ts').XhrResponse>} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.xhr('/api/users');\n * @example\n * // POST request with options\n * requestManager.xhr('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping\n * requestManager.xhr('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n xhr(url, options = {}) {\n const requestId = this.getRequestId(url, options);\n /** @type {import('./index.d.ts').RequestFunction<import('./index.d.ts').XhrResponse>} */\n const xhrFunction = ({ options: fetchOptions }) => {\n // Create XMLHttpRequest\n const xhr = new XMLHttpRequest();\n const method = (options.method || 'GET').toUpperCase();\n // Create a promise that wraps the XHR request\n const xhrPromise = new Promise((resolve, reject) => {\n xhr.onload = function () {\n if (xhr.status >= 200 && xhr.status < 300) {\n let response = xhr.response;\n if (\n options.responseType === 'json' ||\n (xhr.getResponseHeader('Content-Type') &&\n xhr.getResponseHeader('Content-Type').includes('application/json'))\n ) {\n try {\n response = JSON.parse(xhr.responseText);\n } catch {\n response = xhr.responseText;\n }\n }\n resolve({\n data: response,\n status: xhr.status,\n statusText: xhr.statusText,\n headers: xhr.getAllResponseHeaders(),\n xhr: xhr,\n });\n } else {\n reject({\n message: `Request failed with status ${xhr.status}`,\n status: xhr.status,\n statusText: xhr.statusText,\n xhr: xhr,\n });\n }\n };\n xhr.onerror = function () {\n reject({\n message: 'Network error',\n xhr: xhr,\n });\n };\n xhr.ontimeout = function () {\n reject({\n message: 'Request timeout',\n xhr: xhr,\n });\n };\n\n // Open the request\n xhr.open(method, url, true);\n\n // Set response type\n if (options.responseType) xhr.responseType = options.responseType;\n // Set withCredentials\n if (options.withCredentials !== undefined) xhr.withCredentials = options.withCredentials;\n // Set timeout\n if (options.timeout !== undefined) xhr.timeout = options.timeout;\n // Set headers\n if (options.headers)\n Object.keys(options.headers).forEach((key) => {\n xhr.setRequestHeader(key, options.headers[key]);\n });\n\n // Connect abort signal to xhr.abort()\n if (fetchOptions.signal) fetchOptions.signal.addEventListener('abort', () => xhr.abort());\n\n // Send the request\n xhr.send(options.body || null);\n });\n return xhrPromise;\n };\n return this.#_request(requestId, xhrFunction, options);\n }\n\n /**\n * Returns the request identifier for a URL and options.\n * @param {string} url - The URL used when starting the request\n * @param {import('./index.d.ts').BaseRequestOptions} options - Same options used for the request\n * @returns {string} The request identifier\n * @example\n * requestManager.fetch('/api/users');\n * const id = requestManager.getRequestId('/api/users');\n * requestManager.cancel(id);\n */\n getRequestId(url, options = {}) {\n let requestKey = options.requestKey;\n\n const prefix = 'request_';\n\n // Generate a unique identifier to prevent cancellation for non cancelable requests\n if (options.noCancel) {\n return `${prefix}${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n }\n\n // Handle function requestKey\n if (typeof requestKey === 'function') {\n try {\n requestKey = requestKey();\n } catch {\n requestKey = null;\n }\n }\n if (requestKey !== null && requestKey !== undefined) return `${prefix}${String(requestKey)}`;\n\n // Use cleaned URL as key as fallback\n let cleanedUrl = url || '';\n if (cleanedUrl.includes('://')) cleanedUrl = cleanedUrl.split('://')[1];\n if (cleanedUrl.includes('#')) cleanedUrl = cleanedUrl.split('#')[0];\n if (!options.includeQuery && cleanedUrl.includes('?')) cleanedUrl = cleanedUrl.split('?')[0];\n return `${prefix}${cleanedUrl}`;\n }\n\n /**\n * Cancels a specific request by its identifier.\n * @param {string} requestId - The unique identifier of the request to cancel\n * @returns {boolean} True if the request was found and cancelled, false otherwise\n */\n cancel(requestId) {\n /** @type {import('./index.d.ts').ActiveRequest|undefined} */\n const requestInfo = this.activeRequests.get(requestId);\n if (!requestInfo) return false;\n\n requestInfo.isCancelled = true; // Mark as cancelled\n\n // Try to abort using AbortController (for fetch)\n if (requestInfo.abortController && !requestInfo.abortController.signal.aborted) {\n try {\n requestInfo.abortController.abort('Request was cancelled');\n } catch (error) {}\n }\n\n // Try to cancel using cancel token/function (for axios and others)\n if (requestInfo.cancelToken) {\n try {\n if (typeof requestInfo.cancelToken === 'function') requestInfo.cancelToken();\n else if (requestInfo.cancelToken.cancel) requestInfo.cancelToken.cancel();\n } catch (error) {}\n }\n\n // Reject the wrapper promise\n this.#_deleteRequest(\n requestId,\n requestInfo.rejectWrapper,\n this.getOptions().verbose ? new Error(`Request ${requestId} was cancelled`) : null\n );\n return true;\n }\n\n /**\n * Link abort signal with HTTP client abort method.\n * Useful for custom HTTP clients that only support the abort method to cancel requests.\n * @param {Function} abortMethod - The abort method to call when the signal is aborted\n * @param {AbortSignal} signal - The signal to listen to\n */\n addAbortListener(abortMethod, signal) {\n if (!abortMethod || !signal) return;\n signal.addEventListener('abort', () => {\n if (typeof abortMethod === 'function') {\n try {\n abortMethod();\n } catch (error) {}\n }\n });\n }\n\n /**\n * Cancels all active requests.\n * @returns {number} The number of requests that were cancelled\n */\n cancelAll() {\n const requestIds = Array.from(this.activeRequests.keys());\n let cancelledCount = 0;\n requestIds.forEach((requestId) => {\n if (this.cancel(requestId)) cancelledCount++;\n });\n return cancelledCount;\n }\n\n /**\n * Resolves the AbortController for a request: explicit option, pending handoff, or new.\n * Clears the pending handoff so concurrent requests do not share it.\n * @param {AbortController|undefined} provided - Optional AbortController from options\n * @returns {AbortController}\n * @private\n */\n #_resolveAbortController(provided) {\n const abortController = provided || this.abortController || new AbortController();\n this.abortController = null;\n return abortController;\n }\n\n /**\n * Picks the best abort callback for a client request object.\n * @param {Object} req - The request object\n * @returns {Function|null}\n * @private\n */\n #_resolveAbortMethod(req) {\n if (!req) return null;\n if (typeof req.abort === 'function') return () => req.abort();\n const ExtAjax =\n typeof globalThis !== 'undefined' && globalThis.Ext && globalThis.Ext.Ajax ? globalThis.Ext.Ajax : null;\n if (req.xhr && ExtAjax && typeof ExtAjax.abort === 'function') {\n return () => ExtAjax.abort(req);\n }\n if (req.xhr && typeof req.xhr.abort === 'function') return () => req.xhr.abort();\n return null;\n }\n\n /**\n * Prepares request options by merging options and removing custom properties\n * @param {import('./index.d.ts').RequestOptions} options - Configuration options\n * @param {AbortSignal} signal - Abort signal to add to request options\n * @returns {Object} Prepared request options\n * @private\n */\n #_prepareRequestOptions(options, signal) {\n const requestOptions = {};\n const customOptions = ['abortController', 'cancelToken', 'requestKey', 'noCancel', 'includeQuery'];\n Object.keys(options).forEach((key) => {\n if (customOptions.includes(key)) return;\n requestOptions[key] = options[key];\n });\n requestOptions.signal = signal;\n return requestOptions;\n }\n\n /**\n * Deletes a request from the active requests map and rejects the wrapper promise\n * @param {string} requestId - The unique identifier of the request\n * @param {Function} rejectWrapper - The function to reject the wrapper promise\n * @param {*} error - The error to reject the wrapper promise with; the wrapper is not rejected if null/undefined\n * @private\n */\n #_deleteRequest(requestId, rejectWrapper, error) {\n this.activeRequests.delete(requestId);\n if (error !== null && error !== undefined) {\n rejectWrapper(error);\n }\n }\n\n /**\n * Completes a request by deleting it from the active requests map and resolving the wrapper promise\n * @param {string} requestId - The unique identifier of the request\n * @param {Function} resolveWrapper - The function to resolve the wrapper promise\n * @param {Promise} requestPromise - The request promise\n * @param {boolean} isCancelled - Whether the request was cancelled\n * @private\n */\n #_completeRequest(requestId, resolveWrapper, requestPromise, isCancelled) {\n this.activeRequests.delete(requestId);\n if (!isCancelled) {\n resolveWrapper(requestPromise);\n }\n }\n\n /**\n * Internal method that handles the core request logic.\n * @param {string} requestId - Unique identifier for the request\n * @param {Promise|import('./index.d.ts').RequestFunction|string} requestPromise - The request promise, function, or URL string\n * @param {import('./index.d.ts').BaseRequestOptions} options - Configuration options\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @private\n */\n #_request(requestId, requestPromise, options = {}) {\n const abortController = this.#_resolveAbortController(options.abortController);\n\n // Handle different types of requestPromise inputs\n // Priority: Function (Custom logic) > String (URL) > Promise (axios, fetch, etc.)\n if (typeof requestPromise === 'function') {\n // Function: custom logic for any library (axios, ajax, etc.)\n try {\n requestPromise = requestPromise({\n options: this.#_prepareRequestOptions(options, abortController.signal),\n });\n } catch (error) {\n return Promise.reject(error);\n }\n } else if (typeof requestPromise === 'string') {\n // String (URL): make fetch internally\n try {\n requestPromise = fetch(requestPromise, this.#_prepareRequestOptions(options, abortController.signal));\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n // Link the request object's abort method (Ext.Ajax, XHR, etc.) to the cancellation signal\n this.addAbortListener(this.#_resolveAbortMethod(requestPromise), abortController.signal);\n\n // Cancel previous request with the same identifier if it exists\n if (!options.noCancel) this.cancel(requestId);\n\n // Create a wrapper promise that will be resolved/rejected based on the request\n let resolveWrapper, rejectWrapper;\n const wrapperPromise = new Promise((resolve, reject) => {\n resolveWrapper = resolve;\n rejectWrapper = reject;\n });\n\n /**\n * @type {import('./index.d.ts').ActiveRequest}\n */\n const requestInfo = {\n promise: requestPromise,\n abortController: abortController,\n cancelToken: options.cancelToken || null,\n resolveWrapper: resolveWrapper,\n rejectWrapper: rejectWrapper,\n isCancelled: false,\n };\n\n this.activeRequests.set(requestId, requestInfo);\n\n // Handle request promise completion\n if (requestPromise && typeof requestPromise.then === 'function') {\n try {\n let req = requestPromise.then((result) => {\n if (this.activeRequests.get(requestId) !== requestInfo) return;\n this.#_completeRequest(requestId, resolveWrapper, result, requestInfo.isCancelled);\n });\n if (req.catch)\n req.catch((error) => {\n onError(this, error);\n });\n } catch (error) {\n onError(this, error);\n }\n function onError(scope, error) {\n // Check if this requestInfo is still the active one, or if it was cancelled\n if (scope.activeRequests.get(requestId) !== requestInfo) return;\n if (requestInfo.isCancelled) {\n // Already cancelled: let cancel() handle cleanup and reject the wrapper promise\n scope.cancel(requestId);\n return;\n }\n // Only delete if this is still the active request\n scope.#_deleteRequest(requestId, rejectWrapper, error);\n }\n } else {\n // Non-promise (Ext.Ajax request object, raw XHR, etc.). Keep tracked until the\n // underlying XHR finishes so a later duplicate can still cancel it.\n const xhr =\n requestPromise &&\n (requestPromise.xhr ||\n (typeof XMLHttpRequest !== 'undefined' && requestPromise instanceof XMLHttpRequest\n ? requestPromise\n : null));\n const finish = () => {\n if (this.activeRequests.get(requestId) !== requestInfo) return;\n this.#_completeRequest(requestId, resolveWrapper, requestPromise, requestInfo.isCancelled);\n };\n if (xhr && typeof xhr.addEventListener === 'function') {\n xhr.addEventListener('loadend', finish);\n } else {\n setTimeout(finish, 0);\n }\n }\n return wrapperPromise;\n }\n}\n\nexport default RequestManager;\n\nexport { RequestManager };\n"],"names":["RequestManager","constructor","options","this","activeRequests","Map","abortController","getOptions","setOptions","getSignal","getAbortController","signal","AbortController","isActive","requestId","has","getActiveCount","size","clear","request","url","requestPromise","_request","getRequestId","fetch","axios","axiosInstance","axiosLib","cancelToken","CancelToken","source","token","ajax","ajaxFunction","Error","requestOptions","xhr","fetchOptions","XMLHttpRequest","method","toUpperCase","Promise","resolve","reject","onload","status","response","responseType","getResponseHeader","includes","JSON","parse","responseText","data","statusText","headers","getAllResponseHeaders","message","onerror","ontimeout","open","undefined","withCredentials","timeout","Object","keys","forEach","key","setRequestHeader","addEventListener","abort","send","body","requestKey","prefix","noCancel","Date","now","Math","random","toString","slice","String","cleanedUrl","split","includeQuery","cancel","requestInfo","get","isCancelled","aborted","error","_deleteRequest","rejectWrapper","verbose","addAbortListener","abortMethod","cancelAll","requestIds","Array","from","cancelledCount","_resolveAbortController","provided","_resolveAbortMethod","req","ExtAjax","globalThis","Ext","Ajax","_prepareRequestOptions","customOptions","delete","_completeRequest","resolveWrapper","wrapperPromise","promise","set","then","result","catch","onError","scope","finish","setTimeout"],"mappings":"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"}
1
+ {"version":3,"file":"request-manager.cjs.min.js","sources":["../main.js"],"sourcesContent":["/**\n * RequestManager - A library for managing and regulating HTTP requests efficiently.\n * @license MIT\n * @author Eneko Galan <enekogalanelorza@gmail.com>\n * This library allows you to manage HTTP requests from any library (ajax, Ext.Ajax, axios, fetch, etc.)\n * by accepting Promises as parameters. When a request is repeated with the same identifier,\n * the previous request is automatically cancelled and the new one is executed, giving priority to the most recent requests.\n */\nclass RequestManager {\n constructor(options = {}) {\n /**\n * @type {Map<string, import('./index.d.ts').ActiveRequest>}\n */\n this.activeRequests = new Map();\n /**\n * @type {import('./index.d.ts').Options}\n */\n this.options = options;\n /**\n * One-shot AbortController for getSignal()/getAbortController() handoff.\n * Consumed by the next request that does not pass options.abortController.\n * @type {AbortController|null}\n */\n this.abortController = null;\n }\n\n /**\n * Gets the manager options\n * @returns {import('./index.d.ts').Options} Manager options\n */\n getOptions() {\n return this.options;\n }\n\n /**\n * Sets the manager options\n * @param {import('./index.d.ts').Options} options - The options to set\n */\n setOptions(options) {\n this.options = options;\n }\n\n /**\n * Creates a new AbortController and returns its signal for the next request()\n * (one getSignal → one request). Do not use for parallel requests; use fetch(),\n * axios(), or request(url, ({ options }) => ...) instead — they create their own signal.\n * @returns {AbortSignal} The signal from a new AbortController\n * @example\n * const signal = requestManager.getSignal();\n * requestManager.request('/api/users', fetch('/api/users', { signal }));\n */\n getSignal() {\n return this.getAbortController().signal;\n }\n\n /**\n * Creates a new AbortController for the next request handoff.\n * Always returns a fresh controller (never reuses one from another in-flight request).\n * @returns {AbortController} A new AbortController instance\n */\n getAbortController() {\n this.abortController = new AbortController();\n return this.abortController;\n }\n\n /**\n * Checks if a request with the given identifier is currently active.\n * @param {string} requestId - The unique identifier to check\n * @returns {boolean} True if the request is active, false otherwise\n */\n isActive(requestId) {\n return this.activeRequests.has(requestId);\n }\n\n /**\n * Gets the number of active requests.\n * @returns {number} The number of currently active requests\n */\n getActiveCount() {\n return this.activeRequests.size;\n }\n\n /**\n * Clears all active requests without cancelling them.\n * Use with caution - this will not cancel the underlying HTTP requests.\n */\n clear() {\n this.activeRequests.clear();\n }\n\n /**\n * Executes an HTTP request, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {Promise|import('./index.d.ts').RequestFunction|string} requestPromise - The request promise or function that returns a promise\n * @param {import('./index.d.ts').RequestOptions} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Request with Promise\n * requestManager.request('/api/users', axios.get('/api/users'));\n * @example\n * // Request with Function\n * requestManager.request('/api/users', ({ options }) => fetch('/api/users', { signal: options.signal, ...options }));\n * @example\n * // Request with Promise and custom cancellation grouping with requestKey\n * const options = {\n * requestKey: 'get-users'\n * }\n * requestManager.request('/api/users', axios.get('/api/users', options), options);\n */\n request(url, requestPromise, options = {}) {\n return this.#_request(this.getRequestId(url, options), requestPromise, options);\n }\n\n /**\n * Executes an HTTP request using fetch, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to fetch\n * @param {import('./index.d.ts').FetchOptions} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.fetch('/api/users');\n * @example\n * // POST request with options\n * requestManager.fetch('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.fetch('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n fetch(url, options = {}) {\n return this.#_request(this.getRequestId(url, options), url, options);\n }\n\n /**\n * Executes an HTTP request using axios, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').AxiosRequestOptions} options - Optional configuration\n * @param {import('./index.d.ts').AxiosInstance|import('./index.d.ts').AxiosStatic|null} axiosInstance - Optional axios instance to use. If not provided, uses global axios.\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request (uses global axios)\n * requestManager.axios('/api/users');\n * @example\n * // With custom axios instance\n * const myAxios = axios.create({ baseURL: 'https://api.example.com' });\n * requestManager.axios('/users', {}, myAxios);\n * @example\n * // POST request with options\n * requestManager.axios('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.axios('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n axios(url, options = {}, axiosInstance = null) {\n const axiosLib = axiosInstance || axios;\n return this.#_request(\n this.getRequestId(url, options),\n ({ options: requestOptions }) => axiosLib({ url, ...requestOptions }),\n options\n );\n }\n\n /**\n * Executes an HTTP request using jQuery.ajax, cancelling any previous request with the same identifier.\n * @param {import('./index.d.ts').AjaxFunction} ajaxFunction - A function that receives { url, ...options } and returns a Promise\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').BaseRequestOptions & Record<string, any>} options - Optional configuration\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.ajax(ajaxFunction, '/api/users');\n * @example\n * // POST request with options\n * requestManager.ajax(ajaxFunction, '/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping with requestKey\n * requestManager.ajax(ajaxFunction, '/api/users', {\n * requestKey: 'get-users'\n * });\n */\n ajax(ajaxFunction, url, options = {}) {\n if (typeof ajaxFunction !== 'function') throw new Error('ajaxFunction parameter must be a function');\n return this.#_request(\n this.getRequestId(url, options),\n ({ options: requestOptions }) => ajaxFunction({ url, ...requestOptions }),\n options\n );\n }\n\n /**\n * Executes an HTTP request using XMLHttpRequest, cancelling any previous request with the same identifier.\n * @param {string} url - The URL to request\n * @param {import('./index.d.ts').XhrOptions} options - Optional configuration\n * @returns {Promise<import('./index.d.ts').XhrResponse>} A Promise that resolves/rejects based on the most recent request\n * @example\n * // Simple GET request\n * requestManager.xhr('/api/users');\n * @example\n * // POST request with options\n * requestManager.xhr('/api/users', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify({ name: 'John' })\n * });\n * @example\n * // Request with requestKey for custom cancellation grouping\n * requestManager.xhr('/api/users', {\n * requestKey: 'get-users'\n * });\n */\n xhr(url, options = {}) {\n const requestId = this.getRequestId(url, options);\n /** @type {import('./index.d.ts').RequestFunction<import('./index.d.ts').XhrResponse>} */\n const xhrFunction = ({ options: fetchOptions }) => {\n // Create XMLHttpRequest\n const xhr = new XMLHttpRequest();\n const method = (options.method || 'GET').toUpperCase();\n // Create a promise that wraps the XHR request\n const xhrPromise = new Promise((resolve, reject) => {\n xhr.onload = function () {\n if (xhr.status >= 200 && xhr.status < 300) {\n let response = xhr.response;\n if (\n options.responseType === 'json' ||\n ((!options.responseType || options.responseType === 'text') &&\n xhr.getResponseHeader('Content-Type')?.includes('application/json') &&\n typeof response === 'string')\n ) {\n try {\n response = JSON.parse(response);\n } catch {}\n }\n resolve({\n data: response,\n status: xhr.status,\n statusText: xhr.statusText,\n headers: xhr.getAllResponseHeaders(),\n xhr: xhr,\n });\n } else {\n reject({\n message: `Request failed with status ${xhr.status}`,\n status: xhr.status,\n statusText: xhr.statusText,\n xhr: xhr,\n });\n }\n };\n xhr.onerror = function () {\n reject({\n message: 'Network error',\n xhr: xhr,\n });\n };\n xhr.ontimeout = function () {\n reject({\n message: 'Request timeout',\n xhr: xhr,\n });\n };\n\n // Open the request\n xhr.open(method, url, true);\n\n // Set response type\n if (options.responseType) xhr.responseType = options.responseType;\n // Set withCredentials\n if (options.withCredentials !== undefined) xhr.withCredentials = options.withCredentials;\n // Set timeout\n if (options.timeout !== undefined) xhr.timeout = options.timeout;\n // Set headers\n if (options.headers)\n Object.keys(options.headers).forEach((key) => {\n xhr.setRequestHeader(key, options.headers[key]);\n });\n\n // Connect abort signal to xhr.abort()\n if (fetchOptions.signal) fetchOptions.signal.addEventListener('abort', () => xhr.abort());\n\n // Send the request\n xhr.send(options.body || null);\n });\n return xhrPromise;\n };\n return this.#_request(requestId, xhrFunction, options);\n }\n\n /**\n * Returns the request identifier for a URL and options.\n * @param {string} url - The URL used when starting the request\n * @param {import('./index.d.ts').BaseRequestOptions} options - Same options used for the request\n * @returns {string} The request identifier\n * @example\n * requestManager.fetch('/api/users');\n * const id = requestManager.getRequestId('/api/users');\n * requestManager.cancel(id);\n */\n getRequestId(url, options = {}) {\n let requestKey = options.requestKey;\n\n const prefix = 'request_';\n\n // Generate a unique identifier to prevent cancellation for non cancelable requests\n if (options.noCancel) {\n return `${prefix}${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n }\n\n // Handle function requestKey\n if (typeof requestKey === 'function') {\n try {\n requestKey = requestKey();\n } catch {\n requestKey = null;\n }\n }\n if (requestKey !== null && requestKey !== undefined) return `${prefix}${String(requestKey)}`;\n\n // Use cleaned URL as key as fallback\n let cleanedUrl = url || '';\n if (cleanedUrl.includes('://')) cleanedUrl = cleanedUrl.split('://')[1];\n if (cleanedUrl.includes('#')) cleanedUrl = cleanedUrl.split('#')[0];\n if (!options.includeQuery && cleanedUrl.includes('?')) cleanedUrl = cleanedUrl.split('?')[0];\n return `${prefix}${cleanedUrl}`;\n }\n\n /**\n * Cancels a specific request by its identifier.\n * @param {string} requestId - The unique identifier of the request to cancel\n * @returns {boolean} True if the request was found and cancelled, false otherwise\n */\n cancel(requestId) {\n /** @type {import('./index.d.ts').ActiveRequest|undefined} */\n const requestInfo = this.activeRequests.get(requestId);\n if (!requestInfo) return false;\n\n requestInfo.isCancelled = true; // Mark as cancelled\n\n // Try to abort using AbortController (for fetch)\n if (requestInfo.abortController && !requestInfo.abortController.signal.aborted) {\n try {\n requestInfo.abortController.abort('Request was cancelled');\n } catch (error) {}\n }\n\n // Try to cancel using cancel token/function (for axios and others)\n if (requestInfo.cancelToken) {\n try {\n if (typeof requestInfo.cancelToken === 'function') requestInfo.cancelToken();\n else if (requestInfo.cancelToken.cancel) requestInfo.cancelToken.cancel();\n } catch (error) {}\n }\n\n // Reject the wrapper promise\n this.#_deleteRequest(\n requestId,\n requestInfo.rejectWrapper,\n this.getOptions().verbose ? new Error(`Request ${requestId} was cancelled`) : null\n );\n return true;\n }\n\n /**\n * Link abort signal with HTTP client abort method.\n * Useful for custom HTTP clients that only support the abort method to cancel requests.\n * @param {Function} abortMethod - The abort method to call when the signal is aborted\n * @param {AbortSignal} signal - The signal to listen to\n */\n addAbortListener(abortMethod, signal) {\n if (!abortMethod || !signal) return;\n signal.addEventListener('abort', () => {\n if (typeof abortMethod === 'function') {\n try {\n abortMethod();\n } catch (error) {}\n }\n });\n }\n\n /**\n * Cancels all active requests.\n * @returns {number} The number of requests that were cancelled\n */\n cancelAll() {\n const requestIds = Array.from(this.activeRequests.keys());\n let cancelledCount = 0;\n requestIds.forEach((requestId) => {\n if (this.cancel(requestId)) cancelledCount++;\n });\n return cancelledCount;\n }\n\n /**\n * Resolves the AbortController for a request: explicit option, pending handoff, or new.\n * Clears the pending handoff so concurrent requests do not share it.\n * @param {AbortController|undefined} provided - Optional AbortController from options\n * @returns {AbortController}\n * @private\n */\n #_resolveAbortController(provided) {\n const abortController = provided || this.abortController || new AbortController();\n this.abortController = null;\n return abortController;\n }\n\n /**\n * Picks the best abort callback for a client request object.\n * @param {Object} req - The request object\n * @returns {Function|null}\n * @private\n */\n #_resolveAbortMethod(req) {\n if (!req) return null;\n if (typeof req.abort === 'function') return () => req.abort();\n const ExtAjax =\n typeof globalThis !== 'undefined' && globalThis.Ext && globalThis.Ext.Ajax ? globalThis.Ext.Ajax : null;\n if (req.xhr && ExtAjax && typeof ExtAjax.abort === 'function') {\n return () => ExtAjax.abort(req);\n }\n if (req.xhr && typeof req.xhr.abort === 'function') return () => req.xhr.abort();\n return null;\n }\n\n /**\n * Prepares request options by merging options and removing custom properties\n * @param {import('./index.d.ts').RequestOptions} options - Configuration options\n * @param {AbortSignal} signal - Abort signal to add to request options\n * @returns {Object} Prepared request options\n * @private\n */\n #_prepareRequestOptions(options, signal) {\n const requestOptions = {};\n const customOptions = ['abortController', 'cancelToken', 'requestKey', 'noCancel', 'includeQuery'];\n Object.keys(options).forEach((key) => {\n if (customOptions.includes(key)) return;\n requestOptions[key] = options[key];\n });\n requestOptions.signal = signal;\n return requestOptions;\n }\n\n /**\n * Deletes a request from the active requests map and rejects the wrapper promise\n * @param {string} requestId - The unique identifier of the request\n * @param {Function} rejectWrapper - The function to reject the wrapper promise\n * @param {*} error - The error to reject the wrapper promise with; the wrapper is not rejected if null/undefined\n * @private\n */\n #_deleteRequest(requestId, rejectWrapper, error) {\n this.activeRequests.delete(requestId);\n if (error !== null && error !== undefined) {\n rejectWrapper(error);\n }\n }\n\n /**\n * Completes a request by deleting it from the active requests map and resolving the wrapper promise\n * @param {string} requestId - The unique identifier of the request\n * @param {Function} resolveWrapper - The function to resolve the wrapper promise\n * @param {Promise} requestPromise - The request promise\n * @param {boolean} isCancelled - Whether the request was cancelled\n * @private\n */\n #_completeRequest(requestId, resolveWrapper, requestPromise, isCancelled) {\n this.activeRequests.delete(requestId);\n if (!isCancelled) {\n resolveWrapper(requestPromise);\n }\n }\n\n /**\n * Internal method that handles the core request logic.\n * @param {string} requestId - Unique identifier for the request\n * @param {Promise|import('./index.d.ts').RequestFunction|string} requestPromise - The request promise, function, or URL string\n * @param {import('./index.d.ts').BaseRequestOptions} options - Configuration options\n * @returns {Promise} A Promise that resolves/rejects based on the most recent request\n * @private\n */\n #_request(requestId, requestPromise, options = {}) {\n const abortController = this.#_resolveAbortController(options.abortController);\n\n // Handle different types of requestPromise inputs\n // Priority: Function (Custom logic) > String (URL) > Promise (axios, fetch, etc.)\n if (typeof requestPromise === 'function') {\n // Function: custom logic for any library (axios, ajax, etc.)\n try {\n requestPromise = requestPromise({\n options: this.#_prepareRequestOptions(options, abortController.signal),\n });\n } catch (error) {\n return Promise.reject(error);\n }\n } else if (typeof requestPromise === 'string') {\n // String (URL): make fetch internally\n try {\n requestPromise = fetch(requestPromise, this.#_prepareRequestOptions(options, abortController.signal));\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n // Link the request object's abort method (Ext.Ajax, XHR, etc.) to the cancellation signal\n this.addAbortListener(this.#_resolveAbortMethod(requestPromise), abortController.signal);\n\n // Cancel previous request with the same identifier if it exists\n if (!options.noCancel) this.cancel(requestId);\n\n // Create a wrapper promise that will be resolved/rejected based on the request\n let resolveWrapper, rejectWrapper;\n const wrapperPromise = new Promise((resolve, reject) => {\n resolveWrapper = resolve;\n rejectWrapper = reject;\n });\n\n /**\n * @type {import('./index.d.ts').ActiveRequest}\n */\n const requestInfo = {\n promise: requestPromise,\n abortController: abortController,\n cancelToken: options.cancelToken || null,\n resolveWrapper: resolveWrapper,\n rejectWrapper: rejectWrapper,\n isCancelled: false,\n };\n\n this.activeRequests.set(requestId, requestInfo);\n\n // Handle request promise completion\n if (requestPromise && typeof requestPromise.then === 'function') {\n try {\n let req = requestPromise.then((result) => {\n if (this.activeRequests.get(requestId) !== requestInfo) return;\n this.#_completeRequest(requestId, resolveWrapper, result, requestInfo.isCancelled);\n });\n if (req.catch)\n req.catch((error) => {\n onError(this, error);\n });\n } catch (error) {\n onError(this, error);\n }\n function onError(scope, error) {\n // Check if this requestInfo is still the active one, or if it was cancelled\n if (scope.activeRequests.get(requestId) !== requestInfo) return;\n if (requestInfo.isCancelled) {\n // Already cancelled: let cancel() handle cleanup and reject the wrapper promise\n scope.cancel(requestId);\n return;\n }\n // Only delete if this is still the active request\n scope.#_deleteRequest(requestId, rejectWrapper, error);\n }\n } else {\n // Non-promise (Ext.Ajax request object, raw XHR, etc.). Keep tracked until the\n // underlying XHR finishes so a later duplicate can still cancel it.\n const xhr =\n requestPromise &&\n (requestPromise.xhr ||\n (typeof XMLHttpRequest !== 'undefined' && requestPromise instanceof XMLHttpRequest\n ? requestPromise\n : null));\n const finish = () => {\n if (this.activeRequests.get(requestId) !== requestInfo) return;\n this.#_completeRequest(requestId, resolveWrapper, requestPromise, requestInfo.isCancelled);\n };\n if (xhr && typeof xhr.addEventListener === 'function') {\n xhr.addEventListener('loadend', finish);\n } else {\n setTimeout(finish, 0);\n }\n }\n return wrapperPromise;\n }\n}\n\nexport default RequestManager;\n\nexport { RequestManager };\n"],"names":["RequestManager","constructor","options","this","activeRequests","Map","abortController","getOptions","setOptions","getSignal","getAbortController","signal","AbortController","isActive","requestId","has","getActiveCount","size","clear","request","url","requestPromise","_request","getRequestId","fetch","axios","axiosInstance","axiosLib","requestOptions","ajax","ajaxFunction","Error","xhr","fetchOptions","XMLHttpRequest","method","toUpperCase","Promise","resolve","reject","onload","status","response","responseType","getResponseHeader","includes","JSON","parse","data","statusText","headers","getAllResponseHeaders","message","onerror","ontimeout","open","undefined","withCredentials","timeout","Object","keys","forEach","key","setRequestHeader","addEventListener","abort","send","body","requestKey","prefix","noCancel","Date","now","Math","random","toString","slice","String","cleanedUrl","split","includeQuery","cancel","requestInfo","get","isCancelled","aborted","error","cancelToken","_deleteRequest","rejectWrapper","verbose","addAbortListener","abortMethod","cancelAll","requestIds","Array","from","cancelledCount","_resolveAbortController","provided","_resolveAbortMethod","req","ExtAjax","globalThis","Ext","Ajax","_prepareRequestOptions","customOptions","delete","_completeRequest","resolveWrapper","wrapperPromise","promise","set","then","result","catch","onError","scope","finish","setTimeout"],"mappings":"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"}
@@ -9,7 +9,6 @@
9
9
  class RequestManager {
10
10
  constructor(options = {}) {
11
11
  /**
12
- * Map to store active requests by their unique identifier.
13
12
  * @type {Map<string, import('./index.d.ts').ActiveRequest>}
14
13
  */
15
14
  this.activeRequests = new Map();
@@ -97,15 +96,14 @@ class RequestManager {
97
96
  * @returns {Promise} A Promise that resolves/rejects based on the most recent request
98
97
  * @example
99
98
  * // Request with Promise
100
- * requestManager.request('/api/users', axios.get('/api/users', { cancelToken: axios.CancelToken.source().token }));
99
+ * requestManager.request('/api/users', axios.get('/api/users'));
101
100
  * @example
102
101
  * // Request with Function
103
102
  * requestManager.request('/api/users', ({ options }) => fetch('/api/users', { signal: options.signal, ...options }));
104
103
  * @example
105
104
  * // Request with Promise and custom cancellation grouping with requestKey
106
105
  * const options = {
107
- * requestKey: 'get-users',
108
- * cancelToken: axios.CancelToken.source().cancel
106
+ * requestKey: 'get-users'
109
107
  * }
110
108
  * requestManager.request('/api/users', axios.get('/api/users', options), options);
111
109
  */
@@ -166,12 +164,11 @@ class RequestManager {
166
164
  */
167
165
  axios(url, options = {}, axiosInstance = null) {
168
166
  const axiosLib = axiosInstance || axios;
169
- const cancelToken = axiosLib.CancelToken.source();
170
- const requestId = this.getRequestId(url, options);
171
- return this.#_request(requestId, axiosLib({ url, cancelToken: cancelToken.token, ...options }), {
172
- cancelToken: cancelToken,
173
- ...options,
174
- });
167
+ return this.#_request(
168
+ this.getRequestId(url, options),
169
+ ({ options: requestOptions }) => axiosLib({ url, ...requestOptions }),
170
+ options
171
+ );
175
172
  }
176
173
 
177
174
  /**
@@ -240,14 +237,13 @@ class RequestManager {
240
237
  let response = xhr.response;
241
238
  if (
242
239
  options.responseType === 'json' ||
243
- (xhr.getResponseHeader('Content-Type') &&
244
- xhr.getResponseHeader('Content-Type').includes('application/json'))
240
+ ((!options.responseType || options.responseType === 'text') &&
241
+ xhr.getResponseHeader('Content-Type')?.includes('application/json') &&
242
+ typeof response === 'string')
245
243
  ) {
246
244
  try {
247
- response = JSON.parse(xhr.responseText);
248
- } catch {
249
- response = xhr.responseText;
250
- }
245
+ response = JSON.parse(response);
246
+ } catch {}
251
247
  }
252
248
  resolve({
253
249
  data: response,