feat(api): add httpJson helper
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { isApiError, type ApiError } from "@/lib/errors"
|
||||
|
||||
type JsonRequestInit = Omit<RequestInit, "body" | "headers"> & {
|
||||
headers?: HeadersInit
|
||||
body?: BodyInit | null
|
||||
json?: unknown
|
||||
}
|
||||
|
||||
async function readJsonBody(res: Response): Promise<unknown | null> {
|
||||
const text = await res.text()
|
||||
if (!text) return null
|
||||
|
||||
try {
|
||||
return JSON.parse(text) as unknown
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export async function httpJson<T>(path: string, init?: JsonRequestInit): Promise<T> {
|
||||
if (/^https?:\/\//.test(path)) {
|
||||
throw new Error("Absolute URLs are not allowed")
|
||||
}
|
||||
|
||||
const { json, headers: headersInit, body: bodyInit, ...rest } = init ?? {}
|
||||
|
||||
const headers = new Headers(headersInit)
|
||||
headers.set("Accept", "application/json")
|
||||
|
||||
const body = json === undefined ? bodyInit : JSON.stringify(json)
|
||||
|
||||
if (json !== undefined && !headers.has("Content-Type")) {
|
||||
headers.set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
const res = await fetch(path, {
|
||||
...rest,
|
||||
headers,
|
||||
body,
|
||||
})
|
||||
|
||||
const data = await readJsonBody(res)
|
||||
|
||||
if (res.ok) {
|
||||
return data as T
|
||||
}
|
||||
|
||||
const apiError = isApiError(data) ? data : null
|
||||
if (res.status === 401 || apiError?.code === 401) {
|
||||
throw new Error("UNAUTHORIZED")
|
||||
}
|
||||
|
||||
if (apiError) {
|
||||
throw apiError
|
||||
}
|
||||
|
||||
throw { code: res.status, msg: res.statusText || "Request failed" } satisfies ApiError
|
||||
}
|
||||
Reference in New Issue
Block a user