From 10c9e7606742105d5982ba9aab98f5ebb0cadc47 Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 3 Jul 2024 23:50:43 +0200 Subject: [PATCH] chore: Minimum version of Node required: 18 --- .github/workflows/main.yml | 2 +- dist/browser/index.global.js.map | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e71d6d2..c648715 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node: ["16.x", "18.x", "20.x"] + node: ["18.x", "20.x", "22.x"] os: [ubuntu-latest, windows-latest, macOS-latest] steps: diff --git a/dist/browser/index.global.js.map b/dist/browser/index.global.js.map index e896ea6..19ec7c9 100644 --- a/dist/browser/index.global.js.map +++ b/dist/browser/index.global.js.map @@ -1 +1 @@ -{"version":3,"sources":["../node_modules/js-magic/index.ts","../src/request-error-handler.ts","../src/request-handler.ts","../src/api-handler.ts"],"sourcesContent":["export const __get = Symbol(\"__get\");\nexport const __set = Symbol(\"__set\");\nexport const __has = Symbol(\"__has\");\nexport const __delete = Symbol(\"__delete\");\nexport const __invoke = Symbol(\"__invoke\");\n\nexport interface MagicalClass {\n __get?(prop: string | symbol): any;\n __set?(prop: string | symbol, value: any): void;\n __has?(prop: string | symbol): boolean;\n __delete?(prop: string | symbol): void;\n /** @deprecated */\n __invoke?(...args: any[]): any;\n}\n\nlet warnedInvokeDeprecation = false;\n\nexport function applyMagic any>(ctor: T, ctx?: object): T;\nexport function applyMagic any>(fn: T, proxyOnly: boolean): T;\nexport function applyMagic(obj: T): T;\nexport function applyMagic(target: any, ctx: boolean | object = false) {\n if (typeof target === \"function\") {\n if (ctx === true) {\n return proxify(target);\n }\n\n const PseudoClass = function PseudoClass(this: any, ...args: any[]) {\n // Must use `new.target` instead of `this`, otherwise it won't work\n // in Bun (may be a bug).\n if (typeof new.target === \"undefined\") { // function call\n let invoke = target[__invoke] || target[\"__invoke\"];\n\n if (invoke) { // use static __invoke\n checkType(target, invoke, \"__invoke\");\n\n return invoke\n ? invoke.apply(target, args)\n : target(...args);\n }\n\n let proto = target.prototype;\n invoke = proto[__invoke] || proto.__invoke;\n\n if (invoke && !warnedInvokeDeprecation) {\n warnedInvokeDeprecation = true;\n console.warn(\n \"applyMagic: using __invoke without 'static' modifier is deprecated\");\n }\n\n checkType(target, invoke, \"__invoke\");\n\n return invoke ? invoke(...args) : target(...args);\n } else {\n Object.assign(this, new (target)(...args));\n return proxify(this);\n }\n };\n\n Object.setPrototypeOf(PseudoClass, target);\n Object.setPrototypeOf(PseudoClass.prototype, target.prototype);\n\n setProp(PseudoClass, \"name\", target.name);\n setProp(PseudoClass, \"length\", target.length);\n setProp(PseudoClass, \"toString\", function toString(this: any) {\n let obj = this === PseudoClass ? target : this;\n return Function.prototype.toString.call(obj);\n }, true);\n\n return PseudoClass;\n } else if (typeof target === \"object\") {\n return proxify(target);\n } else {\n throw new TypeError(\"'target' must be a function or an object\");\n }\n}\n\nfunction checkType(\n ctor: Function,\n fn: Function,\n name: string,\n argLength: number | undefined = void 0\n) {\n if (fn !== undefined) {\n if (typeof fn != \"function\") {\n throw new TypeError(\n `${ctor.name}.${name} must be a function`\n );\n } else if (argLength !== undefined && fn.length !== argLength) {\n throw new SyntaxError(\n `${ctor.name}.${name} must have ` +\n `${argLength} parameter${argLength === 1 ? \"\" : \"s\"}`\n );\n }\n }\n}\n\nfunction setProp(target: Function, prop: string, value: any, writable = false) {\n Object.defineProperty(target, prop, {\n configurable: true,\n enumerable: false,\n writable,\n value\n });\n}\n\nfunction proxify(target: any) {\n let get = target[__get] || target.__get;\n let set = target[__set] || target.__set;\n let has = target[__has] || target.__has;\n let _delete = target[__delete] || target.__delete;\n\n checkType(new.target, get, \"__get\", 1);\n checkType(new.target, set, \"__set\", 2);\n checkType(new.target, has, \"__has\", 1);\n checkType(new.target, _delete, \"__delete\", 1);\n\n return new Proxy(target, {\n get: (target, prop) => {\n return get ? get.call(target, prop) : target[prop];\n },\n set: (target, prop, value) => {\n set ? set.call(target, prop, value) : (target[prop] = value);\n return true;\n },\n has: (target, prop) => {\n return has ? has.call(target, prop) : (prop in target);\n },\n deleteProperty: (target, prop) => {\n _delete ? _delete.call(target, prop) : (delete target[prop]);\n return true;\n }\n });\n}\n","export class RequestErrorHandler {\n /**\n * Logger Class\n *\n * @type {*}\n * @memberof RequestErrorHandler\n */\n protected logger: any;\n\n /**\n * Error Service Class\n *\n * @type {*}\n * @memberof RequestErrorHandler\n */\n public requestErrorService: any;\n\n public constructor(logger: any, requestErrorService: any) {\n this.logger = logger;\n this.requestErrorService = requestErrorService;\n }\n\n /**\n * Process and Error\n *\n * @param {*} error Error instance or message\n * @throws Request error context\n * @returns {void}\n */\n public process(error: string | Error): void {\n if (this.logger?.warn) {\n this.logger.warn('API ERROR', error);\n }\n\n let errorContext = error;\n\n if (typeof error === 'string') {\n errorContext = new Error(error);\n }\n\n if (this.requestErrorService) {\n if (typeof this.requestErrorService.process !== 'undefined') {\n this.requestErrorService.process(errorContext);\n } else if (typeof this.requestErrorService === 'function') {\n this.requestErrorService(errorContext);\n }\n }\n }\n}\n","// 3rd party libs\nimport type { AxiosInstance, AxiosStatic, Method } from 'axios';\nimport { applyMagic, MagicalClass } from 'js-magic';\n\n// Shared Modules\nimport { RequestErrorHandler } from './request-error-handler';\n\n// Types\nimport type {\n IRequestData,\n IRequestResponse,\n ErrorHandlingStrategy,\n RequestHandlerConfig,\n EndpointConfig,\n RequestError,\n} from './types/http-request';\n\n/**\n * Generic Request Handler\n * It creates an Axios instance and handles requests within that instance\n * It handles errors depending on a chosen error handling strategy\n */\n@applyMagic\nexport class RequestHandler implements MagicalClass {\n /**\n * @var requestInstance Provider's instance\n */\n public requestInstance: AxiosInstance;\n\n /**\n * @var timeout Request timeout\n */\n public timeout: number = 30000;\n\n /**\n * @var cancellable Response cancellation\n */\n public cancellable: boolean = false;\n\n /**\n * @var strategy Request timeout\n */\n public strategy: ErrorHandlingStrategy = 'reject';\n\n /**\n * @var flattenResponse Response flattening\n */\n public flattenResponse: boolean = true;\n\n /**\n * @var defaultResponse Response flattening\n */\n public defaultResponse: any = null;\n\n /**\n * @var axios Axios instance\n */\n protected axios: AxiosStatic;\n\n /**\n * @var logger Logger\n */\n protected logger: any;\n\n /**\n * @var requestErrorService HTTP error service\n */\n protected requestErrorService: any;\n\n /**\n * @var requestsQueue Queue of requests\n */\n protected requestsQueue: Map;\n\n /**\n * Creates an instance of HttpRequestHandler\n *\n * @param {string} config.axios Axios instance\n * @param {string} config.baseURL Base URL for all API calls\n * @param {number} config.timeout Request timeout\n * @param {string} config.strategy Error Handling Strategy\n * @param {string} config.flattenResponse Whether to flatten response \"data\" object within \"data\" one\n * @param {*} config.logger Instance of Logger Class\n * @param {*} config.requestErrorService Instance of Error Service Class\n */\n public constructor({\n axios,\n baseURL = '',\n timeout = null,\n cancellable = false,\n strategy = null,\n flattenResponse = null,\n defaultResponse = {},\n logger = null,\n onError = null,\n ...config\n }: RequestHandlerConfig) {\n this.axios = axios;\n this.timeout = timeout !== null ? timeout : this.timeout;\n this.strategy = strategy !== null ? strategy : this.strategy;\n this.cancellable = cancellable || this.cancellable;\n this.flattenResponse =\n flattenResponse !== null ? flattenResponse : this.flattenResponse;\n this.defaultResponse = defaultResponse;\n this.logger = logger || global.console || window.console || null;\n this.requestErrorService = onError;\n this.requestsQueue = new Map();\n\n this.requestInstance = axios.create({\n ...config,\n baseURL,\n timeout: this.timeout,\n });\n }\n\n /**\n * Get Provider Instance\n *\n * @returns {AxiosInstance} Provider's instance\n */\n public getInstance(): AxiosInstance {\n return this.requestInstance;\n }\n\n /**\n * Maps all API requests\n *\n * @param {string} url Url\n * @param {*} data Payload\n * @param {EndpointConfig} config Config\n * @throws {RequestError} If request fails\n * @returns {Promise} Request response or error info\n */\n public __get(prop: string) {\n if (prop in this) {\n return this[prop];\n }\n\n return this.prepareRequest.bind(this, prop);\n }\n\n /**\n * Prepare Request\n *\n * @param {string} url Url\n * @param {*} data Payload\n * @param {EndpointConfig} config Config\n * @throws {RequestError} If request fails\n * @returns {Promise} Request response or error info\n */\n public prepareRequest(\n type: Method,\n url: string,\n data: any = null,\n config: EndpointConfig = null\n ): Promise {\n return this.handleRequest({\n type,\n url,\n data,\n config,\n });\n }\n\n /**\n * Build request configuration\n *\n * @param {string} method Request method\n * @param {string} url Request url\n * @param {*} data Request data\n * @param {EndpointConfig} config Request config\n * @returns {AxiosInstance} Provider's instance\n */\n protected buildRequestConfig(\n method: string,\n url: string,\n data: any,\n config: EndpointConfig\n ): EndpointConfig {\n const methodLowerCase = method.toLowerCase() as Method;\n const key =\n methodLowerCase === 'get' || methodLowerCase === 'head'\n ? 'params'\n : 'data';\n\n return {\n ...config,\n url,\n method: methodLowerCase,\n [key]: data || {},\n };\n }\n\n /**\n * Process global Request Error\n *\n * @param {RequestError} error Error instance\n * @param {EndpointConfig} requestConfig Per endpoint request config\n * @returns {AxiosInstance} Provider's instance\n */\n protected processRequestError(\n error: RequestError,\n requestConfig: EndpointConfig\n ): void {\n if (this.isRequestCancelled(error, requestConfig)) {\n return;\n }\n\n // Invoke per request \"onError\" call\n if (requestConfig.onError && typeof requestConfig.onError === 'function') {\n requestConfig.onError(error);\n }\n\n const errorHandler = new RequestErrorHandler(\n this.logger,\n this.requestErrorService\n );\n\n errorHandler.process(error);\n }\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {RequestError} error Error instance\n * @param {EndpointConfig} requestConfig Per endpoint request config\n * @returns {AxiosInstance} Provider's instance\n */\n protected async outputErrorResponse(\n error: RequestError,\n requestConfig: EndpointConfig\n ): Promise {\n const isRequestCancelled = this.isRequestCancelled(error, requestConfig);\n const errorHandlingStrategy = requestConfig.strategy || this.strategy;\n\n // By default cancelled requests aren't rejected\n if (isRequestCancelled && !requestConfig.rejectCancelled) {\n return this.defaultResponse;\n }\n\n if (errorHandlingStrategy === 'silent') {\n // Hang the promise\n await new Promise(() => null);\n\n return this.defaultResponse;\n }\n\n // Simply rejects a request promise\n if (\n errorHandlingStrategy === 'reject' ||\n errorHandlingStrategy === 'throwError'\n ) {\n return Promise.reject(error);\n }\n\n return this.defaultResponse;\n }\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {RequestError} error Error instance\n * @param {EndpointConfig} _requestConfig Per endpoint request config\n * @returns {*} Error response\n */\n public isRequestCancelled(\n error: RequestError,\n _requestConfig: EndpointConfig\n ): boolean {\n return this.axios.isCancel(error);\n }\n\n /**\n * Automatically Cancel Previous Requests\n *\n * @param {EndpointConfig} requestConfig Per endpoint request config\n * @returns {AxiosInstance} Provider's instance\n */\n protected addCancellationToken(requestConfig: EndpointConfig) {\n // Both disabled\n if (!this.cancellable && !requestConfig.cancellable) {\n return {};\n }\n\n // Explicitly disabled per request\n if (\n typeof requestConfig.cancellable !== 'undefined' &&\n !requestConfig.cancellable\n ) {\n return {};\n }\n\n // Check if AbortController is available\n if (typeof AbortController === 'undefined') {\n console.error('AbortController is unavailable in your ENV.');\n\n return {};\n }\n\n const { method, baseURL, url, params, data } = requestConfig;\n\n // Generate unique key as a cancellation token. Make sure it fits Map\n const key = JSON.stringify([method, baseURL, url, params, data]).substring(\n 0,\n 55 ** 5\n );\n const previousRequest = this.requestsQueue.get(key);\n\n if (previousRequest) {\n previousRequest.abort();\n }\n\n const controller = new AbortController();\n\n this.requestsQueue.set(key, controller);\n\n return {\n signal: controller.signal,\n };\n }\n\n /**\n * Handle Request depending on used strategy\n *\n * @param {object} payload Payload\n * @param {string} payload.type Request type\n * @param {string} payload.url Request url\n * @param {*} payload.data Request data\n * @param {EndpointConfig} payload.config Request config\n * @throws {RequestError}\n * @returns {Promise} Response Data\n */\n protected async handleRequest({\n type,\n url,\n data = null,\n config = null,\n }: IRequestData): Promise {\n let response = null;\n const endpointConfig = config || {};\n let requestConfig = this.buildRequestConfig(\n type,\n url,\n data,\n endpointConfig\n );\n\n requestConfig = {\n ...this.addCancellationToken(requestConfig),\n ...requestConfig,\n };\n\n try {\n response = await this.requestInstance.request(requestConfig);\n } catch (error) {\n this.processRequestError(error, requestConfig);\n\n return this.outputErrorResponse(error, requestConfig);\n }\n\n return this.processResponseData(response);\n }\n\n /**\n * Process request response\n *\n * @param response Response object\n * @returns {*} Response data\n */\n protected processResponseData(response) {\n if (response.data) {\n if (!this.flattenResponse) {\n return response;\n }\n\n // Special case of data property within Axios data object\n // This is in fact a proper response but we may want to flatten it\n // To ease developers' lives when obtaining the response\n if (\n typeof response.data === 'object' &&\n typeof response.data.data !== 'undefined' &&\n Object.keys(response.data).length === 1\n ) {\n return response.data.data;\n }\n\n return response.data;\n }\n\n return this.defaultResponse;\n }\n}\n","// 3rd party libs\nimport { applyMagic, MagicalClass } from 'js-magic';\n\n// Types\nimport type { AxiosInstance } from 'axios';\n\nimport {\n IRequestResponse,\n APIHandlerConfig,\n EndpointConfig,\n} from './types/http-request';\n\nimport { RequestHandler } from './request-handler';\n\n/**\n * Handles dispatching of API requests\n */\n@applyMagic\nexport class ApiHandler implements MagicalClass {\n /**\n * TS Index signature\n */\n [x: string]: any;\n\n /**\n * @var requestHandler Request Wrapper Instance\n */\n public requestHandler: RequestHandler;\n\n /**\n * Endpoints\n */\n protected endpoints: Record;\n\n /**\n * Logger\n */\n protected logger: any;\n\n /**\n * Creates an instance of API Handler\n *\n * @param {string} config.apiUrl Base URL for all API calls\n * @param {number} config.timeout Request timeout\n * @param {string} config.strategy Error Handling Strategy\n * @param {string} config.flattenResponse Whether to flatten response \"data\" object within \"data\" one\n * @param {*} config.logger Instance of Logger Class\n * @param {*} config.onError Instance of Error Service Class\n */\n public constructor({\n axios,\n apiUrl,\n endpoints,\n timeout = null,\n cancellable = false,\n strategy = null,\n flattenResponse = null,\n defaultResponse = {},\n logger = null,\n onError = null,\n ...config\n }: APIHandlerConfig) {\n this.endpoints = endpoints;\n this.logger = logger;\n\n this.requestHandler = new RequestHandler({\n ...config,\n baseURL: apiUrl,\n axios,\n timeout,\n cancellable,\n strategy,\n flattenResponse,\n defaultResponse,\n logger,\n onError,\n });\n }\n\n /**\n * Get Provider Instance\n *\n * @returns {AxiosInstance} Provider's instance\n */\n public getInstance(): AxiosInstance {\n return this.requestHandler.getInstance();\n }\n\n /**\n * Maps all API requests\n *\n * @param {*} prop Caller\n * @returns {Function} Tailored request function\n */\n public __get(prop: any): any {\n if (prop in this) {\n return this[prop];\n }\n\n // Prevent handler from running for non-existent endpoints\n if (!this.endpoints[prop]) {\n return this.handleNonImplemented.bind(this, prop);\n }\n\n return this.handleRequest.bind(this, prop);\n }\n\n /**\n * Handle Single API Request\n *\n * @param {*} args Arguments\n * @returns {Promise} Resolvable API provider promise\n */\n public async handleRequest(...args: any): Promise {\n const prop = args[0];\n const endpointSettings = this.endpoints[prop];\n\n const queryParams = args[1] || {};\n const uriParams = args[2] || {};\n const requestConfig = args[3] || {};\n\n const uri = endpointSettings.url.replace(/:[a-z]+/gi, (str: string) =>\n uriParams[str.substring(1)] ? uriParams[str.substring(1)] : str\n );\n\n let responseData = null;\n\n const additionalRequestSettings = { ...endpointSettings };\n\n delete additionalRequestSettings.url;\n delete additionalRequestSettings.method;\n\n responseData = await this.requestHandler[\n (endpointSettings.method || 'get').toLowerCase()\n ](uri, queryParams, {\n ...requestConfig,\n ...additionalRequestSettings,\n });\n\n return responseData;\n }\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param prop Method Name\n * @returns {Promise}\n */\n protected handleNonImplemented(prop: string): Promise {\n if (this.logger?.log) {\n this.logger.log(`${prop} endpoint not implemented.`);\n }\n\n return Promise.resolve(null);\n }\n}\n\nexport const createApiFetcher = (options: APIHandlerConfig) =>\n new ApiHandler(options);\n"],"mappings":"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","names":["__get","__set","__has","__delete","__invoke","warnedInvokeDeprecation","applyMagic","target","ctx","proxify","PseudoClass","args","invoke","checkType","proto","setProp","obj","ctor","fn","name","argLength","prop","value","writable","get","set","has","_delete","RequestErrorHandler","logger","requestErrorService","error","_a","errorContext","RequestHandler","axios","baseURL","timeout","cancellable","strategy","flattenResponse","defaultResponse","logger","onError","config","prop","type","url","data","method","methodLowerCase","error","requestConfig","RequestErrorHandler","isRequestCancelled","errorHandlingStrategy","_requestConfig","params","key","previousRequest","controller","response","endpointConfig","__decorateClass","applyMagic","ApiHandler","axios","apiUrl","endpoints","timeout","cancellable","strategy","flattenResponse","defaultResponse","logger","onError","config","RequestHandler","prop","args","endpointSettings","queryParams","uriParams","requestConfig","uri","str","responseData","additionalRequestSettings","_a","__decorateClass","applyMagic","createApiFetcher","options"]} +{"version":3,"sources":["../node_modules/js-magic/index.ts","../src/request-error-handler.ts","../src/request-handler.ts","../src/api-handler.ts"],"sourcesContent":["export const __get = Symbol(\"__get\");\nexport const __set = Symbol(\"__set\");\nexport const __has = Symbol(\"__has\");\nexport const __delete = Symbol(\"__delete\");\nexport const __invoke = Symbol(\"__invoke\");\n\nexport interface MagicalClass {\n __get?(prop: string | symbol): any;\n __set?(prop: string | symbol, value: any): void;\n __has?(prop: string | symbol): boolean;\n __delete?(prop: string | symbol): void;\n /** @deprecated */\n __invoke?(...args: any[]): any;\n}\n\nlet warnedInvokeDeprecation = false;\n\nexport function applyMagic any>(ctor: T, ctx?: object): T;\nexport function applyMagic any>(fn: T, proxyOnly: boolean): T;\nexport function applyMagic(obj: T): T;\nexport function applyMagic(target: any, ctx: boolean | object = false) {\n if (typeof target === \"function\") {\n if (ctx === true) {\n return proxify(target);\n }\n\n const PseudoClass = function PseudoClass(this: any, ...args: any[]) {\n // Must use `new.target` instead of `this`, otherwise it won't work\n // in Bun (may be a bug).\n if (typeof new.target === \"undefined\") { // function call\n let invoke = target[__invoke] || target[\"__invoke\"];\n\n if (invoke) { // use static __invoke\n checkType(target, invoke, \"__invoke\");\n\n return invoke\n ? invoke.apply(target, args)\n : target(...args);\n }\n\n let proto = target.prototype;\n invoke = proto[__invoke] || proto.__invoke;\n\n if (invoke && !warnedInvokeDeprecation) {\n warnedInvokeDeprecation = true;\n console.warn(\n \"applyMagic: using __invoke without 'static' modifier is deprecated\");\n }\n\n checkType(target, invoke, \"__invoke\");\n\n return invoke ? invoke(...args) : target(...args);\n } else {\n Object.assign(this, new (target)(...args));\n return proxify(this);\n }\n };\n\n Object.setPrototypeOf(PseudoClass, target);\n Object.setPrototypeOf(PseudoClass.prototype, target.prototype);\n\n setProp(PseudoClass, \"name\", target.name);\n setProp(PseudoClass, \"length\", target.length);\n setProp(PseudoClass, \"toString\", function toString(this: any) {\n let obj = this === PseudoClass ? target : this;\n return Function.prototype.toString.call(obj);\n }, true);\n\n return PseudoClass;\n } else if (typeof target === \"object\") {\n return proxify(target);\n } else {\n throw new TypeError(\"'target' must be a function or an object\");\n }\n}\n\nfunction checkType(\n ctor: Function,\n fn: Function,\n name: string,\n argLength: number | undefined = void 0\n) {\n if (fn !== undefined) {\n if (typeof fn != \"function\") {\n throw new TypeError(\n `${ctor.name}.${name} must be a function`\n );\n } else if (argLength !== undefined && fn.length !== argLength) {\n throw new SyntaxError(\n `${ctor.name}.${name} must have ` +\n `${argLength} parameter${argLength === 1 ? \"\" : \"s\"}`\n );\n }\n }\n}\n\nfunction setProp(target: Function, prop: string, value: any, writable = false) {\n Object.defineProperty(target, prop, {\n configurable: true,\n enumerable: false,\n writable,\n value\n });\n}\n\nfunction proxify(target: any) {\n let get = target[__get] || target.__get;\n let set = target[__set] || target.__set;\n let has = target[__has] || target.__has;\n let _delete = target[__delete] || target.__delete;\n\n checkType(new.target, get, \"__get\", 1);\n checkType(new.target, set, \"__set\", 2);\n checkType(new.target, has, \"__has\", 1);\n checkType(new.target, _delete, \"__delete\", 1);\n\n return new Proxy(target, {\n get: (target, prop) => {\n return get ? get.call(target, prop) : target[prop];\n },\n set: (target, prop, value) => {\n set ? set.call(target, prop, value) : (target[prop] = value);\n return true;\n },\n has: (target, prop) => {\n return has ? has.call(target, prop) : (prop in target);\n },\n deleteProperty: (target, prop) => {\n _delete ? _delete.call(target, prop) : (delete target[prop]);\n return true;\n }\n });\n}\n","export class RequestErrorHandler {\n /**\n * Logger Class\n *\n * @type {*}\n * @memberof RequestErrorHandler\n */\n protected logger: any;\n\n /**\n * Error Service Class\n *\n * @type {*}\n * @memberof RequestErrorHandler\n */\n public requestErrorService: any;\n\n public constructor(logger: any, requestErrorService: any) {\n this.logger = logger;\n this.requestErrorService = requestErrorService;\n }\n\n /**\n * Process and Error\n *\n * @param {*} error Error instance or message\n * @throws Request error context\n * @returns {void}\n */\n public process(error: string | Error): void {\n if (this.logger?.warn) {\n this.logger.warn('API ERROR', error);\n }\n\n let errorContext = error;\n\n if (typeof error === 'string') {\n errorContext = new Error(error);\n }\n\n if (this.requestErrorService) {\n if (typeof this.requestErrorService.process !== 'undefined') {\n this.requestErrorService.process(errorContext);\n } else if (typeof this.requestErrorService === 'function') {\n this.requestErrorService(errorContext);\n }\n }\n }\n}\n","// 3rd party libs\nimport type { AxiosInstance, AxiosStatic, Method } from 'axios';\nimport { applyMagic, MagicalClass } from 'js-magic';\n\n// Shared Modules\nimport { RequestErrorHandler } from './request-error-handler';\n\n// Types\nimport type {\n IRequestData,\n IRequestResponse,\n ErrorHandlingStrategy,\n RequestHandlerConfig,\n EndpointConfig,\n RequestError,\n} from './types/http-request';\n\n/**\n * Generic Request Handler\n * It creates an Axios instance and handles requests within that instance\n * It handles errors depending on a chosen error handling strategy\n */\n@applyMagic\nexport class RequestHandler implements MagicalClass {\n /**\n * @var requestInstance Provider's instance\n */\n public requestInstance: AxiosInstance;\n\n /**\n * @var timeout Request timeout\n */\n public timeout: number = 30000;\n\n /**\n * @var cancellable Response cancellation\n */\n public cancellable: boolean = false;\n\n /**\n * @var strategy Request timeout\n */\n public strategy: ErrorHandlingStrategy = 'reject';\n\n /**\n * @var flattenResponse Response flattening\n */\n public flattenResponse: boolean = true;\n\n /**\n * @var defaultResponse Response flattening\n */\n public defaultResponse: any = null;\n\n /**\n * @var axios Axios instance\n */\n protected axios: AxiosStatic;\n\n /**\n * @var logger Logger\n */\n protected logger: any;\n\n /**\n * @var requestErrorService HTTP error service\n */\n protected requestErrorService: any;\n\n /**\n * @var requestsQueue Queue of requests\n */\n protected requestsQueue: Map;\n\n /**\n * Creates an instance of HttpRequestHandler\n *\n * @param {string} config.axios Axios instance\n * @param {string} config.baseURL Base URL for all API calls\n * @param {number} config.timeout Request timeout\n * @param {string} config.strategy Error Handling Strategy\n * @param {string} config.flattenResponse Whether to flatten response \"data\" object within \"data\" one\n * @param {*} config.logger Instance of Logger Class\n * @param {*} config.requestErrorService Instance of Error Service Class\n */\n public constructor({\n axios,\n baseURL = '',\n timeout = null,\n cancellable = false,\n strategy = null,\n flattenResponse = null,\n defaultResponse = {},\n logger = null,\n onError = null,\n ...config\n }: RequestHandlerConfig) {\n this.axios = axios;\n this.timeout = timeout !== null ? timeout : this.timeout;\n this.strategy = strategy !== null ? strategy : this.strategy;\n this.cancellable = cancellable || this.cancellable;\n this.flattenResponse =\n flattenResponse !== null ? flattenResponse : this.flattenResponse;\n this.defaultResponse = defaultResponse;\n this.logger = logger || global.console || window.console || null;\n this.requestErrorService = onError;\n this.requestsQueue = new Map();\n\n this.requestInstance = axios.create({\n ...config,\n baseURL,\n timeout: this.timeout,\n });\n }\n\n /**\n * Get Provider Instance\n *\n * @returns {AxiosInstance} Provider's instance\n */\n public getInstance(): AxiosInstance {\n return this.requestInstance;\n }\n\n /**\n * Maps all API requests\n *\n * @param {string} url Url\n * @param {*} data Payload\n * @param {EndpointConfig} config Config\n * @throws {RequestError} If request fails\n * @returns {Promise} Request response or error info\n */\n public __get(prop: string) {\n if (prop in this) {\n return this[prop];\n }\n\n return this.prepareRequest.bind(this, prop);\n }\n\n /**\n * Prepare Request\n *\n * @param {string} url Url\n * @param {*} data Payload\n * @param {EndpointConfig} config Config\n * @throws {RequestError} If request fails\n * @returns {Promise} Request response or error info\n */\n public prepareRequest(\n type: Method,\n url: string,\n data: any = null,\n config: EndpointConfig = null\n ): Promise {\n return this.handleRequest({\n type,\n url,\n data,\n config,\n });\n }\n\n /**\n * Build request configuration\n *\n * @param {string} method Request method\n * @param {string} url Request url\n * @param {*} data Request data\n * @param {EndpointConfig} config Request config\n * @returns {AxiosInstance} Provider's instance\n */\n protected buildRequestConfig(\n method: string,\n url: string,\n data: any,\n config: EndpointConfig\n ): EndpointConfig {\n const methodLowerCase = method.toLowerCase() as Method;\n const key =\n methodLowerCase === 'get' || methodLowerCase === 'head'\n ? 'params'\n : 'data';\n\n return {\n ...config,\n url,\n method: methodLowerCase,\n [key]: data || {},\n };\n }\n\n /**\n * Process global Request Error\n *\n * @param {RequestError} error Error instance\n * @param {EndpointConfig} requestConfig Per endpoint request config\n * @returns {AxiosInstance} Provider's instance\n */\n protected processRequestError(\n error: RequestError,\n requestConfig: EndpointConfig\n ): void {\n if (this.isRequestCancelled(error, requestConfig)) {\n return;\n }\n\n // Invoke per request \"onError\" call\n if (requestConfig.onError && typeof requestConfig.onError === 'function') {\n requestConfig.onError(error);\n }\n\n const errorHandler = new RequestErrorHandler(\n this.logger,\n this.requestErrorService\n );\n\n errorHandler.process(error);\n }\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {RequestError} error Error instance\n * @param {EndpointConfig} requestConfig Per endpoint request config\n * @returns {AxiosInstance} Provider's instance\n */\n protected async outputErrorResponse(\n error: RequestError,\n requestConfig: EndpointConfig\n ): Promise {\n const isRequestCancelled = this.isRequestCancelled(error, requestConfig);\n const errorHandlingStrategy = requestConfig.strategy || this.strategy;\n\n // By default cancelled requests aren't rejected\n if (isRequestCancelled && !requestConfig.rejectCancelled) {\n return this.defaultResponse;\n }\n\n if (errorHandlingStrategy === 'silent') {\n // Hang the promise\n await new Promise(() => null);\n\n return this.defaultResponse;\n }\n\n // Simply rejects a request promise\n if (\n errorHandlingStrategy === 'reject' ||\n errorHandlingStrategy === 'throwError'\n ) {\n return Promise.reject(error);\n }\n\n return this.defaultResponse;\n }\n\n /**\n * Output error response depending on chosen strategy\n *\n * @param {RequestError} error Error instance\n * @param {EndpointConfig} _requestConfig Per endpoint request config\n * @returns {*} Error response\n */\n public isRequestCancelled(\n error: RequestError,\n _requestConfig: EndpointConfig\n ): boolean {\n return this.axios.isCancel(error);\n }\n\n /**\n * Automatically Cancel Previous Requests\n *\n * @param {EndpointConfig} requestConfig Per endpoint request config\n * @returns {AxiosInstance} Provider's instance\n */\n protected addCancellationToken(requestConfig: EndpointConfig) {\n // Both disabled\n if (!this.cancellable && !requestConfig.cancellable) {\n return {};\n }\n\n // Explicitly disabled per request\n if (\n typeof requestConfig.cancellable !== 'undefined' &&\n !requestConfig.cancellable\n ) {\n return {};\n }\n\n // Check if AbortController is available\n if (typeof AbortController === 'undefined') {\n console.error('AbortController is unavailable in your ENV.');\n\n return {};\n }\n\n const { method, baseURL, url, params, data } = requestConfig;\n\n // Generate unique key as a cancellation token. Make sure it fits Map\n const key = JSON.stringify([method, baseURL, url, params, data]).substring(\n 0,\n 55 ** 5\n );\n const previousRequest = this.requestsQueue.get(key);\n\n if (previousRequest) {\n previousRequest.abort();\n }\n\n const controller = new AbortController();\n\n this.requestsQueue.set(key, controller);\n\n return {\n signal: controller.signal,\n };\n }\n\n /**\n * Handle Request depending on used strategy\n *\n * @param {object} payload Payload\n * @param {string} payload.type Request type\n * @param {string} payload.url Request url\n * @param {*} payload.data Request data\n * @param {EndpointConfig} payload.config Request config\n * @throws {RequestError}\n * @returns {Promise} Response Data\n */\n protected async handleRequest({\n type,\n url,\n data = null,\n config = null,\n }: IRequestData): Promise {\n let response = null;\n const endpointConfig = config || {};\n let requestConfig = this.buildRequestConfig(\n type,\n url,\n data,\n endpointConfig\n );\n\n requestConfig = {\n ...this.addCancellationToken(requestConfig),\n ...requestConfig,\n };\n\n try {\n response = await this.requestInstance.request(requestConfig);\n } catch (error) {\n this.processRequestError(error, requestConfig);\n\n return this.outputErrorResponse(error, requestConfig);\n }\n\n return this.processResponseData(response);\n }\n\n /**\n * Process request response\n *\n * @param response Response object\n * @returns {*} Response data\n */\n protected processResponseData(response) {\n if (response.data) {\n if (!this.flattenResponse) {\n return response;\n }\n\n // Special case of data property within Axios data object\n // This is in fact a proper response but we may want to flatten it\n // To ease developers' lives when obtaining the response\n if (\n typeof response.data === 'object' &&\n typeof response.data.data !== 'undefined' &&\n Object.keys(response.data).length === 1\n ) {\n return response.data.data;\n }\n\n return response.data;\n }\n\n return this.defaultResponse;\n }\n}\n","// 3rd party libs\nimport { applyMagic, MagicalClass } from 'js-magic';\n\n// Types\nimport type { AxiosInstance } from 'axios';\n\nimport {\n IRequestResponse,\n APIHandlerConfig,\n EndpointConfig,\n} from './types/http-request';\n\nimport { RequestHandler } from './request-handler';\n\n/**\n * Handles dispatching of API requests\n */\n@applyMagic\nexport class ApiHandler implements MagicalClass {\n /**\n * TS Index signature\n */\n [x: string]: any;\n\n /**\n * @var requestHandler Request Wrapper Instance\n */\n public requestHandler: RequestHandler;\n\n /**\n * Endpoints\n */\n protected endpoints: Record;\n\n /**\n * Logger\n */\n protected logger: any;\n\n /**\n * Creates an instance of API Handler\n *\n * @param {string} config.apiUrl Base URL for all API calls\n * @param {number} config.timeout Request timeout\n * @param {string} config.strategy Error Handling Strategy\n * @param {string} config.flattenResponse Whether to flatten response \"data\" object within \"data\" one\n * @param {*} config.logger Instance of Logger Class\n * @param {*} config.onError Instance of Error Service Class\n */\n public constructor({\n axios,\n apiUrl,\n endpoints,\n timeout = null,\n cancellable = false,\n strategy = null,\n flattenResponse = null,\n defaultResponse = {},\n logger = null,\n onError = null,\n ...config\n }: APIHandlerConfig) {\n this.endpoints = endpoints;\n this.logger = logger;\n\n this.requestHandler = new RequestHandler({\n ...config,\n baseURL: apiUrl,\n axios,\n timeout,\n cancellable,\n strategy,\n flattenResponse,\n defaultResponse,\n logger,\n onError,\n });\n }\n\n /**\n * Get Provider Instance\n *\n * @returns {AxiosInstance} Provider's instance\n */\n public getInstance(): AxiosInstance {\n return this.requestHandler.getInstance();\n }\n\n /**\n * Maps all API requests\n *\n * @param {*} prop Caller\n * @returns {Function} Tailored request function\n */\n public __get(prop: any): any {\n if (prop in this) {\n return this[prop];\n }\n\n // Prevent handler from running for non-existent endpoints\n if (!this.endpoints[prop]) {\n return this.handleNonImplemented.bind(this, prop);\n }\n\n return this.handleRequest.bind(this, prop);\n }\n\n /**\n * Handle Single API Request\n *\n * @param {*} args Arguments\n * @returns {Promise} Resolvable API provider promise\n */\n public async handleRequest(...args: any): Promise {\n const prop = args[0];\n const endpointSettings = this.endpoints[prop];\n\n const queryParams = args[1] || {};\n const uriParams = args[2] || {};\n const requestConfig = args[3] || {};\n\n const uri = endpointSettings.url.replace(/:[a-z]+/gi, (str: string) =>\n uriParams[str.substring(1)] ? uriParams[str.substring(1)] : str\n );\n\n let responseData = null;\n\n const additionalRequestSettings = { ...endpointSettings };\n\n delete additionalRequestSettings.url;\n delete additionalRequestSettings.method;\n\n responseData = await this.requestHandler[\n (endpointSettings.method || 'get').toLowerCase()\n ](uri, queryParams, {\n ...requestConfig,\n ...additionalRequestSettings,\n });\n\n return responseData;\n }\n\n /**\n * Triggered when trying to use non-existent endpoints\n *\n * @param prop Method Name\n * @returns {Promise}\n */\n protected handleNonImplemented(prop: string): Promise {\n if (this.logger?.log) {\n this.logger.log(`${prop} endpoint not implemented.`);\n }\n\n return Promise.resolve(null);\n }\n}\n\nexport const createApiFetcher = (options: APIHandlerConfig) =>\n new ApiHandler(options);\n"],"mappings":"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","names":["__get","__set","__has","__delete","__invoke","warnedInvokeDeprecation","applyMagic","target","ctx","proxify","PseudoClass","args","invoke","checkType","proto","setProp","obj","ctor","fn","name","argLength","prop","value","writable","get","set","has","_delete","RequestErrorHandler","logger","requestErrorService","error","_a","errorContext","RequestHandler","axios","baseURL","timeout","cancellable","strategy","flattenResponse","defaultResponse","logger","onError","config","prop","type","url","data","method","methodLowerCase","error","requestConfig","RequestErrorHandler","isRequestCancelled","errorHandlingStrategy","_requestConfig","params","key","previousRequest","controller","response","endpointConfig","__decorateClass","applyMagic","ApiHandler","axios","apiUrl","endpoints","timeout","cancellable","strategy","flattenResponse","defaultResponse","logger","onError","config","RequestHandler","prop","args","endpointSettings","queryParams","uriParams","requestConfig","uri","str","responseData","additionalRequestSettings","_a","__decorateClass","applyMagic","createApiFetcher","options"]} \ No newline at end of file diff --git a/package.json b/package.json index fcc6f24..aca2a98 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "node" ], "engines": { - "node": ">=16" + "node": ">=18" }, "scripts": { "start": "tsup src/index.ts --watch",