@hyper-fetch/core
Version:
Cache, Queue and Persist your requests no matter if you are online or offline!
1 lines • 296 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":[],"sources":["../src/plugin/plugin.ts","../src/utils/uuid.utils.ts","../../../node_modules/events/events.js","../src/utils/emitter.utils.ts","../src/managers/app/app.manager.ts","../src/managers/app/app.manager.utils.ts","../src/managers/app/app.manager.events.ts","../src/managers/app/app.manager.constants.ts","../src/managers/request/request.manager.ts","../src/managers/request/request.manager.utils.ts","../src/managers/request/request.manager.events.ts","../src/managers/logger/logger.manager.ts","../src/managers/logger/logger.manager.utils.ts","../src/managers/logger/logger.manager.constants.ts","../src/adapter/adapter.utils.ts","../src/request/request.hooks.ts","../src/constants/http.constants.ts","../src/request/request.utils.ts","../src/constants/time.constants.ts","../src/request/request.ts","../src/adapter/adapter.bindings.ts","../src/mocker/mocker.ts","../src/adapter/adapter.ts","../src/http-adapter/http-adapter.utils.ts","../src/http-adapter/http-adapter.constants.ts","../src/http-adapter/http-adapter.fetch.ts","../src/http-adapter/http-adapter.ts","../src/cache/cache.ts","../src/cache/cache.utils.ts","../src/cache/cache.events.ts","../src/dispatcher/dispatcher.constants.ts","../src/dispatcher/dispatcher.events.ts","../src/dispatcher/dispatcher.ts","../src/dispatcher/dispatcher.utils.ts","../src/client/client.utils.ts","../src/client/client.ts","../src/client/client.constants.ts","../src/client/client.create.ts","../src/sdk/sdk.ts"],"sourcesContent":["import type { PluginMethodParameters, PluginMethods, PluginOptionsType } from \"plugin\";\nimport type { ClientInstance } from \"client\";\n\n/**\n * Base class for plugins that hook into the request, cache, dispatcher, and adapter lifecycle.\n * Extend this to build devtools, logging, analytics, or custom side-effect plugins.\n */\nexport class Plugin<Client extends ClientInstance = ClientInstance, PluginData = void> {\n public name: string;\n public data: PluginData;\n\n public client: Client | undefined = undefined;\n\n private pluginMethods: Partial<PluginMethods<Client>> = {};\n\n constructor(public config: PluginOptionsType<PluginData>) {\n this.name = config.name;\n if (config.data) {\n this.data = config.data;\n }\n }\n\n /** Bind the plugin to a client instance. Called automatically when the plugin is added via `client.addPlugin()`. */\n initialize = (client: Client) => {\n this.client = client;\n return this;\n };\n\n /** Invoke a registered plugin method by name. Used internally by the client to dispatch lifecycle events. */\n trigger = <Key extends keyof PluginMethods<Client>>(method: Key, data: PluginMethodParameters<Key, Client>) => {\n const callback = this.pluginMethods[method];\n if (callback) {\n callback(data as any);\n }\n };\n\n /* -------------------------------------------------------------------------------------------------\n * Plugin lifecycle\n * -----------------------------------------------------------------------------------------------*/\n\n /**\n * Callback that will be executed when plugin is mounted\n */\n onMount = (callback: PluginMethods<Client>[\"onMount\"]) => {\n this.pluginMethods.onMount = callback;\n return this;\n };\n\n /**\n * Callback that will be executed when plugin is unmounted\n */\n onUnmount = (callback: PluginMethods<Client>[\"onUnmount\"]) => {\n this.pluginMethods.onUnmount = callback;\n return this;\n };\n\n /* -------------------------------------------------------------------------------------------------\n * Request lifecycle\n * -----------------------------------------------------------------------------------------------*/\n\n /**\n * Callback that will be executed when request is created\n */\n onRequestCreate = (callback: PluginMethods<Client>[\"onRequestCreate\"]) => {\n this.pluginMethods.onRequestCreate = callback;\n return this;\n };\n /**\n * Callback that will be executed when request gets triggered\n */\n onRequestTrigger = (callback: PluginMethods<Client>[\"onRequestTrigger\"]) => {\n this.pluginMethods.onRequestTrigger = callback;\n return this;\n };\n /**\n * Callback that will be executed when request starts\n */\n onRequestStart = (callback: PluginMethods<Client>[\"onRequestStart\"]) => {\n this.pluginMethods.onRequestStart = callback;\n return this;\n };\n /**\n * Callback that will be executed when response is successful\n */\n onRequestSuccess = (callback: PluginMethods<Client>[\"onRequestSuccess\"]) => {\n this.pluginMethods.onRequestSuccess = callback;\n return this;\n };\n /**\n * Callback that will be executed when response is failed\n */\n onRequestError = (callback: PluginMethods<Client>[\"onRequestError\"]) => {\n this.pluginMethods.onRequestError = callback;\n return this;\n };\n /**\n * Callback that will be executed when response is finished\n */\n onRequestFinished = (callback: PluginMethods<Client>[\"onRequestFinished\"]) => {\n this.pluginMethods.onRequestFinished = callback;\n return this;\n };\n\n /* -------------------------------------------------------------------------------------------------\n * Dispatcher lifecycle\n * -----------------------------------------------------------------------------------------------*/\n\n /** Called when the dispatcher storage is fully cleared */\n onDispatcherCleared = (callback: PluginMethods<Client>[\"onDispatcherCleared\"]) => {\n this.pluginMethods.onDispatcherCleared = callback;\n return this;\n };\n\n /** Called when a dispatcher queue has no more pending requests */\n onDispatcherQueueDrained = (callback: PluginMethods<Client>[\"onDispatcherQueueDrained\"]) => {\n this.pluginMethods.onDispatcherQueueDrained = callback;\n return this;\n };\n\n /** Called when a dispatcher queue transitions to running, paused, or stopped */\n onDispatcherQueueRunning = (callback: PluginMethods<Client>[\"onDispatcherQueueRunning\"]) => {\n this.pluginMethods.onDispatcherQueueRunning = callback;\n return this;\n };\n\n /** Called when a new item is added to a dispatcher queue */\n onDispatcherItemAdded = (callback: PluginMethods<Client>[\"onDispatcherItemAdded\"]) => {\n this.pluginMethods.onDispatcherItemAdded = callback;\n return this;\n };\n\n /** Called when an item is removed from a dispatcher queue */\n onDispatcherItemDeleted = (callback: PluginMethods<Client>[\"onDispatcherItemDeleted\"]) => {\n this.pluginMethods.onDispatcherItemDeleted = callback;\n return this;\n };\n\n /** Called when a new dispatcher queue is created */\n onDispatcherQueueCreated = (callback: PluginMethods<Client>[\"onDispatcherQueueCreated\"]) => {\n this.pluginMethods.onDispatcherQueueCreated = callback;\n return this;\n };\n\n /** Called when an entire dispatcher queue is cleared */\n onDispatcherQueueCleared = (callback: PluginMethods<Client>[\"onDispatcherQueueCleared\"]) => {\n this.pluginMethods.onDispatcherQueueCleared = callback;\n return this;\n };\n\n /* -------------------------------------------------------------------------------------------------\n * Cache lifecycle\n * -----------------------------------------------------------------------------------------------*/\n\n /** Called when a cache entry is created or updated */\n onCacheItemChange = (callback: PluginMethods<Client>[\"onCacheItemChange\"]) => {\n this.pluginMethods.onCacheItemChange = callback;\n return this;\n };\n\n /** Called when a cache entry is deleted */\n onCacheItemDelete = (callback: PluginMethods<Client>[\"onCacheItemDelete\"]) => {\n this.pluginMethods.onCacheItemDelete = callback;\n return this;\n };\n\n /* -------------------------------------------------------------------------------------------------\n * Adapter lifecycle\n * -----------------------------------------------------------------------------------------------*/\n\n /** Called when the adapter fetcher is about to execute a request */\n onAdapterFetch = (callback: PluginMethods<Client>[\"onAdapterFetch\"]) => {\n this.pluginMethods.onAdapterFetch = callback;\n return this;\n };\n}\n","import type { RequestInstance } from \"request\";\n\nexport const getUniqueRequestId = (request: Pick<RequestInstance, \"queryKey\">) => {\n return `${request.queryKey}_${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`;\n};\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar R = typeof Reflect === 'object' ? Reflect : null\nvar ReflectApply = R && typeof R.apply === 'function'\n ? R.apply\n : function ReflectApply(target, receiver, args) {\n return Function.prototype.apply.call(target, receiver, args);\n }\n\nvar ReflectOwnKeys\nif (R && typeof R.ownKeys === 'function') {\n ReflectOwnKeys = R.ownKeys\n} else if (Object.getOwnPropertySymbols) {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target)\n .concat(Object.getOwnPropertySymbols(target));\n };\n} else {\n ReflectOwnKeys = function ReflectOwnKeys(target) {\n return Object.getOwnPropertyNames(target);\n };\n}\n\nfunction ProcessEmitWarning(warning) {\n if (console && console.warn) console.warn(warning);\n}\n\nvar NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {\n return value !== value;\n}\n\nfunction EventEmitter() {\n EventEmitter.init.call(this);\n}\nmodule.exports = EventEmitter;\nmodule.exports.once = once;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._eventsCount = 0;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nvar defaultMaxListeners = 10;\n\nfunction checkListener(listener) {\n if (typeof listener !== 'function') {\n throw new TypeError('The \"listener\" argument must be of type Function. Received type ' + typeof listener);\n }\n}\n\nObject.defineProperty(EventEmitter, 'defaultMaxListeners', {\n enumerable: true,\n get: function() {\n return defaultMaxListeners;\n },\n set: function(arg) {\n if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {\n throw new RangeError('The value of \"defaultMaxListeners\" is out of range. It must be a non-negative number. Received ' + arg + '.');\n }\n defaultMaxListeners = arg;\n }\n});\n\nEventEmitter.init = function() {\n\n if (this._events === undefined ||\n this._events === Object.getPrototypeOf(this)._events) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n }\n\n this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {\n throw new RangeError('The value of \"n\" is out of range. It must be a non-negative number. Received ' + n + '.');\n }\n this._maxListeners = n;\n return this;\n};\n\nfunction _getMaxListeners(that) {\n if (that._maxListeners === undefined)\n return EventEmitter.defaultMaxListeners;\n return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n return _getMaxListeners(this);\n};\n\nEventEmitter.prototype.emit = function emit(type) {\n var args = [];\n for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);\n var doError = (type === 'error');\n\n var events = this._events;\n if (events !== undefined)\n doError = (doError && events.error === undefined);\n else if (!doError)\n return false;\n\n // If there is no 'error' event listener then throw.\n if (doError) {\n var er;\n if (args.length > 0)\n er = args[0];\n if (er instanceof Error) {\n // Note: The comments on the `throw` lines are intentional, they show\n // up in Node's output if this results in an unhandled exception.\n throw er; // Unhandled 'error' event\n }\n // At least give some kind of context to the user\n var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));\n err.context = er;\n throw err; // Unhandled 'error' event\n }\n\n var handler = events[type];\n\n if (handler === undefined)\n return false;\n\n if (typeof handler === 'function') {\n ReflectApply(handler, this, args);\n } else {\n var len = handler.length;\n var listeners = arrayClone(handler, len);\n for (var i = 0; i < len; ++i)\n ReflectApply(listeners[i], this, args);\n }\n\n return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n var m;\n var events;\n var existing;\n\n checkListener(listener);\n\n events = target._events;\n if (events === undefined) {\n events = target._events = Object.create(null);\n target._eventsCount = 0;\n } else {\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (events.newListener !== undefined) {\n target.emit('newListener', type,\n listener.listener ? listener.listener : listener);\n\n // Re-assign `events` because a newListener handler could have caused the\n // this._events to be assigned to a new object\n events = target._events;\n }\n existing = events[type];\n }\n\n if (existing === undefined) {\n // Optimize the case of one listener. Don't need the extra array object.\n existing = events[type] = listener;\n ++target._eventsCount;\n } else {\n if (typeof existing === 'function') {\n // Adding the second element, need to change to array.\n existing = events[type] =\n prepend ? [listener, existing] : [existing, listener];\n // If we've already got an array, just append.\n } else if (prepend) {\n existing.unshift(listener);\n } else {\n existing.push(listener);\n }\n\n // Check for listener leak\n m = _getMaxListeners(target);\n if (m > 0 && existing.length > m && !existing.warned) {\n existing.warned = true;\n // No error code for this since it is a Warning\n // eslint-disable-next-line no-restricted-syntax\n var w = new Error('Possible EventEmitter memory leak detected. ' +\n existing.length + ' ' + String(type) + ' listeners ' +\n 'added. Use emitter.setMaxListeners() to ' +\n 'increase limit');\n w.name = 'MaxListenersExceededWarning';\n w.emitter = target;\n w.type = type;\n w.count = existing.length;\n ProcessEmitWarning(w);\n }\n }\n\n return target;\n}\n\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n function prependListener(type, listener) {\n return _addListener(this, type, listener, true);\n };\n\nfunction onceWrapper() {\n if (!this.fired) {\n this.target.removeListener(this.type, this.wrapFn);\n this.fired = true;\n if (arguments.length === 0)\n return this.listener.call(this.target);\n return this.listener.apply(this.target, arguments);\n }\n}\n\nfunction _onceWrap(target, type, listener) {\n var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };\n var wrapped = onceWrapper.bind(state);\n wrapped.listener = listener;\n state.wrapFn = wrapped;\n return wrapped;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n checkListener(listener);\n this.on(type, _onceWrap(this, type, listener));\n return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n function prependOnceListener(type, listener) {\n checkListener(listener);\n this.prependListener(type, _onceWrap(this, type, listener));\n return this;\n };\n\n// Emits a 'removeListener' event if and only if the listener was removed.\nEventEmitter.prototype.removeListener =\n function removeListener(type, listener) {\n var list, events, position, i, originalListener;\n\n checkListener(listener);\n\n events = this._events;\n if (events === undefined)\n return this;\n\n list = events[type];\n if (list === undefined)\n return this;\n\n if (list === listener || list.listener === listener) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else {\n delete events[type];\n if (events.removeListener)\n this.emit('removeListener', type, list.listener || listener);\n }\n } else if (typeof list !== 'function') {\n position = -1;\n\n for (i = list.length - 1; i >= 0; i--) {\n if (list[i] === listener || list[i].listener === listener) {\n originalListener = list[i].listener;\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (position === 0)\n list.shift();\n else {\n spliceOne(list, position);\n }\n\n if (list.length === 1)\n events[type] = list[0];\n\n if (events.removeListener !== undefined)\n this.emit('removeListener', type, originalListener || listener);\n }\n\n return this;\n };\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners =\n function removeAllListeners(type) {\n var listeners, events, i;\n\n events = this._events;\n if (events === undefined)\n return this;\n\n // not listening for removeListener, no need to emit\n if (events.removeListener === undefined) {\n if (arguments.length === 0) {\n this._events = Object.create(null);\n this._eventsCount = 0;\n } else if (events[type] !== undefined) {\n if (--this._eventsCount === 0)\n this._events = Object.create(null);\n else\n delete events[type];\n }\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n var keys = Object.keys(events);\n var key;\n for (i = 0; i < keys.length; ++i) {\n key = keys[i];\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = Object.create(null);\n this._eventsCount = 0;\n return this;\n }\n\n listeners = events[type];\n\n if (typeof listeners === 'function') {\n this.removeListener(type, listeners);\n } else if (listeners !== undefined) {\n // LIFO order\n for (i = listeners.length - 1; i >= 0; i--) {\n this.removeListener(type, listeners[i]);\n }\n }\n\n return this;\n };\n\nfunction _listeners(target, type, unwrap) {\n var events = target._events;\n\n if (events === undefined)\n return [];\n\n var evlistener = events[type];\n if (evlistener === undefined)\n return [];\n\n if (typeof evlistener === 'function')\n return unwrap ? [evlistener.listener || evlistener] : [evlistener];\n\n return unwrap ?\n unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);\n}\n\nEventEmitter.prototype.listeners = function listeners(type) {\n return _listeners(this, type, true);\n};\n\nEventEmitter.prototype.rawListeners = function rawListeners(type) {\n return _listeners(this, type, false);\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n if (typeof emitter.listenerCount === 'function') {\n return emitter.listenerCount(type);\n } else {\n return listenerCount.call(emitter, type);\n }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n var events = this._events;\n\n if (events !== undefined) {\n var evlistener = events[type];\n\n if (typeof evlistener === 'function') {\n return 1;\n } else if (evlistener !== undefined) {\n return evlistener.length;\n }\n }\n\n return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];\n};\n\nfunction arrayClone(arr, n) {\n var copy = new Array(n);\n for (var i = 0; i < n; ++i)\n copy[i] = arr[i];\n return copy;\n}\n\nfunction spliceOne(list, index) {\n for (; index + 1 < list.length; index++)\n list[index] = list[index + 1];\n list.pop();\n}\n\nfunction unwrapListeners(arr) {\n var ret = new Array(arr.length);\n for (var i = 0; i < ret.length; ++i) {\n ret[i] = arr[i].listener || arr[i];\n }\n return ret;\n}\n\nfunction once(emitter, name) {\n return new Promise(function (resolve, reject) {\n function errorListener(err) {\n emitter.removeListener(name, resolver);\n reject(err);\n }\n\n function resolver() {\n if (typeof emitter.removeListener === 'function') {\n emitter.removeListener('error', errorListener);\n }\n resolve([].slice.call(arguments));\n };\n\n eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });\n if (name !== 'error') {\n addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });\n }\n });\n}\n\nfunction addErrorHandlerIfEventEmitter(emitter, handler, flags) {\n if (typeof emitter.on === 'function') {\n eventTargetAgnosticAddListener(emitter, 'error', handler, flags);\n }\n}\n\nfunction eventTargetAgnosticAddListener(emitter, name, listener, flags) {\n if (typeof emitter.on === 'function') {\n if (flags.once) {\n emitter.once(name, listener);\n } else {\n emitter.on(name, listener);\n }\n } else if (typeof emitter.addEventListener === 'function') {\n // EventTarget does not have `error` event semantics like Node\n // EventEmitters, we do not listen for `error` events here.\n emitter.addEventListener(name, function wrapListener(arg) {\n // IE does not have builtin `{ once: true }` support so we\n // have to do it manually.\n if (flags.once) {\n emitter.removeEventListener(name, wrapListener);\n }\n listener(arg);\n });\n } else {\n throw new TypeError('The \"emitter\" argument must be of type EventEmitter. Received type ' + typeof emitter);\n }\n}\n","import Emitter from \"events\";\n\nconst getListenName = (event: string | symbol) => `listen_${String(event)}`;\n\nexport class EventEmitter extends Emitter {\n emitCallbacks: Array<(event: string, data: any, isTriggeredExternally?: true) => void> = [];\n\n // eslint-disable-next-line @typescript-eslint/no-useless-constructor\n constructor(options?: ConstructorParameters<typeof Emitter>[0]) {\n super(options);\n }\n\n emit(type: string, data: any, isTriggeredExternally: boolean) {\n const params: [string, any, true?] = [type, data];\n\n if (isTriggeredExternally) {\n params.push(isTriggeredExternally);\n }\n\n this.emitCallbacks?.forEach((callback) => callback(...params));\n return super.emit(...params);\n }\n\n onEmit = (callback: (event: string, data: any, isTriggeredExternally?: true) => void) => {\n this.emitCallbacks?.push(callback);\n return () => {\n this.emitCallbacks = this.emitCallbacks?.filter((cb) => cb !== callback);\n };\n };\n\n onListener = (event: string, listener: (count: number) => void) => {\n super.on(getListenName(event), listener);\n return () => {\n super.off(getListenName(event), listener);\n };\n };\n\n on = (event: string | symbol, listener: (...args: any[]) => void) => {\n super.on(event, listener);\n super.emit(getListenName(event), super.listeners(event).length);\n return this;\n };\n\n off = (event: string | symbol, listener: (...args: any[]) => void) => {\n super.off(event, listener);\n super.emit(getListenName(event), super.listeners(event).length);\n return this;\n };\n\n addListener = this.on;\n removeListener = this.off;\n}\n","import { EventEmitter } from \"utils\";\nimport type { AppManagerOptionsType } from \"managers\";\nimport { appManagerInitialOptions, getAppManagerEvents, hasDocument } from \"managers\";\n\n/**\n * App manager handles main application states - focus and online. Those two values can answer questions:\n * - Is the tab or current view instance focused and visible for user?\n * - Is our application online or offline?\n * With the app manager it is not a problem to get the valid answer for this question.\n *\n * @caution\n * Make sure to apply valid focus/online handlers for different environments like for example for native mobile applications.\n */\nexport class AppManager {\n emitter = new EventEmitter();\n events = getAppManagerEvents(this.emitter);\n\n isBrowser: boolean;\n isOnline: boolean;\n isFocused: boolean;\n\n constructor(public options?: AppManagerOptionsType) {\n this.emitter?.setMaxListeners(1000);\n const {\n initiallyFocused = appManagerInitialOptions.initiallyFocused,\n initiallyOnline = appManagerInitialOptions.initiallyOnline,\n } = this.options || appManagerInitialOptions;\n\n this.setInitialFocus(initiallyFocused);\n this.setInitialOnline(initiallyOnline);\n\n this.isBrowser = hasDocument();\n }\n\n initialize = () => {\n const { focusEvent = appManagerInitialOptions.focusEvent, onlineEvent = appManagerInitialOptions.onlineEvent } =\n this.options || appManagerInitialOptions;\n\n focusEvent(this.setFocused);\n onlineEvent(this.setOnline);\n };\n\n private setInitialFocus = async (initValue: Exclude<AppManagerOptionsType[\"initiallyFocused\"], undefined>) => {\n if (typeof initValue === \"function\") {\n this.isFocused = false;\n this.isFocused = await initValue();\n } else {\n this.isFocused = initValue;\n }\n };\n\n private setInitialOnline = async (initValue: Exclude<AppManagerOptionsType[\"initiallyOnline\"], undefined>) => {\n if (typeof initValue === \"function\") {\n this.isOnline = false;\n this.isOnline = await initValue();\n } else {\n this.isOnline = initValue;\n }\n };\n\n setFocused = (isFocused: boolean) => {\n this.isFocused = isFocused;\n\n if (isFocused) {\n this.events.emitFocus();\n } else {\n this.events.emitBlur();\n }\n };\n\n setOnline = (isOnline: boolean) => {\n this.isOnline = isOnline;\n\n if (isOnline) {\n this.events.emitOnline();\n } else {\n this.events.emitOffline();\n }\n };\n}\n","export const hasWindow = () => {\n try {\n return Boolean(window && window.addEventListener);\n } catch (err) {\n /* istanbul ignore next */\n return false;\n }\n};\n\nexport const hasDocument = () => {\n try {\n return Boolean(hasWindow() && window.document && window.document.addEventListener);\n } catch (err) {\n /* istanbul ignore next */\n return false;\n }\n};\n\nexport const onWindowEvent = <K extends keyof WindowEventMap>(\n key: K,\n listener: (this: Window, ev: WindowEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions | undefined,\n): VoidFunction => {\n /* istanbul ignore next */\n if (hasWindow()) {\n window.addEventListener(key, listener, options);\n return () => window.removeEventListener(key, listener, options);\n }\n /* istanbul ignore next */\n return () => null;\n};\n\nexport const onDocumentEvent = <K extends keyof DocumentEventMap>(\n key: K,\n listener: (this: Document, ev: DocumentEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions | undefined,\n): VoidFunction => {\n /* istanbul ignore next */\n if (hasDocument()) {\n window.document.addEventListener(key, listener, options);\n return () => window.document.removeEventListener(key, listener, options);\n }\n /* istanbul ignore next */\n return () => null;\n};\n","import type EventEmitter from \"events\";\n\nimport { AppEvents } from \"managers\";\n\n/** Create event emitters and listeners for application-level focus, blur, online, and offline state changes. */\nexport const getAppManagerEvents = (emitter: EventEmitter) => ({\n /** Emit when the application window gains focus */\n emitFocus: (): void => {\n emitter.emit(AppEvents.FOCUS);\n },\n /** Emit when the application window loses focus */\n emitBlur: (): void => {\n emitter.emit(AppEvents.BLUR);\n },\n /** Emit when the application transitions to online state */\n emitOnline: (): void => {\n emitter.emit(AppEvents.ONLINE);\n },\n /** Emit when the application transitions to offline state */\n emitOffline: (): void => {\n emitter.emit(AppEvents.OFFLINE);\n },\n /** Listen for focus events */\n onFocus: (callback: () => void): VoidFunction => {\n emitter.on(AppEvents.FOCUS, callback);\n return () => emitter.removeListener(AppEvents.FOCUS, callback);\n },\n /** Listen for blur events */\n onBlur: (callback: () => void): VoidFunction => {\n emitter.on(AppEvents.BLUR, callback);\n return () => emitter.removeListener(AppEvents.BLUR, callback);\n },\n /** Listen for online state transitions */\n onOnline: (callback: () => void): VoidFunction => {\n emitter.on(AppEvents.ONLINE, callback);\n return () => emitter.removeListener(AppEvents.ONLINE, callback);\n },\n /** Listen for offline state transitions */\n onOffline: (callback: () => void): VoidFunction => {\n emitter.on(AppEvents.OFFLINE, callback);\n return () => emitter.removeListener(AppEvents.OFFLINE, callback);\n },\n});\n","import type { RequiredKeys } from \"types\";\nimport type { AppManagerOptionsType } from \"managers\";\nimport { onWindowEvent, onDocumentEvent } from \"./app.manager.utils\";\n\nexport enum AppEvents {\n FOCUS = \"focus\",\n BLUR = \"blur\",\n ONLINE = \"online\",\n OFFLINE = \"offline\",\n}\n\nexport const appManagerInitialOptions: RequiredKeys<AppManagerOptionsType> = {\n initiallyFocused: true,\n initiallyOnline: true,\n focusEvent: (setFocused) => {\n onDocumentEvent(\"visibilitychange\", () => setFocused(true));\n onWindowEvent(\"focus\", () => setFocused(true));\n onWindowEvent(\"blur\", () => setFocused(false));\n },\n onlineEvent: (setOnline) => {\n onWindowEvent(\"online\", () => setOnline(true));\n onWindowEvent(\"offline\", () => setOnline(false));\n },\n};\n","import { EventEmitter } from \"utils\";\nimport { getRequestManagerEvents } from \"managers\";\n\n/**\n * **Request Manager** is used to emit `request lifecycle events` like - request start, request end, upload and download progress.\n * It is also the place of `request aborting` system, here we store all the keys and controllers that are isolated for each client instance.\n */\nexport class RequestManager {\n emitter = new EventEmitter();\n events = getRequestManagerEvents(this.emitter);\n\n constructor() {\n this.emitter?.setMaxListeners(1000);\n }\n\n abortControllers = new Map<string, Map<string, AbortController>>();\n\n addAbortController = (abortKey: string, requestId: string) => {\n let abortGroup = this.abortControllers.get(abortKey);\n if (!abortGroup) {\n const newAbortGroup = new Map();\n abortGroup = newAbortGroup;\n this.abortControllers.set(abortKey, newAbortGroup);\n }\n\n const abortController = abortGroup.get(requestId);\n if (!abortController || abortController.signal.aborted) {\n abortGroup.set(requestId, new AbortController());\n }\n };\n\n getAbortController = (abortKey: string, requestId: string) => {\n return this.abortControllers.get(abortKey)?.get(requestId);\n };\n\n removeAbortController = (abortKey: string, requestId: string) => {\n this.abortControllers.get(abortKey)?.delete(requestId);\n };\n\n // Aborting\n\n useAbortController = (abortKey: string, requestId: string) => {\n const controller = this.abortControllers.get(abortKey)?.get(requestId);\n controller?.abort();\n };\n\n abortByKey = (abortKey: string) => {\n const controllers = this.abortControllers.get(abortKey);\n\n if (controllers) {\n const entries = Array.from(controllers.entries());\n entries.forEach(([key]) => {\n this.useAbortController(abortKey, key);\n });\n }\n };\n\n abortByRequestId = (abortKey: string, requestId: string) => {\n this.useAbortController(abortKey, requestId);\n };\n\n abortAll = () => {\n const entries = Array.from(this.abortControllers.entries());\n entries.forEach(([abortKey, value]) => {\n const controllers = Array.from(value.entries());\n controllers.forEach(([requestId]) => {\n this.useAbortController(abortKey, requestId);\n });\n });\n };\n}\n","// Events\n\nexport const getLoadingKey = (): string => `loading-event-any`;\nexport const getLoadingByQueryKey = (queryKey: string): string => `${queryKey}-loading-event`;\nexport const getLoadingByCacheKey = (cacheKey: string): string => `${cacheKey}-loading-cache-event`;\nexport const getLoadingByIdKey = (id: string): string => `${id}-loading-event-by-id`;\nexport const getRemoveKey = (): string => `remove-event-any`;\nexport const getRemoveByQueryKey = (queryKey: string): string => `${queryKey}-remove-event`;\nexport const getRemoveByIdKey = (id: string): string => `${id}-remove-event-by-id`;\nexport const getAbortKey = () => `request-abort-any`;\nexport const getAbortByAbortKey = (abortKey: string) => `${abortKey}-request-abort`;\nexport const getAbortByIdKey = (id: string) => `${id}-request-abort-by-id`;\nexport const getResponseKey = () => `response-any`;\nexport const getResponseByCacheKey = (cacheKey: string) => `${cacheKey}-response`;\nexport const getResponseByIdKey = (id: string) => `${id}-response-by-id`;\nexport const getRequestStartKey = () => `request-start-any`;\nexport const getRequestStarByQueryKey = (queryKey: string) => `${queryKey}-request-start`;\nexport const getRequestStartByIdKey = (id: string) => `${id}-request-start-by-id`;\nexport const getResponseStartKey = () => `response-start-any`;\nexport const getResponseStartByQueryKey = (queryKey: string) => `${queryKey}-response-start`;\nexport const getResponseStartByIdKey = (id: string) => `${id}-response-start-by-id`;\nexport const getUploadProgressKey = () => `request-progress-any`;\nexport const getUploadProgressByQueryKey = (queryKey: string) => `${queryKey}-request-progress`;\nexport const getUploadProgressByIdKey = (id: string) => `${id}-request-progress-by-id`;\nexport const getDownloadProgressKey = () => `response-progress-any`;\nexport const getDownloadProgressByQueryKey = (queryKey: string) => `${queryKey}-response-progress`;\nexport const getDownloadProgressByIdKey = (id: string) => `${id}-response-progress-by-id`;\nexport const getRequestDeduplicatedKey = () => `request-deduplicated-any`;\nexport const getRequestDeduplicatedByQueryKey = (queryKey: string) => `${queryKey}-query-request-deduplicated`;\nexport const getRequestDeduplicatedByCacheKey = (cacheKey: string) => `${cacheKey}-cache-request-deduplicated`;\nexport const getRequestDeduplicatedByIdKey = (id: string) => `${id}-request-deduplicated-by-id`;\n","/* eslint-disable max-params */\nimport type EventEmitter from \"events\";\n\nimport type {\n RequestEventType,\n RequestLoadingEventType,\n RequestProgressEventType,\n RequestResponseEventType,\n RequestRemovedEventType,\n RequestDeduplicatedEventType,\n} from \"managers\";\nimport {\n getRequestStarByQueryKey,\n getResponseStartByQueryKey,\n getDownloadProgressByQueryKey,\n getUploadProgressByQueryKey,\n getResponseByIdKey,\n getAbortByAbortKey,\n getAbortByIdKey,\n getResponseByCacheKey,\n getUploadProgressByIdKey,\n getDownloadProgressByIdKey,\n getResponseStartByIdKey,\n getRequestStartByIdKey,\n getLoadingByQueryKey,\n getLoadingByIdKey,\n getRemoveByQueryKey,\n getRemoveByIdKey,\n getLoadingKey,\n getRequestStartKey,\n getUploadProgressKey,\n getDownloadProgressKey,\n getResponseKey,\n getAbortKey,\n getRemoveKey,\n getResponseStartKey,\n getLoadingByCacheKey,\n getRequestDeduplicatedKey,\n getRequestDeduplicatedByIdKey,\n getRequestDeduplicatedByCacheKey,\n getRequestDeduplicatedByQueryKey,\n} from \"managers\";\nimport type { AdapterInstance } from \"adapter\";\nimport type { RequestInstance } from \"request\";\nimport type { Client } from \"client\";\nimport type { ExtendRequest } from \"types\";\n\n/** Create event emitters and listeners for the request lifecycle: loading, progress, response, abort, deduplication, and removal. */\nexport const getRequestManagerEvents = (emitter: EventEmitter) => ({\n /**\n * Emitters\n */\n\n /** Emit when a request is deduplicated (skipped because an identical one is in-flight) */\n emitDeduplicated: (data: RequestDeduplicatedEventType<RequestInstance>, isTriggeredExternally = false): void => {\n emitter.emit(getRequestDeduplicatedKey(), data, isTriggeredExternally);\n emitter.emit(getRequestDeduplicatedByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getRequestDeduplicatedByCacheKey(data.request.cacheKey), data, isTriggeredExternally);\n emitter.emit(getRequestDeduplicatedByQueryKey(data.request.queryKey), data, isTriggeredExternally);\n },\n\n /** Emit loading state changes for a request */\n emitLoading: (data: RequestLoadingEventType<RequestInstance>, isTriggeredExternally = false): void => {\n emitter.emit(getLoadingKey(), data, isTriggeredExternally);\n emitter.emit(getLoadingByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getLoadingByCacheKey(data.request.cacheKey), data, isTriggeredExternally);\n emitter.emit(getLoadingByQueryKey(data.request.queryKey), data, isTriggeredExternally);\n },\n\n /** Emit when a request starts being sent */\n emitRequestStart: (data: RequestEventType<RequestInstance>, isTriggeredExternally = false): void => {\n emitter.emit(getRequestStartKey(), data, isTriggeredExternally);\n emitter.emit(getRequestStartByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getRequestStarByQueryKey(data.request.queryKey), data, isTriggeredExternally);\n },\n /** Emit when the response starts being received */\n emitResponseStart: (data: RequestEventType<RequestInstance>, isTriggeredExternally = false): void => {\n emitter.emit(getResponseStartKey(), data, isTriggeredExternally);\n emitter.emit(getResponseStartByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getResponseStartByQueryKey(data.request.queryKey), data, isTriggeredExternally);\n },\n\n /** Emit upload progress updates */\n emitUploadProgress: (data: RequestProgressEventType<RequestInstance>, isTriggeredExternally = false): void => {\n emitter.emit(getUploadProgressKey(), data, isTriggeredExternally);\n emitter.emit(getUploadProgressByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getUploadProgressByQueryKey(data.request.queryKey), data, isTriggeredExternally);\n },\n /** Emit download progress updates */\n emitDownloadProgress: (data: RequestProgressEventType<RequestInstance>, isTriggeredExternally = false): void => {\n emitter.emit(getDownloadProgressKey(), data, isTriggeredExternally);\n emitter.emit(getDownloadProgressByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getDownloadProgressByQueryKey(data.request.queryKey), data, isTriggeredExternally);\n },\n\n /** Emit when a response is received */\n emitResponse: <Adapter extends AdapterInstance>(\n data: RequestResponseEventType<ExtendRequest<RequestInstance, { client: Client<any, Adapter> }>>,\n isTriggeredExternally = false,\n ): void => {\n emitter.emit(getResponseKey(), data, isTriggeredExternally);\n emitter.emit(getResponseByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getResponseByCacheKey(data.request.cacheKey), data, isTriggeredExternally);\n },\n\n /** Emit when a request is aborted */\n emitAbort: (data: RequestEventType<RequestInstance>, isTriggeredExternally = false): void => {\n emitter.emit(getAbortKey(), data, isTriggeredExternally);\n emitter.emit(getAbortByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getAbortByAbortKey(data.request.abortKey), data, isTriggeredExternally);\n },\n\n /** Emit when a request is removed from the dispatcher queue */\n emitRemove: (data: RequestRemovedEventType<RequestInstance>, isTriggeredExternally = false): void => {\n emitter.emit(getRemoveKey(), data, isTriggeredExternally);\n emitter.emit(getRemoveByIdKey(data.requestId), data, isTriggeredExternally);\n emitter.emit(getRemoveByQueryKey(data.request.queryKey), data, isTriggeredExternally);\n },\n\n /**\n * Listeners\n */\n\n /** Listen for deduplicated request events */\n onDeduplicated: <T extends RequestInstance>(\n callback: (data: RequestDeduplicatedEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getRequestDeduplicatedKey(), callback);\n return () => emitter.removeListener(getRequestDeduplicatedKey(), callback);\n },\n onDeduplicatedByQueue: <T extends RequestInstance>(\n queryKey: string,\n callback: (data: RequestDeduplicatedEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getRequestDeduplicatedByQueryKey(queryKey), callback);\n return () => emitter.removeListener(getRequestDeduplicatedByQueryKey(queryKey), callback);\n },\n onDeduplicatedByCache: <T extends RequestInstance>(\n cacheKey: string,\n callback: (data: RequestDeduplicatedEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getRequestDeduplicatedByCacheKey(cacheKey), callback);\n return () => emitter.removeListener(getRequestDeduplicatedByCacheKey(cacheKey), callback);\n },\n onDeduplicatedById: <T extends RequestInstance>(\n requestId: string,\n callback: (data: RequestDeduplicatedEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getRequestDeduplicatedByIdKey(requestId), callback);\n return () => emitter.removeListener(getRequestDeduplicatedByIdKey(requestId), callback);\n },\n\n // Loading\n onLoading: <T extends RequestInstance>(callback: (data: RequestLoadingEventType<T>) => void): VoidFunction => {\n emitter.on(getLoadingKey(), callback);\n return () => emitter.removeListener(getLoadingKey(), callback);\n },\n onLoadingByQueue: <T extends RequestInstance>(\n queryKey: string,\n callback: (data: RequestLoadingEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getLoadingByQueryKey(queryKey), callback);\n return () => emitter.removeListener(getLoadingByQueryKey(queryKey), callback);\n },\n onLoadingByCache: <T extends RequestInstance>(\n cacheKey: string,\n callback: (data: RequestLoadingEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getLoadingByCacheKey(cacheKey), callback);\n return () => emitter.removeListener(getLoadingByCacheKey(cacheKey), callback);\n },\n onLoadingById: <T extends RequestInstance>(\n requestId: string,\n callback: (data: RequestLoadingEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getLoadingByIdKey(requestId), callback);\n return () => emitter.removeListener(getLoadingByIdKey(requestId), callback);\n },\n\n // Request Start\n onRequestStart: <T extends RequestInstance>(callback: (details: RequestEventType<T>) => void): VoidFunction => {\n emitter.on(getRequestStartKey(), callback);\n return () => emitter.removeListener(getRequestStartKey(), callback);\n },\n onRequestStartByQueue: <T extends RequestInstance>(\n queryKey: string,\n callback: (details: RequestEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getRequestStarByQueryKey(queryKey), callback);\n return () => emitter.removeListener(getRequestStarByQueryKey(queryKey), callback);\n },\n onRequestStartById: <T extends RequestInstance>(\n requestId: string,\n callback: (details: RequestEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getRequestStartByIdKey(requestId), callback);\n return () => emitter.removeListener(getRequestStartByIdKey(requestId), callback);\n },\n\n // Response Start\n onResponseStart: <T extends RequestInstance>(callback: (details: RequestEventType<T>) => void): VoidFunction => {\n emitter.on(getResponseStartKey(), callback);\n return () => emitter.removeListener(getResponseStartKey(), callback);\n },\n onResponseStartByQueue: <T extends RequestInstance>(\n queryKey: string,\n callback: (details: RequestEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getResponseStartByQueryKey(queryKey), callback);\n return () => emitter.removeListener(getResponseStartByQueryKey(queryKey), callback);\n },\n onResponseStartById: <T extends RequestInstance>(\n requestId: string,\n callback: (details: RequestEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getResponseStartByIdKey(requestId), callback);\n return () => emitter.removeListener(getResponseStartByIdKey(requestId), callback);\n },\n\n // Progress\n onUploadProgress: <T extends RequestInstance = RequestInstance>(\n callback: (data: RequestProgressEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getUploadProgressKey(), callback);\n return () => emitter.removeListener(getUploadProgressKey(), callback);\n },\n onUploadProgressByQueue: <T extends RequestInstance = RequestInstance>(\n queryKey: string,\n callback: (data: RequestProgressEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getUploadProgressByQueryKey(queryKey), callback);\n return () => emitter.removeListener(getUploadProgressByQueryKey(queryKey), callback);\n },\n onUploadProgressById: <T extends RequestInstance = RequestInstance>(\n requestId: string,\n callback: (data: RequestProgressEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getUploadProgressByIdKey(requestId), callback);\n return () => emitter.removeListener(getUploadProgressByIdKey(requestId), callback);\n },\n\n onDownloadProgress: <T extends RequestInstance = RequestInstance>(\n callback: (data: RequestProgressEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getDownloadProgressKey(), callback);\n return () => emitter.removeListener(getDownloadProgressKey(), callback);\n },\n onDownloadProgressByQueue: <T extends RequestInstance = RequestInstance>(\n queryKey: string,\n callback: (data: RequestProgressEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getDownloadProgressByQueryKey(queryKey), callback);\n return () => emitter.removeListener(getDownloadProgressByQueryKey(queryKey), callback);\n },\n onDownloadProgressById: <T extends RequestInstance = RequestInstance>(\n requestId: string,\n callback: (data: RequestProgressEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getDownloadProgressByIdKey(requestId), callback);\n return () => emitter.removeListener(getDownloadProgressByIdKey(requestId), callback);\n },\n\n // Response\n onResponse: <T extends RequestInstance>(callback: (data: RequestResponseEventType<T>) => void): VoidFunction => {\n emitter.on(getResponseKey(), callback);\n return () => emitter.removeListener(getResponseKey(), callback);\n },\n onResponseByCache: <T extends RequestInstance>(\n cacheKey: string,\n callback: (data: RequestResponseEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getResponseByCacheKey(cacheKey), callback);\n return () => emitter.removeListener(getResponseByCacheKey(cacheKey), callback);\n },\n onResponseById: <T extends RequestInstance>(\n requestId: string,\n callback: (data: RequestResponseEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getResponseByIdKey(requestId), callback);\n return () => emitter.removeListener(getResponseByIdKey(requestId), callback);\n },\n\n // Abort\n onAbort: <T extends RequestInstance = RequestInstance>(\n callback: (request: RequestEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getAbortKey(), callback);\n return () => emitter.removeListener(getAbortKey(), callback);\n },\n onAbortByKey: <T extends RequestInstance = RequestInstance>(\n abortKey: string,\n callback: (request: RequestEventType<T>) => void,\n ): VoidFunction => {\n emitter.on(getAbortByAbortKey(abortKey), callback);\n return () => emitter.removeListener(getAbortByAbortKey(a