56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
|
import { type DefaultError, type UseMutationOptions, type queryOptions, useQuery } from "@tanstack/react-query"
|
||
|
import { useNavigate } from "@tanstack/react-router"
|
||
|
import { useEffect } from "react"
|
||
|
|
||
|
class BadRequestError extends Error {}
|
||
|
class InternalError extends Error {}
|
||
|
class UnauthenticatedError extends Error {}
|
||
|
|
||
|
type QueryKey = ["bookmarks", ...ReadonlyArray<unknown>]
|
||
|
|
||
|
async function fetchApi<TData>(route: string, init?: RequestInit): Promise<[TData | void, Response]> {
|
||
|
const response = await fetch(`${import.meta.env.VITE_API_URL}/api${route}`, {
|
||
|
...init,
|
||
|
credentials: "include",
|
||
|
})
|
||
|
switch (response.status) {
|
||
|
case 200:
|
||
|
return [await response.json(), response]
|
||
|
case 204:
|
||
|
return [undefined, response]
|
||
|
case 400:
|
||
|
throw new BadRequestError()
|
||
|
case 401:
|
||
|
throw new UnauthenticatedError()
|
||
|
default:
|
||
|
throw new InternalError()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function useAuthenticatedQuery<TData>(queryKey: QueryKey, fn: () => Promise<TData>) {
|
||
|
const query = useQuery({
|
||
|
queryKey,
|
||
|
queryFn: () => fn(),
|
||
|
retry: (_, error) => !(error instanceof UnauthenticatedError),
|
||
|
})
|
||
|
|
||
|
const navigate = useNavigate()
|
||
|
|
||
|
useEffect(() => {
|
||
|
if (query.error && query.error instanceof UnauthenticatedError) {
|
||
|
navigate({ to: "/login", replace: true })
|
||
|
}
|
||
|
}, [query.error, navigate])
|
||
|
|
||
|
return query
|
||
|
}
|
||
|
|
||
|
function mutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown>(
|
||
|
options: UseMutationOptions<TData, TError, TVariables, TContext>,
|
||
|
): UseMutationOptions<TData, TError, TVariables, TContext> {
|
||
|
return options
|
||
|
}
|
||
|
|
||
|
export { BadRequestError, InternalError, UnauthenticatedError, fetchApi, useAuthenticatedQuery, mutationOptions }
|
||
|
export type { QueryKey }
|