2026-02-16 20:39:41 +01:00
|
|
|
const API_BASE = import.meta.env['VITE_API_URL'] ?? ''
|
2026-02-05 15:09:14 +01:00
|
|
|
|
|
|
|
|
export class ApiError extends Error {
|
|
|
|
|
status: number
|
|
|
|
|
|
|
|
|
|
constructor(status: number, message: string) {
|
|
|
|
|
super(message)
|
|
|
|
|
this.name = 'ApiError'
|
|
|
|
|
this.status = status
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 16:41:24 +01:00
|
|
|
async function request<T>(path: string, options?: RequestInit): Promise<T> {
|
2026-02-05 15:09:14 +01:00
|
|
|
const res = await fetch(`${API_BASE}/api/v1${path}`, {
|
|
|
|
|
...options,
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
...options?.headers,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
const body = await res.json().catch(() => ({}))
|
|
|
|
|
throw new ApiError(res.status, body.detail ?? res.statusText)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (res.status === 204) return undefined as T
|
|
|
|
|
return res.json()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const api = {
|
|
|
|
|
get: <T>(path: string) => request<T>(path),
|
|
|
|
|
|
|
|
|
|
post: <T>(path: string, body: unknown) =>
|
|
|
|
|
request<T>(path, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
body: JSON.stringify(body),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
patch: <T>(path: string, body: unknown) =>
|
|
|
|
|
request<T>(path, {
|
|
|
|
|
method: 'PATCH',
|
|
|
|
|
body: JSON.stringify(body),
|
|
|
|
|
}),
|
|
|
|
|
|
2026-02-05 18:36:19 +01:00
|
|
|
put: <T>(path: string, body: unknown) =>
|
|
|
|
|
request<T>(path, {
|
|
|
|
|
method: 'PUT',
|
|
|
|
|
body: JSON.stringify(body),
|
|
|
|
|
}),
|
|
|
|
|
|
2026-02-14 16:41:24 +01:00
|
|
|
del: <T = void>(path: string) => request<T>(path, { method: 'DELETE' }),
|
2026-02-05 15:09:14 +01:00
|
|
|
}
|