export class ApiError extends Error { public status: number; public data: unknown; constructor(status: number, data: unknown) { super(`HTTP error! status: ${status}`); this.status = status; this.data = data; Object.setPrototypeOf(this, ApiError.prototype); } } const utils = { isTokenExpired: (token: string): boolean => { const payload = JSON.parse(atob(token.split('.')[1])); // Decode JWT payload return payload.exp * 1000 < Date.now(); // Compare expiration (in ms) to current time }, getUserRoles: (token: string): string[] => { try { const payload = JSON.parse(atob(token.split('.')[1])); return payload['http://schemas.microsoft.com/ws/2008/06/identity/claims/role'] || // Standard role claim payload.role || // Fallback for custom 'role' claim []; } catch { return []; } }, /*The following may not be needed any longer? **TODO: WebMethod should be changed to mimic fetch command but add in auth headers? fetch('/api/protected-endpoint', { headers: { 'Authorization': `Bearer ${localStorage.getItem('accessToken')}` } }); */ getCookie: (name: string): string | null => { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop()?.split(';').shift() ?? null; return null; }, getParameterByName: (name: string): string | null => { const regex = new RegExp(`[?&]${name}=([^&#]*)`); const results = regex.exec(window.location.search); return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null; }, //addAuthHeaders: (headers: Record = {}): Record => { // const authToken = utils.getCookie('Auth-Token'); // if (authToken) { // headers['Auth-Token'] = authToken; // } // const impersonateGuid = utils.getParameterByName("impersonateid") || sessionStorage.getItem('Auth-Impersonate-Guid'); // if (impersonateGuid) { // sessionStorage.setItem('Auth-Impersonate-Guid', impersonateGuid); // headers['Auth-Impersonate-Guid'] = impersonateGuid; // } // const franchiseCode = sessionStorage.getItem('franchiseCode'); // if (franchiseCode) { // headers['Auth-Current-Franchise'] = franchiseCode; // } // return headers; //}, //webMethod: async ({ // httpMethod = 'POST', // baseMethodPath = 'api/', // methodPage = '', // methodName = '', // parameters = {} as Record, // contentType = 'application/json;', // timeout = 300000, // success = (_data: T) => { }, // error = (_err: unknown) => { }, //}: { // httpMethod?: string; // baseMethodPath?: string; // methodPage?: string; // methodName?: string; // contentType?: string; // parameters?: Record; // timeout?: number; // success?: (_data: T) => void; // error?: (_err: unknown) => void; //}): Promise => { // try { // const baseUrl = window.API_BASE_URL || ''; // const url = `${baseUrl.replace(/\/$/, '')}/${baseMethodPath.replace(/\/$/, '')}/${methodPage}${methodName ? '/' + methodName : ''}`; // const headers = utils.addAuthHeaders({ // 'Content-Type': contentType, // }); // const controller = new AbortController(); // //const timeoutId = setTimeout(() => controller.abort(), timeout); // setTimeout(() => controller.abort(), timeout); // const response = await fetch(url, { // method: httpMethod, // headers, // body: (httpMethod.toUpperCase() == "GET" ? null : JSON.stringify(parameters)), // signal: controller.signal, // }); // if (!response.ok) { // let data = null; // try { // data = await response.json(); // } catch { // // Intentionally empty, if not json ignore // } // throw new ApiError(response.status, data); // } // const authToken = response.headers.get('Auth-Token'); // const loggedIn = response.headers.get('usahl_logged_in') === 'true'; // const expires = loggedIn ? 365 : 14; // document.cookie = `Auth-Token=${authToken};path=/;max-age=${expires * 24 * 60 * 60}`; // document.cookie = `usahl_logged_in=${loggedIn};path=/;max-age=${expires * 24 * 60 * 60}`; // const data = await response.json(); // success(data); // } catch (err) { // if ((err as Error).name === 'AbortError') { // console.error('Request timed out'); // } // error(err); // } //}, getBoolean: (variable: any): boolean => { if (variable != null) { switch (typeof variable) { case 'boolean': return variable; case 'number': return variable !== 0; case 'string': return /^(true|yes)$/i.test(variable) || variable.length > 0; } } return false; }, //isLoggedIn: (): boolean => { // return utils.getBoolean(utils.getCookie('usahl_logged_in')); //}, //sessionStorage: (key: string, value?: any): any => { // if (value === undefined) { // let val = window.sessionStorage.getItem(key); // if (val && val.startsWith('usahl_json:')) { // val = val.substring(11); // return JSON.parse(val); // } // return val; // } else { // const val = typeof value === 'object' ? `usahl_json:${JSON.stringify(value)}` : value; // window.sessionStorage.setItem(key, val); // } //}, //sessionStorageClear: (): void => { // window.sessionStorage.clear(); //}, //sessionStorageRemove: (key: string): void => { // window.sessionStorage.removeItem(key); //}, //localStorage: (key: string, value?: any): any => { // if (value === undefined) { // let val = window.localStorage.getItem(key); // if (val && val.startsWith('usahl_json:')) { // val = val.substring(11); // return JSON.parse(val); // } // return val; // } else { // const val = typeof value === 'object' ? `usahl_json:${JSON.stringify(value)}` : value; // window.localStorage.setItem(key, val); // } //}, //localStorageClear: (): void => { // window.localStorage.clear(); //}, //localStorageRemove: (key: string): void => { // window.localStorage.removeItem(key); //}, }; declare global { interface Window { utils: object } } window.utils = utils; export default utils;