MogensR's picture
Create web/src/lib/api/clients.ts
5883557
raw
history blame
5.63 kB
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',
},
})
// Request interceptor for auth
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)
)
// Response interceptor for error handling
this.client.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
// Handle token refresh or redirect to login
window.location.href = '/login'
}
return Promise.reject(error)
}
)
}
// Generic request method
async request<T>(config: AxiosRequestConfig): Promise<T> {
const response = await this.client.request<T>(config)
return response.data
}
// Convenience methods
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 })
}
// File upload
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)
}
},
})
}
// WebSocket connection for real-time updates
createWebSocket(path: string): WebSocket {
const wsURL = this.baseURL.replace(/^http/, 'ws')
return new WebSocket(`${wsURL}${path}`)
}
}
// Export singleton instance
export const apiClient = new APIClient()
// Export typed API methods
export const api = {
// Auth
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
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
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
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
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