| const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080"; | |
| export class ApiError extends Error { | |
| constructor( | |
| message: string, | |
| public statusCode: number, | |
| public code?: string | |
| ) { | |
| super(message); | |
| this.name = "ApiError"; | |
| } | |
| } | |
| export async function apiRequest<T>( | |
| endpoint: string, | |
| options: RequestInit = {} | |
| ): Promise<T> { | |
| const url = `${API_BASE_URL}${endpoint}`; | |
| const defaultHeaders = { | |
| "Content-Type": "application/json", | |
| }; | |
| const config: RequestInit = { | |
| ...options, | |
| headers: { | |
| ...defaultHeaders, | |
| ...options.headers, | |
| }, | |
| }; | |
| try { | |
| const response = await fetch(url, config); | |
| if (!response.ok) { | |
| const errorData = await response.json().catch(() => ({})); | |
| throw new ApiError( | |
| errorData.message || `HTTP error! status: ${response.status}`, | |
| response.status, | |
| errorData.code | |
| ); | |
| } | |
| return await response.json(); | |
| } catch (error) { | |
| if (error instanceof ApiError) { | |
| throw error; | |
| } | |
| throw new ApiError("Network error", 0); | |
| } | |
| } | |
| export const api = { | |
| get: <T>(endpoint: string, headers?: HeadersInit) => | |
| apiRequest<T>(endpoint, { method: "GET", headers }), | |
| post: <T>(endpoint: string, data?: unknown, headers?: HeadersInit) => | |
| apiRequest<T>(endpoint, { | |
| method: "POST", | |
| body: JSON.stringify(data), | |
| headers, | |
| }), | |
| put: <T>(endpoint: string, data?: unknown, headers?: HeadersInit) => | |
| apiRequest<T>(endpoint, { | |
| method: "PUT", | |
| body: JSON.stringify(data), | |
| headers, | |
| }), | |
| delete: <T>(endpoint: string, headers?: HeadersInit) => | |
| apiRequest<T>(endpoint, { method: "DELETE", headers }), | |
| }; | |