diff --git a/dist/browser/index.global.js b/dist/browser/index.global.js index 0b5b522..69c4b7b 100644 --- a/dist/browser/index.global.js +++ b/dist/browser/index.global.js @@ -1,2 +1,2 @@ -(()=>{var E=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var h=(r,e,t,s)=>{for(var o=s>1?void 0:s?C(e,t):e,n=r.length-1,i;n>=0;n--)(i=r[n])&&(o=(s?i(e,t,o):i(o))||o);return s&&o&&E(e,t,o),o};var w=Symbol("__get"),x=Symbol("__set"),I=Symbol("__has"),S=Symbol("__delete"),R=Symbol("__invoke"),_=!1;function y(r,e=!1){if(typeof r=="function"){if(e===!0)return g(r);let t=function(...o){if(typeof new.target>"u"){let n=r[R]||r.__invoke;if(n)return p(r,n,"__invoke"),n?n.apply(r,o):r(...o);let i=r.prototype;return n=i[R]||i.__invoke,n&&!_&&(_=!0,console.warn("applyMagic: using __invoke without 'static' modifier is deprecated")),p(r,n,"__invoke"),n?n(...o):r(...o)}else return Object.assign(this,new r(...o)),g(this)};return Object.setPrototypeOf(t,r),Object.setPrototypeOf(t.prototype,r.prototype),b(t,"name",r.name),b(t,"length",r.length),b(t,"toString",function(){let o=this===t?r:this;return Function.prototype.toString.call(o)},!0),t}else{if(typeof r=="object")return g(r);throw new TypeError("'target' must be a function or an object")}}function p(r,e,t,s=void 0){if(e!==void 0){if(typeof e!="function")throw new TypeError(`${r.name}.${t} must be a function`);if(s!==void 0&&e.length!==s)throw new SyntaxError(`${r.name}.${t} must have ${s} parameter${s===1?"":"s"}`)}}function b(r,e,t,s=!1){Object.defineProperty(r,e,{configurable:!0,enumerable:!1,writable:s,value:t})}function g(r){let e=r[w]||r.__get,t=r[x]||r.__set,s=r[I]||r.__has,o=r[S]||r.__delete;return p(new.target,e,"__get",1),p(new.target,t,"__set",2),p(new.target,s,"__has",1),p(new.target,o,"__delete",1),new Proxy(r,{get:(n,i)=>e?e.call(n,i):n[i],set:(n,i,l)=>(t?t.call(n,i,l):n[i]=l,!0),has:(n,i)=>s?s.call(n,i):i in n,deleteProperty:(n,i)=>(o?o.call(n,i):delete n[i],!0)})}var m=class{logger;requestErrorService;constructor(e,t){this.logger=e,this.requestErrorService=t}process(e){var s;(s=this.logger)!=null&&s.warn&&this.logger.warn("API ERROR",e);let t=e;typeof e=="string"&&(t=new Error(e)),this.requestErrorService&&(typeof this.requestErrorService.process<"u"?this.requestErrorService.process(t):typeof this.requestErrorService=="function"&&this.requestErrorService(t))}};var d=class{requestInstance;timeout=3e4;cancellable=!1;strategy="reject";flattenResponse=!0;defaultResponse=null;axios;logger;requestErrorService;requestsQueue;constructor({axios:e,baseURL:t="",timeout:s=null,cancellable:o=!1,strategy:n=null,flattenResponse:i=null,defaultResponse:l={},logger:u=null,onError:a=null,...c}){this.axios=e,this.timeout=s!==null?s:this.timeout,this.strategy=n!==null?n:this.strategy,this.cancellable=o||this.cancellable,this.flattenResponse=i!==null?i:this.flattenResponse,this.defaultResponse=l,this.logger=u||global.console||window.console||null,this.requestErrorService=a,this.requestsQueue=new Map,this.requestInstance=e.create({...c,baseURL:t,timeout:this.timeout})}getInstance(){return this.requestInstance}__get(e){return e in this?this[e]:this.prepareRequest.bind(this,e)}prepareRequest(e,t,s=null,o=null){return this.handleRequest({type:e,url:t,data:s,config:o})}buildRequestConfig(e,t,s,o){let n=e.toLowerCase();return{...o,url:t,method:n,[n==="get"||n==="head"?"params":"data"]:s||{}}}processRequestError(e,t){if(this.isRequestCancelled(e,t))return;t.onError&&typeof t.onError=="function"&&t.onError(e),new m(this.logger,this.requestErrorService).process(e)}async outputErrorResponse(e,t){let s=this.isRequestCancelled(e,t),o=t.strategy||this.strategy;return s&&!t.rejectCancelled?this.defaultResponse:o==="silent"?(await new Promise(()=>null),this.defaultResponse):o==="reject"||o==="throwError"?Promise.reject(e):this.defaultResponse}isRequestCancelled(e,t){return this.axios.isCancel(e)}addCancellationToken(e){if(!this.cancellable&&!e.cancellable)return{};if(typeof e.cancellable<"u"&&!e.cancellable)return{};if(typeof AbortController>"u")return console.error("AbortController is unavailable in your ENV."),{};let{method:t,baseURL:s,url:o,params:n,data:i}=e,l=JSON.stringify([t,s,o,n,i]).substring(0,55**5),u=this.requestsQueue.get(l);u&&u.abort();let a=new AbortController;return this.requestsQueue.set(l,a),{signal:a.signal}}async handleRequest({type:e,url:t,data:s=null,config:o=null}){let n=null,i=o||{},l=this.buildRequestConfig(e,t,s,i);l={...this.addCancellationToken(l),...l};try{n=await this.requestInstance.request(l)}catch(u){return this.processRequestError(u,l),this.outputErrorResponse(u,l)}return this.processResponseData(n)}processResponseData(e){return e.data?this.flattenResponse?typeof e.data=="object"&&typeof e.data.data<"u"&&Object.keys(e.data).length===1?e.data.data:e.data:e:this.defaultResponse}};d=h([y],d);var f=class{requestHandler;endpoints;logger;constructor({axios:e,apiUrl:t,endpoints:s,timeout:o=null,cancellable:n=!1,strategy:i=null,flattenResponse:l=null,defaultResponse:u={},logger:a=null,onError:c=null,...q}){this.endpoints=s,this.logger=a,this.requestHandler=new d({...q,baseURL:t,axios:e,timeout:o,cancellable:n,strategy:i,flattenResponse:l,defaultResponse:u,logger:a,onError:c})}getInstance(){return this.requestHandler.getInstance()}__get(e){return e in this?this[e]:this.endpoints[e]?this.handleRequest.bind(this,e):this.handleNonImplemented.bind(this,e)}async handleRequest(...e){let t=e[0],s=this.endpoints[t],o=e[1]||{},n=e[2]||{},i=e[3]||{},l=s.url.replace(/:[a-z]+/gi,c=>n[c.substring(1)]?n[c.substring(1)]:c),u=null,a={...s};return delete a.url,delete a.method,u=await this.requestHandler[(s.method||"get").toLowerCase()](l,o,{...i,...a}),u}handleNonImplemented(e){var t;return(t=this.logger)!=null&&t.log&&this.logger.log(`${e} endpoint not implemented.`),Promise.resolve(null)}};f=h([y],f);var F=r=>new f(r);})(); +(()=>{var E=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var h=(r,e,t,s)=>{for(var o=s>1?void 0:s?w(e,t):e,n=r.length-1,i;n>=0;n--)(i=r[n])&&(o=(s?i(e,t,o):i(o))||o);return s&&o&&E(e,t,o),o};var C=Symbol("__get"),x=Symbol("__set"),S=Symbol("__has"),v=Symbol("__delete"),R=Symbol("__invoke"),_=!1;function y(r,e=!1){if(typeof r=="function"){if(e===!0)return g(r);let t=function(...o){if(typeof new.target>"u"){let n=r[R]||r.__invoke;if(n)return p(r,n,"__invoke"),n?n.apply(r,o):r(...o);let i=r.prototype;return n=i[R]||i.__invoke,n&&!_&&(_=!0,console.warn("applyMagic: using __invoke without 'static' modifier is deprecated")),p(r,n,"__invoke"),n?n(...o):r(...o)}else return Object.assign(this,new r(...o)),g(this)};return Object.setPrototypeOf(t,r),Object.setPrototypeOf(t.prototype,r.prototype),b(t,"name",r.name),b(t,"length",r.length),b(t,"toString",function(){let o=this===t?r:this;return Function.prototype.toString.call(o)},!0),t}else{if(typeof r=="object")return g(r);throw new TypeError("'target' must be a function or an object")}}function p(r,e,t,s=void 0){if(e!==void 0){if(typeof e!="function")throw new TypeError(`${r.name}.${t} must be a function`);if(s!==void 0&&e.length!==s)throw new SyntaxError(`${r.name}.${t} must have ${s} parameter${s===1?"":"s"}`)}}function b(r,e,t,s=!1){Object.defineProperty(r,e,{configurable:!0,enumerable:!1,writable:s,value:t})}function g(r){let e=r[C]||r.__get,t=r[x]||r.__set,s=r[S]||r.__has,o=r[v]||r.__delete;return p(new.target,e,"__get",1),p(new.target,t,"__set",2),p(new.target,s,"__has",1),p(new.target,o,"__delete",1),new Proxy(r,{get:(n,i)=>e?e.call(n,i):n[i],set:(n,i,l)=>(t?t.call(n,i,l):n[i]=l,!0),has:(n,i)=>s?s.call(n,i):i in n,deleteProperty:(n,i)=>(o?o.call(n,i):delete n[i],!0)})}var m=class{logger;requestErrorService;constructor(e,t){this.logger=e,this.requestErrorService=t}process(e){var s;(s=this.logger)!=null&&s.warn&&this.logger.warn("API ERROR",e);let t=e;typeof e=="string"&&(t=new Error(e)),this.requestErrorService&&(typeof this.requestErrorService.process<"u"?this.requestErrorService.process(t):typeof this.requestErrorService=="function"&&this.requestErrorService(t))}};var d=class{requestInstance;timeout=3e4;cancellable=!1;strategy="reject";flattenResponse=!0;defaultResponse=null;axios;logger;requestErrorService;requestsQueue;constructor({axios:e,baseURL:t="",timeout:s=null,cancellable:o=!1,strategy:n=null,flattenResponse:i=null,defaultResponse:l={},logger:u=null,onError:a=null,...c}){this.axios=e,this.timeout=s!==null?s:this.timeout,this.strategy=n!==null?n:this.strategy,this.cancellable=o||this.cancellable,this.flattenResponse=i!==null?i:this.flattenResponse,this.defaultResponse=l,this.logger=u||global.console||window.console||null,this.requestErrorService=a,this.requestsQueue=new Map,this.requestInstance=e.create({...c,baseURL:t,timeout:this.timeout})}getInstance(){return this.requestInstance}__get(e){return e in this?this[e]:this.prepareRequest.bind(this,e)}prepareRequest(e,t,s=null,o=null){return this.handleRequest({type:e,url:t,data:s,config:o})}buildRequestConfig(e,t,s,o){let n=e.toLowerCase();return{...o,url:t,method:n,[n==="get"||n==="head"?"params":"data"]:s||{}}}processRequestError(e,t){if(this.isRequestCancelled(e,t))return;t.onError&&typeof t.onError=="function"&&t.onError(e),new m(this.logger,this.requestErrorService).process(e)}async outputErrorResponse(e,t){let s=this.isRequestCancelled(e,t),o=t.strategy||this.strategy;return s&&!t.rejectCancelled?this.defaultResponse:o==="silent"?(await new Promise(()=>null),this.defaultResponse):o==="reject"||o==="throwError"?Promise.reject(e):this.defaultResponse}isRequestCancelled(e,t){return this.axios.isCancel(e)}addCancellationToken(e){if(!this.cancellable&&!e.cancellable)return{};if(typeof e.cancellable<"u"&&!e.cancellable)return{};if(typeof AbortController>"u")return console.error("AbortController is unavailable in your ENV."),{};let{method:t,baseURL:s,url:o,params:n,data:i}=e,l=JSON.stringify([t,s,o,n,i]).substring(0,55**5),u=this.requestsQueue.get(l);u&&u.abort();let a=new AbortController;return this.requestsQueue.set(l,a),{signal:a.signal}}async handleRequest({type:e,url:t,data:s=null,config:o=null}){let n=null,i=o||{},l=this.buildRequestConfig(e,t,s,i);l={...this.addCancellationToken(l),...l};try{n=await this.requestInstance.request(l)}catch(u){return this.processRequestError(u,l),this.outputErrorResponse(u,l)}return this.processResponseData(n)}processResponseData(e){return e.data?this.flattenResponse?typeof e.data=="object"&&typeof e.data.data<"u"&&Object.keys(e.data).length===1?e.data.data:e.data:e:this.defaultResponse}};d=h([y],d);var f=class{requestHandler;endpoints;logger;constructor({axios:e,apiUrl:t,endpoints:s,timeout:o=null,cancellable:n=!1,strategy:i=null,flattenResponse:l=null,defaultResponse:u={},logger:a=null,onError:c=null,...q}){this.endpoints=s,this.logger=a,this.requestHandler=new d({...q,baseURL:t,axios:e,timeout:o,cancellable:n,strategy:i,flattenResponse:l,defaultResponse:u,logger:a,onError:c})}getInstance(){return this.requestHandler.getInstance()}__get(e){return e in this?this[e]:this.endpoints[e]?this.handleRequest.bind(this,e):this.handleNonImplemented.bind(this,e)}async handleRequest(...e){let t=e[0],s=this.endpoints[t],o=e[1]||{},n=e[2]||{},i=e[3]||{},l=s.url.replace(/:[a-z]+/gi,c=>n[c.substring(1)]?n[c.substring(1)]:c),u=null,a={...s};return delete a.url,delete a.method,u=await this.requestHandler[(s.method||"get").toLowerCase()](l,o,{...i,...a}),u}handleNonImplemented(e){var t;return(t=this.logger)!=null&&t.log&&this.logger.log(`${e} endpoint not implemented.`),Promise.resolve(null)}};f=h([y],f);var Q=r=>new f(r);})(); //# sourceMappingURL=index.global.js.map \ No newline at end of file diff --git a/dist/browser/index.global.js.map b/dist/browser/index.global.js.map index 19ec7c9..30245a8 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"]} \ No newline at end of file +{"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 RequestData,\n RequestResponse,\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 * @private\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 }: RequestData): 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","/* eslint-disable @typescript-eslint/no-explicit-any */\n// 3rd party libs\nimport { applyMagic, MagicalClass } from 'js-magic';\n\n// Types\nimport type { AxiosInstance } from 'axios';\n\nimport {\n RequestResponse,\n APIHandlerConfig,\n EndpointsConfig,\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]: unknown;\n\n /**\n * @var requestHandler Request Wrapper Instance\n */\n public requestHandler: RequestHandler;\n\n /**\n * Endpoints\n */\n protected endpoints: EndpointsConfig;\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 * @private\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: string[]): 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 = (\n options: APIHandlerConfig,\n) => new ApiHandler(options) as ApiHandler & AllEndpointsList;\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/dist/browser/index.mjs b/dist/browser/index.mjs index 41f527b..8340a8e 100644 --- a/dist/browser/index.mjs +++ b/dist/browser/index.mjs @@ -1,2 +1,2 @@ -var m=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var h=(u,e,t,r)=>{for(var n=r>1?void 0:r?R(e,t):e,s=u.length-1,o;s>=0;s--)(o=u[s])&&(n=(r?o(e,t,n):o(n))||n);return r&&n&&m(e,t,n),n};import{applyMagic as q}from"js-magic";import{applyMagic as b}from"js-magic";var g=class{logger;requestErrorService;constructor(e,t){this.logger=e,this.requestErrorService=t}process(e){var r;(r=this.logger)!=null&&r.warn&&this.logger.warn("API ERROR",e);let t=e;typeof e=="string"&&(t=new Error(e)),this.requestErrorService&&(typeof this.requestErrorService.process<"u"?this.requestErrorService.process(t):typeof this.requestErrorService=="function"&&this.requestErrorService(t))}};var p=class{requestInstance;timeout=3e4;cancellable=!1;strategy="reject";flattenResponse=!0;defaultResponse=null;axios;logger;requestErrorService;requestsQueue;constructor({axios:e,baseURL:t="",timeout:r=null,cancellable:n=!1,strategy:s=null,flattenResponse:o=null,defaultResponse:i={},logger:l=null,onError:a=null,...c}){this.axios=e,this.timeout=r!==null?r:this.timeout,this.strategy=s!==null?s:this.strategy,this.cancellable=n||this.cancellable,this.flattenResponse=o!==null?o:this.flattenResponse,this.defaultResponse=i,this.logger=l||global.console||window.console||null,this.requestErrorService=a,this.requestsQueue=new Map,this.requestInstance=e.create({...c,baseURL:t,timeout:this.timeout})}getInstance(){return this.requestInstance}__get(e){return e in this?this[e]:this.prepareRequest.bind(this,e)}prepareRequest(e,t,r=null,n=null){return this.handleRequest({type:e,url:t,data:r,config:n})}buildRequestConfig(e,t,r,n){let s=e.toLowerCase();return{...n,url:t,method:s,[s==="get"||s==="head"?"params":"data"]:r||{}}}processRequestError(e,t){if(this.isRequestCancelled(e,t))return;t.onError&&typeof t.onError=="function"&&t.onError(e),new g(this.logger,this.requestErrorService).process(e)}async outputErrorResponse(e,t){let r=this.isRequestCancelled(e,t),n=t.strategy||this.strategy;return r&&!t.rejectCancelled?this.defaultResponse:n==="silent"?(await new Promise(()=>null),this.defaultResponse):n==="reject"||n==="throwError"?Promise.reject(e):this.defaultResponse}isRequestCancelled(e,t){return this.axios.isCancel(e)}addCancellationToken(e){if(!this.cancellable&&!e.cancellable)return{};if(typeof e.cancellable<"u"&&!e.cancellable)return{};if(typeof AbortController>"u")return console.error("AbortController is unavailable in your ENV."),{};let{method:t,baseURL:r,url:n,params:s,data:o}=e,i=JSON.stringify([t,r,n,s,o]).substring(0,55**5),l=this.requestsQueue.get(i);l&&l.abort();let a=new AbortController;return this.requestsQueue.set(i,a),{signal:a.signal}}async handleRequest({type:e,url:t,data:r=null,config:n=null}){let s=null,o=n||{},i=this.buildRequestConfig(e,t,r,o);i={...this.addCancellationToken(i),...i};try{s=await this.requestInstance.request(i)}catch(l){return this.processRequestError(l,i),this.outputErrorResponse(l,i)}return this.processResponseData(s)}processResponseData(e){return e.data?this.flattenResponse?typeof e.data=="object"&&typeof e.data.data<"u"&&Object.keys(e.data).length===1?e.data.data:e.data:e:this.defaultResponse}};p=h([b],p);var d=class{requestHandler;endpoints;logger;constructor({axios:e,apiUrl:t,endpoints:r,timeout:n=null,cancellable:s=!1,strategy:o=null,flattenResponse:i=null,defaultResponse:l={},logger:a=null,onError:c=null,...f}){this.endpoints=r,this.logger=a,this.requestHandler=new p({...f,baseURL:t,axios:e,timeout:n,cancellable:s,strategy:o,flattenResponse:i,defaultResponse:l,logger:a,onError:c})}getInstance(){return this.requestHandler.getInstance()}__get(e){return e in this?this[e]:this.endpoints[e]?this.handleRequest.bind(this,e):this.handleNonImplemented.bind(this,e)}async handleRequest(...e){let t=e[0],r=this.endpoints[t],n=e[1]||{},s=e[2]||{},o=e[3]||{},i=r.url.replace(/:[a-z]+/gi,c=>s[c.substring(1)]?s[c.substring(1)]:c),l=null,a={...r};return delete a.url,delete a.method,l=await this.requestHandler[(r.method||"get").toLowerCase()](i,n,{...o,...a}),l}handleNonImplemented(e){var t;return(t=this.logger)!=null&&t.log&&this.logger.log(`${e} endpoint not implemented.`),Promise.resolve(null)}};d=h([q],d);var j=u=>new d(u);export{d as ApiHandler,g as RequestErrorHandler,p as RequestHandler,j as createApiFetcher}; +var m=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var h=(u,e,t,r)=>{for(var n=r>1?void 0:r?R(e,t):e,s=u.length-1,o;s>=0;s--)(o=u[s])&&(n=(r?o(e,t,n):o(n))||n);return r&&n&&m(e,t,n),n};import{applyMagic as q}from"js-magic";import{applyMagic as b}from"js-magic";var g=class{logger;requestErrorService;constructor(e,t){this.logger=e,this.requestErrorService=t}process(e){var r;(r=this.logger)!=null&&r.warn&&this.logger.warn("API ERROR",e);let t=e;typeof e=="string"&&(t=new Error(e)),this.requestErrorService&&(typeof this.requestErrorService.process<"u"?this.requestErrorService.process(t):typeof this.requestErrorService=="function"&&this.requestErrorService(t))}};var p=class{requestInstance;timeout=3e4;cancellable=!1;strategy="reject";flattenResponse=!0;defaultResponse=null;axios;logger;requestErrorService;requestsQueue;constructor({axios:e,baseURL:t="",timeout:r=null,cancellable:n=!1,strategy:s=null,flattenResponse:o=null,defaultResponse:i={},logger:l=null,onError:a=null,...c}){this.axios=e,this.timeout=r!==null?r:this.timeout,this.strategy=s!==null?s:this.strategy,this.cancellable=n||this.cancellable,this.flattenResponse=o!==null?o:this.flattenResponse,this.defaultResponse=i,this.logger=l||global.console||window.console||null,this.requestErrorService=a,this.requestsQueue=new Map,this.requestInstance=e.create({...c,baseURL:t,timeout:this.timeout})}getInstance(){return this.requestInstance}__get(e){return e in this?this[e]:this.prepareRequest.bind(this,e)}prepareRequest(e,t,r=null,n=null){return this.handleRequest({type:e,url:t,data:r,config:n})}buildRequestConfig(e,t,r,n){let s=e.toLowerCase();return{...n,url:t,method:s,[s==="get"||s==="head"?"params":"data"]:r||{}}}processRequestError(e,t){if(this.isRequestCancelled(e,t))return;t.onError&&typeof t.onError=="function"&&t.onError(e),new g(this.logger,this.requestErrorService).process(e)}async outputErrorResponse(e,t){let r=this.isRequestCancelled(e,t),n=t.strategy||this.strategy;return r&&!t.rejectCancelled?this.defaultResponse:n==="silent"?(await new Promise(()=>null),this.defaultResponse):n==="reject"||n==="throwError"?Promise.reject(e):this.defaultResponse}isRequestCancelled(e,t){return this.axios.isCancel(e)}addCancellationToken(e){if(!this.cancellable&&!e.cancellable)return{};if(typeof e.cancellable<"u"&&!e.cancellable)return{};if(typeof AbortController>"u")return console.error("AbortController is unavailable in your ENV."),{};let{method:t,baseURL:r,url:n,params:s,data:o}=e,i=JSON.stringify([t,r,n,s,o]).substring(0,55**5),l=this.requestsQueue.get(i);l&&l.abort();let a=new AbortController;return this.requestsQueue.set(i,a),{signal:a.signal}}async handleRequest({type:e,url:t,data:r=null,config:n=null}){let s=null,o=n||{},i=this.buildRequestConfig(e,t,r,o);i={...this.addCancellationToken(i),...i};try{s=await this.requestInstance.request(i)}catch(l){return this.processRequestError(l,i),this.outputErrorResponse(l,i)}return this.processResponseData(s)}processResponseData(e){return e.data?this.flattenResponse?typeof e.data=="object"&&typeof e.data.data<"u"&&Object.keys(e.data).length===1?e.data.data:e.data:e:this.defaultResponse}};p=h([b],p);var d=class{requestHandler;endpoints;logger;constructor({axios:e,apiUrl:t,endpoints:r,timeout:n=null,cancellable:s=!1,strategy:o=null,flattenResponse:i=null,defaultResponse:l={},logger:a=null,onError:c=null,...f}){this.endpoints=r,this.logger=a,this.requestHandler=new p({...f,baseURL:t,axios:e,timeout:n,cancellable:s,strategy:o,flattenResponse:i,defaultResponse:l,logger:a,onError:c})}getInstance(){return this.requestHandler.getInstance()}__get(e){return e in this?this[e]:this.endpoints[e]?this.handleRequest.bind(this,e):this.handleNonImplemented.bind(this,e)}async handleRequest(...e){let t=e[0],r=this.endpoints[t],n=e[1]||{},s=e[2]||{},o=e[3]||{},i=r.url.replace(/:[a-z]+/gi,c=>s[c.substring(1)]?s[c.substring(1)]:c),l=null,a={...r};return delete a.url,delete a.method,l=await this.requestHandler[(r.method||"get").toLowerCase()](i,n,{...o,...a}),l}handleNonImplemented(e){var t;return(t=this.logger)!=null&&t.log&&this.logger.log(`${e} endpoint not implemented.`),Promise.resolve(null)}};d=h([q],d);var k=u=>new d(u);export{d as ApiHandler,g as RequestErrorHandler,p as RequestHandler,k as createApiFetcher}; //# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/dist/browser/index.mjs.map b/dist/browser/index.mjs.map index 5f96efc..c330123 100644 --- a/dist/browser/index.mjs.map +++ b/dist/browser/index.mjs.map @@ -1 +1 @@ -{"version":3,"sources":["../src/api-handler.ts","../src/request-handler.ts","../src/request-error-handler.ts"],"sourcesContent":["// 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","// 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","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"],"mappings":"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","names":["applyMagic","applyMagic","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 +{"version":3,"sources":["../src/api-handler.ts","../src/request-handler.ts","../src/request-error-handler.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n// 3rd party libs\nimport { applyMagic, MagicalClass } from 'js-magic';\n\n// Types\nimport type { AxiosInstance } from 'axios';\n\nimport {\n RequestResponse,\n APIHandlerConfig,\n EndpointsConfig,\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]: unknown;\n\n /**\n * @var requestHandler Request Wrapper Instance\n */\n public requestHandler: RequestHandler;\n\n /**\n * Endpoints\n */\n protected endpoints: EndpointsConfig;\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 * @private\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: string[]): 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 = (\n options: APIHandlerConfig,\n) => new ApiHandler(options) as ApiHandler & AllEndpointsList;\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 RequestData,\n RequestResponse,\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 * @private\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 }: RequestData): 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","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"],"mappings":"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","names":["applyMagic","applyMagic","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/dist/node/index.js b/dist/node/index.js index bd76032..3ea4a0c 100644 --- a/dist/node/index.js +++ b/dist/node/index.js @@ -1,2 +1,2 @@ -var g=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var E=Object.prototype.hasOwnProperty;var C=(o,e)=>{for(var t in e)g(o,t,{get:e[t],enumerable:!0})},I=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of y(e))!E.call(o,r)&&r!==t&&g(o,r,{get:()=>e[r],enumerable:!(n=m(e,r))||n.enumerable});return o};var x=o=>I(g({},"__esModule",{value:!0}),o),f=(o,e,t,n)=>{for(var r=n>1?void 0:n?m(e,t):e,s=o.length-1,i;s>=0;s--)(i=o[s])&&(r=(n?i(e,t,r):i(r))||r);return n&&r&&g(e,t,r),r};var S={};C(S,{ApiHandler:()=>d,RequestErrorHandler:()=>h,RequestHandler:()=>p,createApiFetcher:()=>w});module.exports=x(S);var b=require("js-magic");var R=require("js-magic");var h=class{logger;requestErrorService;constructor(e,t){this.logger=e,this.requestErrorService=t}process(e){var n;(n=this.logger)!=null&&n.warn&&this.logger.warn("API ERROR",e);let t=e;typeof e=="string"&&(t=new Error(e)),this.requestErrorService&&(typeof this.requestErrorService.process<"u"?this.requestErrorService.process(t):typeof this.requestErrorService=="function"&&this.requestErrorService(t))}};var p=class{requestInstance;timeout=3e4;cancellable=!1;strategy="reject";flattenResponse=!0;defaultResponse=null;axios;logger;requestErrorService;requestsQueue;constructor({axios:e,baseURL:t="",timeout:n=null,cancellable:r=!1,strategy:s=null,flattenResponse:i=null,defaultResponse:l={},logger:a=null,onError:u=null,...c}){this.axios=e,this.timeout=n!==null?n:this.timeout,this.strategy=s!==null?s:this.strategy,this.cancellable=r||this.cancellable,this.flattenResponse=i!==null?i:this.flattenResponse,this.defaultResponse=l,this.logger=a||global.console||window.console||null,this.requestErrorService=u,this.requestsQueue=new Map,this.requestInstance=e.create({...c,baseURL:t,timeout:this.timeout})}getInstance(){return this.requestInstance}__get(e){return e in this?this[e]:this.prepareRequest.bind(this,e)}prepareRequest(e,t,n=null,r=null){return this.handleRequest({type:e,url:t,data:n,config:r})}buildRequestConfig(e,t,n,r){let s=e.toLowerCase();return{...r,url:t,method:s,[s==="get"||s==="head"?"params":"data"]:n||{}}}processRequestError(e,t){if(this.isRequestCancelled(e,t))return;t.onError&&typeof t.onError=="function"&&t.onError(e),new h(this.logger,this.requestErrorService).process(e)}async outputErrorResponse(e,t){let n=this.isRequestCancelled(e,t),r=t.strategy||this.strategy;return n&&!t.rejectCancelled?this.defaultResponse:r==="silent"?(await new Promise(()=>null),this.defaultResponse):r==="reject"||r==="throwError"?Promise.reject(e):this.defaultResponse}isRequestCancelled(e,t){return this.axios.isCancel(e)}addCancellationToken(e){if(!this.cancellable&&!e.cancellable)return{};if(typeof e.cancellable<"u"&&!e.cancellable)return{};if(typeof AbortController>"u")return console.error("AbortController is unavailable in your ENV."),{};let{method:t,baseURL:n,url:r,params:s,data:i}=e,l=JSON.stringify([t,n,r,s,i]).substring(0,55**5),a=this.requestsQueue.get(l);a&&a.abort();let u=new AbortController;return this.requestsQueue.set(l,u),{signal:u.signal}}async handleRequest({type:e,url:t,data:n=null,config:r=null}){let s=null,i=r||{},l=this.buildRequestConfig(e,t,n,i);l={...this.addCancellationToken(l),...l};try{s=await this.requestInstance.request(l)}catch(a){return this.processRequestError(a,l),this.outputErrorResponse(a,l)}return this.processResponseData(s)}processResponseData(e){return e.data?this.flattenResponse?typeof e.data=="object"&&typeof e.data.data<"u"&&Object.keys(e.data).length===1?e.data.data:e.data:e:this.defaultResponse}};p=f([R.applyMagic],p);var d=class{requestHandler;endpoints;logger;constructor({axios:e,apiUrl:t,endpoints:n,timeout:r=null,cancellable:s=!1,strategy:i=null,flattenResponse:l=null,defaultResponse:a={},logger:u=null,onError:c=null,...q}){this.endpoints=n,this.logger=u,this.requestHandler=new p({...q,baseURL:t,axios:e,timeout:r,cancellable:s,strategy:i,flattenResponse:l,defaultResponse:a,logger:u,onError:c})}getInstance(){return this.requestHandler.getInstance()}__get(e){return e in this?this[e]:this.endpoints[e]?this.handleRequest.bind(this,e):this.handleNonImplemented.bind(this,e)}async handleRequest(...e){let t=e[0],n=this.endpoints[t],r=e[1]||{},s=e[2]||{},i=e[3]||{},l=n.url.replace(/:[a-z]+/gi,c=>s[c.substring(1)]?s[c.substring(1)]:c),a=null,u={...n};return delete u.url,delete u.method,a=await this.requestHandler[(n.method||"get").toLowerCase()](l,r,{...i,...u}),a}handleNonImplemented(e){var t;return(t=this.logger)!=null&&t.log&&this.logger.log(`${e} endpoint not implemented.`),Promise.resolve(null)}};d=f([b.applyMagic],d);var w=o=>new d(o);0&&(module.exports={ApiHandler,RequestErrorHandler,RequestHandler,createApiFetcher}); +var g=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var E=Object.prototype.hasOwnProperty;var C=(o,e)=>{for(var t in e)g(o,t,{get:e[t],enumerable:!0})},x=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of y(e))!E.call(o,r)&&r!==t&&g(o,r,{get:()=>e[r],enumerable:!(n=m(e,r))||n.enumerable});return o};var w=o=>x(g({},"__esModule",{value:!0}),o),f=(o,e,t,n)=>{for(var r=n>1?void 0:n?m(e,t):e,s=o.length-1,i;s>=0;s--)(i=o[s])&&(r=(n?i(e,t,r):i(r))||r);return n&&r&&g(e,t,r),r};var S={};C(S,{ApiHandler:()=>d,RequestErrorHandler:()=>h,RequestHandler:()=>p,createApiFetcher:()=>I});module.exports=w(S);var b=require("js-magic");var R=require("js-magic");var h=class{logger;requestErrorService;constructor(e,t){this.logger=e,this.requestErrorService=t}process(e){var n;(n=this.logger)!=null&&n.warn&&this.logger.warn("API ERROR",e);let t=e;typeof e=="string"&&(t=new Error(e)),this.requestErrorService&&(typeof this.requestErrorService.process<"u"?this.requestErrorService.process(t):typeof this.requestErrorService=="function"&&this.requestErrorService(t))}};var p=class{requestInstance;timeout=3e4;cancellable=!1;strategy="reject";flattenResponse=!0;defaultResponse=null;axios;logger;requestErrorService;requestsQueue;constructor({axios:e,baseURL:t="",timeout:n=null,cancellable:r=!1,strategy:s=null,flattenResponse:i=null,defaultResponse:l={},logger:a=null,onError:u=null,...c}){this.axios=e,this.timeout=n!==null?n:this.timeout,this.strategy=s!==null?s:this.strategy,this.cancellable=r||this.cancellable,this.flattenResponse=i!==null?i:this.flattenResponse,this.defaultResponse=l,this.logger=a||global.console||window.console||null,this.requestErrorService=u,this.requestsQueue=new Map,this.requestInstance=e.create({...c,baseURL:t,timeout:this.timeout})}getInstance(){return this.requestInstance}__get(e){return e in this?this[e]:this.prepareRequest.bind(this,e)}prepareRequest(e,t,n=null,r=null){return this.handleRequest({type:e,url:t,data:n,config:r})}buildRequestConfig(e,t,n,r){let s=e.toLowerCase();return{...r,url:t,method:s,[s==="get"||s==="head"?"params":"data"]:n||{}}}processRequestError(e,t){if(this.isRequestCancelled(e,t))return;t.onError&&typeof t.onError=="function"&&t.onError(e),new h(this.logger,this.requestErrorService).process(e)}async outputErrorResponse(e,t){let n=this.isRequestCancelled(e,t),r=t.strategy||this.strategy;return n&&!t.rejectCancelled?this.defaultResponse:r==="silent"?(await new Promise(()=>null),this.defaultResponse):r==="reject"||r==="throwError"?Promise.reject(e):this.defaultResponse}isRequestCancelled(e,t){return this.axios.isCancel(e)}addCancellationToken(e){if(!this.cancellable&&!e.cancellable)return{};if(typeof e.cancellable<"u"&&!e.cancellable)return{};if(typeof AbortController>"u")return console.error("AbortController is unavailable in your ENV."),{};let{method:t,baseURL:n,url:r,params:s,data:i}=e,l=JSON.stringify([t,n,r,s,i]).substring(0,55**5),a=this.requestsQueue.get(l);a&&a.abort();let u=new AbortController;return this.requestsQueue.set(l,u),{signal:u.signal}}async handleRequest({type:e,url:t,data:n=null,config:r=null}){let s=null,i=r||{},l=this.buildRequestConfig(e,t,n,i);l={...this.addCancellationToken(l),...l};try{s=await this.requestInstance.request(l)}catch(a){return this.processRequestError(a,l),this.outputErrorResponse(a,l)}return this.processResponseData(s)}processResponseData(e){return e.data?this.flattenResponse?typeof e.data=="object"&&typeof e.data.data<"u"&&Object.keys(e.data).length===1?e.data.data:e.data:e:this.defaultResponse}};p=f([R.applyMagic],p);var d=class{requestHandler;endpoints;logger;constructor({axios:e,apiUrl:t,endpoints:n,timeout:r=null,cancellable:s=!1,strategy:i=null,flattenResponse:l=null,defaultResponse:a={},logger:u=null,onError:c=null,...q}){this.endpoints=n,this.logger=u,this.requestHandler=new p({...q,baseURL:t,axios:e,timeout:r,cancellable:s,strategy:i,flattenResponse:l,defaultResponse:a,logger:u,onError:c})}getInstance(){return this.requestHandler.getInstance()}__get(e){return e in this?this[e]:this.endpoints[e]?this.handleRequest.bind(this,e):this.handleNonImplemented.bind(this,e)}async handleRequest(...e){let t=e[0],n=this.endpoints[t],r=e[1]||{},s=e[2]||{},i=e[3]||{},l=n.url.replace(/:[a-z]+/gi,c=>s[c.substring(1)]?s[c.substring(1)]:c),a=null,u={...n};return delete u.url,delete u.method,a=await this.requestHandler[(n.method||"get").toLowerCase()](l,r,{...i,...u}),a}handleNonImplemented(e){var t;return(t=this.logger)!=null&&t.log&&this.logger.log(`${e} endpoint not implemented.`),Promise.resolve(null)}};d=f([b.applyMagic],d);var I=o=>new d(o);0&&(module.exports={ApiHandler,RequestErrorHandler,RequestHandler,createApiFetcher}); //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/node/index.js.map b/dist/node/index.js.map index 6148c38..ada43b0 100644 --- a/dist/node/index.js.map +++ b/dist/node/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.ts","../src/api-handler.ts","../src/request-handler.ts","../src/request-error-handler.ts"],"sourcesContent":["export * from './types';\nexport * from './api-handler';\nexport * from './request-handler';\nexport * from './request-error-handler';\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","// 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","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"],"mappings":"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","names":["src_exports","__export","ApiHandler","RequestErrorHandler","RequestHandler","createApiFetcher","__toCommonJS","import_js_magic","import_js_magic","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","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","createApiFetcher","options"]} \ No newline at end of file +{"version":3,"sources":["../src/index.ts","../src/api-handler.ts","../src/request-handler.ts","../src/request-error-handler.ts"],"sourcesContent":["export * from './types';\nexport * from './api-handler';\nexport * from './request-handler';\nexport * from './request-error-handler';\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// 3rd party libs\nimport { applyMagic, MagicalClass } from 'js-magic';\n\n// Types\nimport type { AxiosInstance } from 'axios';\n\nimport {\n RequestResponse,\n APIHandlerConfig,\n EndpointsConfig,\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]: unknown;\n\n /**\n * @var requestHandler Request Wrapper Instance\n */\n public requestHandler: RequestHandler;\n\n /**\n * Endpoints\n */\n protected endpoints: EndpointsConfig;\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 * @private\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: string[]): 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 = (\n options: APIHandlerConfig,\n) => new ApiHandler(options) as ApiHandler & AllEndpointsList;\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 RequestData,\n RequestResponse,\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 * @private\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 }: RequestData): 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","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"],"mappings":"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","names":["src_exports","__export","ApiHandler","RequestErrorHandler","RequestHandler","createApiFetcher","__toCommonJS","import_js_magic","import_js_magic","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","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","createApiFetcher","options"]} \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs index 20a893b..ee6fc14 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -6,4 +6,5 @@ export default [ js.configs.recommended, eslintPluginPrettierRecommended, ...tseslint.configs.recommended, + { ignores: ['dist'] }, ];