UNPKG

custom-api-handler

Version:

The package uses axios library to request APIs and uses local-storage for tokens (auth & refresh).

352 lines (334 loc) 11.4 kB
import axios, { Method } from "axios"; import { authToken, commonErrorMsg, refreshToken, refreshTokenNotFound, responseSuccess, sessionExpired, unknownError, } from "./customMsgs"; import { isAccessTokenExpired, isRefreshTokenExpired, } from "./customValidations"; /** * API-Handler class for custom API requesting methods with axios */ class APIHandler { private tokenBearerLabel: string = ""; private refreshTokenLabelName: string = Buffer.from(refreshToken).toString("base64"); private accessTokenLabelName: string = Buffer.from(authToken).toString("base64"); constructor() {} /** * Method to set token label * @param tokenBearerLabel | Provide Bearer name to be included for tokens added in header for API request (if any) */ public setTokenBearerLabel = (tokenBearerLabel: string) => { this.tokenBearerLabel = tokenBearerLabel; }; /** * Method to set refresh-token label name * @param refreshTokenLabelName | Provide refresh-token label name that is sent from backend-server. */ public setRefreshTokenLabelName = (refreshTokenLabelName: string) => { this.refreshTokenLabelName = Buffer.from(refreshTokenLabelName).toString( "base64" ); localStorage.setItem(this.refreshTokenLabelName, ""); }; /** * Method to get current used refresh-token label name * @returns | Refresh-Token Label Name */ public getRefreshTokenLabelName = () => Buffer.from(this.refreshTokenLabelName, "base64").toString(); /** * Method to set access-token label name * @param accessTokenLabelName | Provide access-token label name that is sent from backend-server. */ public setAccessTokenLabelName = (accessTokenLabelName: string) => { this.accessTokenLabelName = Buffer.from(accessTokenLabelName).toString("base64"); localStorage.setItem(this.accessTokenLabelName, ""); }; /** * Method to get current used access-token label name * @returns | Access-Token Label Name */ public getAccessTokenLabelName = () => Buffer.from(this.accessTokenLabelName, "base64").toString(); /** * Method to validate params * @param obj | Provide params in object for validation * @returns | custom msg (if error) or false */ private validateParams = (obj: any) => { for (let objProp in obj) { if ( (obj[objProp] === null || obj[objProp] === undefined) && objProp !== "params" && objProp !== "data" ) { return `${commonErrorMsg} ${objProp}!`; } } return false; }; /** * Method for requesting API with options for including auth & refresh tokens in API request header * @param {String} url | Provide API URL to be requested * @param {Method} method | Provide request type * @param {any} data | Provide request-body(if any) * @param {any} params | Provide request-params(if any) * @param {String} baseURL | Provide API Base-URL for the request * @param {Boolean} isAuthTokenRequiredInHeader | Provide true/false for adding auth-token from local-storage in header * @param {Boolean} isRefTokenRequiredInHeader | Provide true/false for adding refresh-token from local-storage in header * @returns | Requested API response promise */ public requestApi = async ( url: string = "", method: Method = "get", data: any = null, params: any = null, baseURL: string = "", isAuthTokenRequiredInHeader: boolean = true, isRefTokenRequiredInHeader: boolean = true ) => { try { let paramsValidation = this.validateParams({ url, method, data, params, baseURL, isAuthTokenRequiredInHeader, isRefTokenRequiredInHeader, }); if (paramsValidation) { throw new Error(paramsValidation); } else { let authTokenValue = ""; let refreshTokenValue = ""; let header = {}; if (isAuthTokenRequiredInHeader && isRefTokenRequiredInHeader) { authTokenValue = `${this.tokenBearerLabel} ${localStorage.getItem( this.accessTokenLabelName )}`; refreshTokenValue = `${this.tokenBearerLabel} ${localStorage.getItem( this.refreshTokenLabelName )}`; header = { [this.getAccessTokenLabelName()]: authTokenValue, [this.getRefreshTokenLabelName()]: refreshTokenValue, }; } else if (isAuthTokenRequiredInHeader) { authTokenValue = `${this.tokenBearerLabel} ${localStorage.getItem( this.accessTokenLabelName )}`; header = { [this.getAccessTokenLabelName()]: authTokenValue, }; } else if (isRefTokenRequiredInHeader) { refreshTokenValue = `${this.tokenBearerLabel} ${localStorage.getItem( this.refreshTokenLabelName )}`; header = { [this.getRefreshTokenLabelName()]: refreshTokenValue, }; } return await axios({ baseURL, url, method, data, headers: header, params, }) .then((response) => response) .catch((error) => { throw error; }); } } catch (error) { throw error; } }; /** * Method for requesting API with refresh-token wrapper for requesting new auth & refresh tokens before each API request * @param {String} url | Provide API URL to be requested * @param {String} rftURL | Provide refresh-token API URL * @param {Method} method | Provide request type * @param {any} data | Provide request-body(if any) * @param {any} params | Provide request-params(if any) * @param {String} baseURL | Provide API Base-URL for the request * @param {String} rftBaseURL | Provide refresh-token API Base-URL for the request * @returns | Requested API response promise */ public rftWrapper = async ( url: string = "", rftURL: string = "", method: Method = "get", data: any = null, params: any = null, baseURL: string = "", rftBaseURL: string = "" ) => { try { let paramsValidation = this.validateParams({ url, rftURL, method, data, params, baseURL, rftBaseURL, }); if (paramsValidation) { throw new Error(paramsValidation); } else { let refreshTokenHeaders = { [this.getAccessTokenLabelName()]: `${ this.tokenBearerLabel } ${localStorage.getItem(this.accessTokenLabelName)}`, [this.getRefreshTokenLabelName()]: `${ this.tokenBearerLabel } ${localStorage.getItem(this.refreshTokenLabelName)}`, }; return await axios({ baseURL: rftBaseURL, url: rftURL, data: "", headers: refreshTokenHeaders, method: "GET", }) .then(async (response) => { if ( response.data?.response_type?.toUpperCase() === responseSuccess ) { let responseData = response.data?.response_data; let authTokenValue = responseData[this.getAccessTokenLabelName()]; let refreshTokenValue = responseData[this.getRefreshTokenLabelName()]; if (authTokenValue) { localStorage.setItem(this.accessTokenLabelName, authTokenValue); } if (refreshTokenValue) { localStorage.setItem( this.refreshTokenLabelName, refreshTokenValue ); } return await this.requestApi(url, method, data, params, baseURL); } else { if (response.data?.error_description === refreshTokenNotFound) { return await this.requestApi( url, method, data, params, baseURL ); } } }) .catch((error) => { setTimeout(() => { this.removeLocalStorage(); window.location.reload(); }, 2000); return Promise.reject(new Error(unknownError)); }); } } catch (error) { throw error; } }; /** * Method for requesting API with auth & refresh tokens expiry check and requesting new tokens before each API request (if expired) * @param {String} url | Provide API URL to be requested * @param {String} rftURL | Provide refresh-token API URL * @param {Method} method | Provide request type * @param {any} data | Provide request-body(if any) * @param {any} params | Provide request-params(if any) * @param {Boolean} isRFTandATValidationRequired | Provide true/false for including auth-token & refresh-token expiry check * @param {String} baseURL | Provide API Base-URL for the request * @param {String} rftBaseURL | Provide refresh-token API Base-URL for the request * @returns | Requested API response promise */ public reqAPIwithRFTWrapper = async ( url: string = "", rftURL: string = "", method: Method = "get", data: any = null, params: any = null, isRFTandATValidationRequired: boolean = true, baseURL: string = "", rftBaseURL: string = "" ) => { try { let paramsValidation = this.validateParams({ url, rftURL, method, data, params, isRFTandATValidationRequired, baseURL, rftBaseURL, }); if (paramsValidation) { throw new Error(paramsValidation); } else { if (isRFTandATValidationRequired) { if (isAccessTokenExpired() && !isRefreshTokenExpired()) { return await this.rftWrapper( url, rftURL, method, data, params, baseURL, rftBaseURL ); } else if (isRefreshTokenExpired()) { setTimeout(() => { this.removeLocalStorage(); window.location.reload(); }, 2000); return Promise.reject(new Error(sessionExpired)); } else { return await this.requestApi(url, method, data, params, baseURL); } } else { return await this.rftWrapper( url, rftURL, method, data, params, baseURL, rftBaseURL ); } } } catch (error) { throw error; } }; /** * Method to remove auth-token & refresh-token from local-storage */ private removeLocalStorage = () => { const localStorageArray = [ this.accessTokenLabelName, this.refreshTokenLabelName, ]; for (let localStorageItem of localStorageArray) { localStorage.removeItem(localStorageItem); } }; } export const apiHandler = new APIHandler();