Files
th-hotel-simple/client/src/services/httpClient.ts
2026-07-08 16:20:06 +08:00

55 lines
1.4 KiB
TypeScript

const apiBaseUrl = import.meta.env.VITE_API_BASE_URL ?? ''
export class ApiError extends Error {
readonly status: number
readonly details: unknown
constructor(message: string, status: number, details: unknown) {
super(message)
this.name = 'ApiError'
this.status = status
this.details = details
}
}
export async function getJson<T>(path: string): Promise<T> {
return requestJson<T>(path, {
method: 'GET',
})
}
export async function sendJson<T>(path: string, method: 'POST' | 'PUT', body?: unknown): Promise<T> {
return requestJson<T>(path, {
method,
headers: {
'Content-Type': 'application/json',
},
body: body === undefined ? undefined : JSON.stringify(body),
})
}
async function requestJson<T>(path: string, init: RequestInit): Promise<T> {
const response = await fetch(`${apiBaseUrl}${path}`, {
...init,
headers: {
Accept: 'application/json',
...init.headers,
},
})
const payload = await readResponsePayload(response)
if (!response.ok) {
throw new ApiError(`Request failed with status ${response.status}`, response.status, payload)
}
return payload as T
}
async function readResponsePayload(response: Response): Promise<unknown> {
const contentType = response.headers.get('content-type') ?? ''
if (!contentType.includes('application/json')) {
return response.text()
}
return response.json()
}