2026-03-15 17:10:32 +00:00
|
|
|
import { createContext, useContext } from "react"
|
|
|
|
|
|
|
|
|
|
export type ApiRequestMiddleware = (
|
|
|
|
|
url: Parameters<typeof fetch>[0],
|
|
|
|
|
init: RequestInit,
|
|
|
|
|
) => RequestInit
|
|
|
|
|
|
|
|
|
|
export class ApiClient {
|
|
|
|
|
private readonly baseUrl: string
|
|
|
|
|
private readonly middlewares: readonly ApiRequestMiddleware[]
|
|
|
|
|
|
|
|
|
|
static noop = new ApiClient({ baseUrl: "" })
|
|
|
|
|
|
|
|
|
|
constructor({
|
|
|
|
|
baseUrl,
|
|
|
|
|
middlewares = [],
|
|
|
|
|
}: {
|
|
|
|
|
baseUrl: string
|
|
|
|
|
middlewares?: ApiRequestMiddleware[]
|
|
|
|
|
}) {
|
|
|
|
|
this.baseUrl = baseUrl
|
|
|
|
|
this.middlewares = middlewares
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async request<T>(...[url, init = {}]: Parameters<typeof fetch>): Promise<[Response, T]> {
|
|
|
|
|
const finalInit = this.middlewares.reduce(
|
|
|
|
|
(prevInit, middleware) => middleware(url, prevInit),
|
|
|
|
|
init,
|
|
|
|
|
)
|
2026-04-12 18:33:46 +01:00
|
|
|
return fetch(this.baseUrl ? new URL(url.toString(), this.baseUrl) : url, finalInit).then(
|
|
|
|
|
(res) => Promise.all([Promise.resolve(res), res.json()]),
|
2026-03-15 17:10:32 +00:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const ApiClientContext = createContext(ApiClient.noop)
|
|
|
|
|
export function useApiClient() {
|
|
|
|
|
return useContext(ApiClientContext)
|
|
|
|
|
}
|