diff --git a/frontend/lib/api/client.ts b/frontend/lib/api/client.ts new file mode 100644 index 0000000..cd447bc --- /dev/null +++ b/frontend/lib/api/client.ts @@ -0,0 +1,14 @@ +// frontend/lib/api/client.ts +import axios from 'axios'; +import {setupInterceptors} from './interceptors' + +const api = axios.create({ + baseURL: process.env.NEXT_PUBLIC_API_URL, +}); + +// Prevent API calls during SSR +if (typeof window !== 'undefined') { + setupInterceptors(api); +} + +export default api; diff --git a/frontend/lib/api/error-handler.ts b/frontend/lib/api/error-handler.ts new file mode 100644 index 0000000..449a5ae --- /dev/null +++ b/frontend/lib/api/error-handler.ts @@ -0,0 +1,11 @@ +// frontend/lib/api/error-handler.ts +import { ApiError } from './types'; + +export function handleApiError(error: any): ApiError { + const response = error.response || {}; + return { + message: response.data?.message || 'Unexpected error occurred', + code: response.data?.code || 'UNKNOWN_ERROR', + status: response.status || 500, + }; +} diff --git a/frontend/lib/api/interceptors.ts b/frontend/lib/api/interceptors.ts new file mode 100644 index 0000000..f83149f --- /dev/null +++ b/frontend/lib/api/interceptors.ts @@ -0,0 +1,33 @@ +// frontend/lib/api/interceptors.ts +import type { AxiosInstance } from 'axios'; +import { handleApiError } from './error-handler'; + +export function setupInterceptors(api: AxiosInstance) { + api.interceptors.request.use((config) => { + const token = localStorage.getItem('jwt'); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; + }); + + api.interceptors.response.use( + (response) => response, + async (error) => { + const { status } = error.response || {}; + if (status === 401) { + window.location.href = '/login'; + } + + // Retry logic: up to 3 attempts + const config = error.config; + if (!config.__retryCount) config.__retryCount = 0; + if (config.__retryCount < 3) { + config.__retryCount += 1; + return api(config); + } + + return Promise.reject(handleApiError(error)); + }, + ); +} diff --git a/frontend/lib/api/types.ts b/frontend/lib/api/types.ts new file mode 100644 index 0000000..77cef32 --- /dev/null +++ b/frontend/lib/api/types.ts @@ -0,0 +1,11 @@ +// frontend/lib/api/types.ts +export interface ApiResponse { + data: T; + status: number; +} + +export interface ApiError { + message: string; + code: string; + status: number; +}