{"version":3,"file":"request-manager.min.cjs","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     * Gets the active requests\n     * @returns {Map<string, import('./index.d.ts').ActiveRequest>} The active requests\n     */\n    getActiveRequests() {\n        return this.activeRequests;\n    }\n\n    /**\n     * Gets the active request by its identifier\n     * @param {string} requestId - The unique identifier of the request\n     * @returns {import('./index.d.ts').ActiveRequest|undefined} The active request or undefined if not found\n     */\n    getActiveRequest(requestId) {\n        return this.activeRequests.get(requestId);\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 || (typeof axios !== 'undefined' ? axios : null);\n        if (!axiosLib) {\n            throw new Error(\n                'axios was not found: pass an axios instance as the third argument of requestManager.axios() or make sure axios is available globally'\n            );\n        }\n        this.#_checkAxiosVersion(axiosLib);\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<XMLHttpRequest>} A Promise that resolves with the XHR instance (or rejects on error)\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        return this.#_request(\n            this.getRequestId(url, options),\n            () => {\n                const xhr = new XMLHttpRequest();\n                const method = (options.method || 'GET').toUpperCase();\n                xhr.open(method, url, true);\n                if (options.responseType) xhr.responseType = options.responseType;\n                if (options.withCredentials !== undefined) xhr.withCredentials = options.withCredentials;\n                if (options.timeout !== undefined) xhr.timeout = options.timeout;\n                if (options.headers) {\n                    Object.keys(options.headers).forEach((key) => {\n                        xhr.setRequestHeader(key, options.headers[key]);\n                    });\n                }\n                xhr.send(options.body || null);\n                return xhr;\n            },\n            options\n        );\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(options);\n            } catch {\n                requestKey = null;\n            }\n        }\n        if (requestKey != null) 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\n        const methodPrefix =\n            options.includeMethod === false ? '' : `${(options.method || options.type || 'GET').toUpperCase()}_`;\n\n        return `${prefix}${methodPrefix}${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 request = this.getActiveRequest(requestId);\n        if (!request) return false;\n\n        request.isCancelled = true; // Mark as cancelled\n\n        // Try to abort using AbortController (for fetch)\n        if (request.abortController && !request.abortController.signal.aborted) {\n            try {\n                request.abortController.abort('Request was cancelled');\n            } catch (error) {}\n        }\n\n        // Try to cancel using cancel token/function (for axios and others)\n        if (request.cancelToken) {\n            try {\n                if (typeof request.cancelToken === 'function') request.cancelToken();\n                else if (request.cancelToken.cancel) request.cancelToken.cancel();\n            } catch (error) {}\n        }\n\n        // Reject the wrapper promise\n        const error = this.getOptions().verbose ? new Error(`Request ${requestId} was cancelled`) : null;\n        this.#_handleRequestFinish(requestId, error != null, () => request.rejectWrapper(error));\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.getActiveRequests().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 = [\n            'abortController',\n            'cancelToken',\n            'requestKey',\n            'noCancel',\n            'includeQuery',\n            'includeMethod',\n            'verbose',\n        ];\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     * Warns when the provided axios instance predates 0.22.0, the first version\n     * supporting AbortSignal cancellation. Older instances silently ignore\n     * options.signal, so duplicate requests would not be cancelled.\n     * @param {object} axiosLib - The axios instance about to be used\n     * @private\n     */\n    #_checkAxiosVersion(axiosLib) {\n        const version = typeof axiosLib?.VERSION === 'string' ? axiosLib.VERSION : null;\n        if (!version) return;\n        const [major, minor] = version.split('.').map(Number);\n        if (major === 0 && minor < 22) {\n            console.warn(\n                `[request-manager] axios >= 0.22.0 is required: axios ${version} ignores the AbortSignal used for automatic cancellation. Please upgrade axios.`\n            );\n        }\n    }\n\n    /**\n     * Handles the completion of a request by deleting it from the active requests map and resolving/rejecting the wrapper promise\n     * @param {string} requestId - The unique identifier of the request\n     * @param {boolean} condition - The condition to resolve/reject the wrapper promise\n     * @param {Function} wrapperPromise - The function to resolve/reject the wrapper promise\n     * @private\n     */\n    #_handleRequestFinish(requestId, condition, wrapperPromise) {\n        this.getActiveRequests().delete(requestId);\n        if (condition) {\n            wrapperPromise();\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        // Ext.Ajax / raw XHR: wrap so settle matches thenable clients (resolve ok, reject on error)\n        if (!requestPromise || typeof requestPromise.then !== 'function') {\n            const raw = requestPromise;\n            const xhr =\n                raw?.xhr ||\n                (typeof XMLHttpRequest !== 'undefined' && raw instanceof XMLHttpRequest ? raw : null) ||\n                (typeof raw?.addEventListener === 'function' && typeof raw?.abort === 'function' ? raw : null);\n            requestPromise = new Promise((resolve, reject) => {\n                if (!xhr || typeof xhr.addEventListener !== 'function') {\n                    resolve(raw);\n                    return;\n                }\n                let timedOut = false;\n                xhr.addEventListener('timeout', () => {\n                    timedOut = true;\n                });\n                xhr.addEventListener('loadend', () => {\n                    if (xhr.aborted) return reject({ message: 'Request was cancelled', xhr });\n                    if (timedOut) return reject({ message: 'Request timeout', xhr });\n                    if (xhr.status < 200 || xhr.status >= 300) {\n                        if (xhr.status === 0) return reject({ message: 'Network error', xhr });\n                        return reject({\n                            message: `Request failed with status ${xhr.status}`,\n                            status: xhr.status,\n                            statusText: xhr.statusText,\n                            xhr,\n                        });\n                    }\n                    resolve(raw);\n                });\n            });\n        }\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 request = {\n            promise: requestPromise,\n            abortController: abortController,\n            cancelToken: options.cancelToken || null,\n            resolveWrapper: resolveWrapper,\n            rejectWrapper: rejectWrapper,\n            isCancelled: false,\n        };\n\n        this.getActiveRequests().set(requestId, request);\n\n        // Handle request promise completion\n        try {\n            let req = requestPromise.then((result) => {\n                if (this.getActiveRequest(requestId) !== request) return;\n                this.#_handleRequestFinish(requestId, !request.isCancelled, () => resolveWrapper(result));\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 request is still the active one, or if it was cancelled\n            if (scope.getActiveRequest(requestId) !== request) return;\n            if (request.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.#_handleRequestFinish(requestId, error != null, () => rejectWrapper(error));\n        }\n        return wrapperPromise;\n    }\n}\n\nexport default RequestManager;\n\nexport { RequestManager };\n"],"names":["RequestManager","constructor","options","arguments","length","undefined","_classPrivateMethodInitSpec","_RequestManager_brand","this","activeRequests","Map","abortController","getOptions","setOptions","getSignal","getAbortController","signal","AbortController","getActiveRequests","getActiveRequest","requestId","get","isActive","has","getActiveCount","size","clear","request","url","requestPromise","_assertClassBrand","_request","call","getRequestId","fetch","axios","axiosLib","Error","_checkAxiosVersion","_ref","requestOptions","_objectSpread","ajax","ajaxFunction","_ref2","xhr","XMLHttpRequest","method","toUpperCase","open","responseType","withCredentials","timeout","headers","Object","keys","forEach","key","setRequestHeader","send","body","requestKey","prefix","noCancel","concat","Date","now","Math","random","toString","slice","_unused","String","cleanedUrl","includes","split","includeQuery","methodPrefix","includeMethod","type","cancel","isCancelled","aborted","abort","error","cancelToken","verbose","_handleRequestFinish","rejectWrapper","addAbortListener","abortMethod","addEventListener","cancelAll","requestIds","Array","from","cancelledCount","_resolveAbortController","provided","_resolveAbortMethod","req","ExtAjax","globalThis","Ext","Ajax","_prepareRequestOptions","customOptions","version","VERSION","_version$split$map2","_slicedToArray","map","Number","major","minor","console","warn","condition","wrapperPromise","delete","resolveWrapper","Promise","reject","then","raw","resolve","timedOut","message","status","statusText","promise","set","result","catch","onError","scope"],"mappings":"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"}