import axios, {type AxiosError, type AxiosRequestConfig, type Method} from 'axios'; import JSONbig from 'json-bigint'; import { PrincipalType } from './auth/authTypes'; // Create a JSONbig instance that stores big integers as strings const JSONbigString = JSONbig({ storeAsString: true }); const apiClient = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || '/api', timeout: 10000, // transformResponse is used to parse JSON with big integers (Long type from backend) as strings. // This prevents precision loss in JavaScript. transformResponse: [(data) => { // Do not transform if data is not a string or is empty if (!data || typeof data !== 'string') { return data; } try { // Use the configured JSONbig instance to parse the data return JSONbigString.parse(data); } catch (e) { // If parsing fails, it might not be JSON, so return original data // This is the default behavior of axios if parsing fails return data; } }], }); export const isLoginRequiredError = (error: any): boolean => { if (!axios.isAxiosError(error) || !error.response) { return false; } const LOGIN_REQUIRED_ERROR_CODE = ['A001', 'A002', 'A003', 'A006']; const code = error.response?.data?.code; return code && LOGIN_REQUIRED_ERROR_CODE.includes(code); } async function request( method: Method, endpoint: string, data: object = {}, type: PrincipalType, ): Promise { const config: AxiosRequestConfig = { method, url: endpoint, headers: { 'Content-Type': 'application/json' }, }; const accessTokenKey = type === PrincipalType.ADMIN ? 'adminAccessToken' : 'accessToken'; const accessToken = localStorage.getItem(accessTokenKey); if (accessToken) { if (!config.headers) { config.headers = {}; } config.headers['Authorization'] = `Bearer ${accessToken}`; } if (method.toUpperCase() !== 'GET') { config.data = data; } try { const response = await apiClient.request(config); return response.data.data; } catch (error: unknown) { const axiosError = error as AxiosError<{ code: string, message: string }>; console.error('API 요청 실패:', axiosError); throw axiosError; } } async function get(endpoint: string): Promise { return request('GET', endpoint, {}, PrincipalType.USER); } async function adminGet(endpoint: string): Promise { return request('GET', endpoint, {}, PrincipalType.ADMIN); } async function post(endpoint: string, data: object = {}): Promise { return request('POST', endpoint, data, PrincipalType.USER); } async function adminPost(endpoint: string, data: object = {}): Promise { return request('POST', endpoint, data, PrincipalType.ADMIN); } async function put(endpoint: string, data: object = {}): Promise { return request('PUT', endpoint, data, PrincipalType.USER); } async function adminPut(endpoint: string, data: object = {}): Promise { return request('PUT', endpoint, data, PrincipalType.ADMIN); } async function patch(endpoint: string, data: object = {}): Promise { return request('PATCH', endpoint, data, PrincipalType.USER); } async function adminPatch(endpoint: string, data: object = {}): Promise { return request('PATCH', endpoint, data, PrincipalType.ADMIN); } async function del(endpoint: string): Promise { return request('DELETE', endpoint, {}, PrincipalType.USER); } async function adminDel(endpoint: string): Promise { return request('DELETE', endpoint, {}, PrincipalType.ADMIN); } export default { get, adminGet, post, adminPost, put, adminPut, patch, adminPatch, del, adminDel, };