| import axios, { AxiosInstance, AxiosRequestConfig } from 'axios' |
| import { getSession } from 'next-auth/react' |
|
|
| class APIClient { |
| private client: AxiosInstance |
| private baseURL: string |
|
|
| constructor() { |
| this.baseURL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000' |
| |
| this.client = axios.create({ |
| baseURL: this.baseURL, |
| timeout: 30000, |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| }) |
|
|
| |
| this.client.interceptors.request.use( |
| async (config) => { |
| const session = await getSession() |
| if (session?.accessToken) { |
| config.headers.Authorization = `Bearer ${session.accessToken}` |
| } |
| return config |
| }, |
| (error) => Promise.reject(error) |
| ) |
|
|
| |
| this.client.interceptors.response.use( |
| (response) => response, |
| async (error) => { |
| if (error.response?.status === 401) { |
| |
| window.location.href = '/login' |
| } |
| return Promise.reject(error) |
| } |
| ) |
| } |
|
|
| |
| async request<T>(config: AxiosRequestConfig): Promise<T> { |
| const response = await this.client.request<T>(config) |
| return response.data |
| } |
|
|
| |
| async get<T>(url: string, config?: AxiosRequestConfig): Promise<T> { |
| return this.request<T>({ ...config, method: 'GET', url }) |
| } |
|
|
| async post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> { |
| return this.request<T>({ ...config, method: 'POST', url, data }) |
| } |
|
|
| async put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> { |
| return this.request<T>({ ...config, method: 'PUT', url, data }) |
| } |
|
|
| async delete<T>(url: string, config?: AxiosRequestConfig): Promise<T> { |
| return this.request<T>({ ...config, method: 'DELETE', url }) |
| } |
|
|
| |
| async upload<T>( |
| url: string, |
| file: File, |
| onProgress?: (progress: number) => void |
| ): Promise<T> { |
| const formData = new FormData() |
| formData.append('file', file) |
|
|
| return this.request<T>({ |
| method: 'POST', |
| url, |
| data: formData, |
| headers: { |
| 'Content-Type': 'multipart/form-data', |
| }, |
| onUploadProgress: (progressEvent) => { |
| if (onProgress && progressEvent.total) { |
| const progress = Math.round( |
| (progressEvent.loaded * 100) / progressEvent.total |
| ) |
| onProgress(progress) |
| } |
| }, |
| }) |
| } |
|
|
| |
| createWebSocket(path: string): WebSocket { |
| const wsURL = this.baseURL.replace(/^http/, 'ws') |
| return new WebSocket(`${wsURL}${path}`) |
| } |
| } |
|
|
| |
| export const apiClient = new APIClient() |
|
|
| |
| export const api = { |
| |
| auth: { |
| login: (credentials: { email: string; password: string }) => |
| apiClient.post<{ token: string; user: any }>('/auth/login', credentials), |
| |
| register: (data: { email: string; password: string; name: string }) => |
| apiClient.post<{ token: string; user: any }>('/auth/register', data), |
| |
| logout: () => apiClient.post('/auth/logout'), |
| |
| refreshToken: () => |
| apiClient.post<{ token: string }>('/auth/refresh'), |
| }, |
|
|
| |
| processing: { |
| removeBackground: (file: File, options?: any, onProgress?: (p: number) => void) => |
| apiClient.upload<{ id: string; result: string }>('/process/remove-background', file, onProgress), |
| |
| replaceBackground: (imageId: string, backgroundId: string) => |
| apiClient.post<{ result: string }>('/process/replace-background', { |
| imageId, |
| backgroundId, |
| }), |
| |
| batchProcess: (files: File[], options?: any) => { |
| const formData = new FormData() |
| files.forEach((file) => formData.append('files', file)) |
| if (options) { |
| formData.append('options', JSON.stringify(options)) |
| } |
| return apiClient.post<{ jobId: string }>('/process/batch', formData, { |
| headers: { 'Content-Type': 'multipart/form-data' }, |
| }) |
| }, |
| |
| getJobStatus: (jobId: string) => |
| apiClient.get<{ status: string; progress: number; results?: any[] }>( |
| `/process/jobs/${jobId}` |
| ), |
| }, |
|
|
| |
| projects: { |
| list: (params?: { page?: number; limit?: number; search?: string }) => |
| apiClient.get<{ items: any[]; total: number }>('/projects', { params }), |
| |
| get: (id: string) => |
| apiClient.get<any>(`/projects/${id}`), |
| |
| create: (data: any) => |
| apiClient.post<any>('/projects', data), |
| |
| update: (id: string, data: any) => |
| apiClient.put<any>(`/projects/${id}`, data), |
| |
| delete: (id: string) => |
| apiClient.delete(`/projects/${id}`), |
| }, |
|
|
| |
| backgrounds: { |
| list: (category?: string) => |
| apiClient.get<any[]>('/backgrounds', { params: { category } }), |
| |
| upload: (file: File) => |
| apiClient.upload<{ id: string; url: string }>('/backgrounds/upload', file), |
| |
| generate: (prompt: string) => |
| apiClient.post<{ id: string; url: string }>('/backgrounds/generate', { prompt }), |
| }, |
|
|
| |
| user: { |
| profile: () => |
| apiClient.get<any>('/user/profile'), |
| |
| updateProfile: (data: any) => |
| apiClient.put<any>('/user/profile', data), |
| |
| usage: () => |
| apiClient.get<{ images: number; videos: number; storage: number }>( |
| '/user/usage' |
| ), |
| |
| billing: () => |
| apiClient.get<any>('/user/billing'), |
| }, |
| } |
|
|
| export default api |