83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
export interface ApiResponse<T = any> {
|
|
error?: string;
|
|
success: boolean;
|
|
data?: T;
|
|
message?: string;
|
|
requires2FA?: boolean;
|
|
}
|
|
|
|
class ApiClient {
|
|
private getBaseURL(): string {
|
|
if (typeof window === 'undefined') {
|
|
// Server-side calls downstream Spring Boot
|
|
return process.env.API_URL_SERVER || 'http://localhost:8080';
|
|
}
|
|
// Client-side calls Next.js API Routes proxy
|
|
return process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/api';
|
|
}
|
|
|
|
private async request<T>(
|
|
method: string,
|
|
endpoint: string,
|
|
body?: any,
|
|
config?: RequestInit & { timeoutMs?: number }
|
|
): Promise<any> {
|
|
const baseURL = this.getBaseURL();
|
|
const url = `${baseURL}${endpoint}`;
|
|
|
|
const headers: Record<string, string> = {
|
|
'Content-Type': 'application/json',
|
|
...(config?.headers as any),
|
|
};
|
|
|
|
const controller = new AbortController();
|
|
const id = setTimeout(() => controller.abort(), config?.timeoutMs || 10000);
|
|
|
|
const options: RequestInit = {
|
|
method,
|
|
headers,
|
|
signal: controller.signal,
|
|
...config,
|
|
};
|
|
|
|
if (body !== undefined) {
|
|
options.body = JSON.stringify(body);
|
|
}
|
|
|
|
try {
|
|
const res = await fetch(url, options);
|
|
clearTimeout(id);
|
|
|
|
if (!res.ok && res.status !== 400 && res.status !== 401 && res.status !== 403) {
|
|
throw new Error(`HTTP error! status: ${res.status}`);
|
|
}
|
|
|
|
return await res.json();
|
|
} catch (err: any) {
|
|
clearTimeout(id);
|
|
if (err.name === 'AbortError') {
|
|
throw new Error('Request timeout');
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
get<T>(endpoint: string, config?: RequestInit & { timeoutMs?: number }) {
|
|
return this.request<T>('GET', endpoint, undefined, config);
|
|
}
|
|
|
|
post<T>(endpoint: string, data?: any, config?: RequestInit & { timeoutMs?: number }) {
|
|
return this.request<T>('POST', endpoint, data, config);
|
|
}
|
|
|
|
put<T>(endpoint: string, data?: any, config?: RequestInit & { timeoutMs?: number }) {
|
|
return this.request<T>('PUT', endpoint, data, config);
|
|
}
|
|
|
|
delete<T>(endpoint: string, config?: RequestInit & { timeoutMs?: number }) {
|
|
return this.request<T>('DELETE', endpoint, undefined, config);
|
|
}
|
|
}
|
|
|
|
export const apiClient = new ApiClient();
|