File
Blob: src/client/query.ts
| 1 | import { QueryClient } from "@tanstack/react-query"; |
| 2 | |
| 3 | import { isApiError } from "@/client/lib/api"; |
| 4 | import { redirectToLogin } from "@/client/auth/login-redirect"; |
| 5 | import { toast } from "@/client/lib/toast"; |
| 6 | |
| 7 | function isUnauthorizedError(err: unknown): boolean { |
| 8 | if (!err) return false; |
| 9 | if (typeof err === "object" && err !== null && "status" in err) { |
| 10 | const status = (err as { status?: number }).status; |
| 11 | if (status === 401) return true; |
| 12 | } |
| 13 | if (isApiError(err) && err.error.code === "unauthorized") return true; |
| 14 | return false; |
| 15 | } |
| 16 | |
| 17 | export const queryClient = new QueryClient({ |
| 18 | defaultOptions: { |
| 19 | queries: { |
| 20 | staleTime: 30_000, |
| 21 | retry: (_failureCount, err) => { |
| 22 | if (isUnauthorizedError(err)) return false; |
| 23 | return _failureCount < 1; |
| 24 | }, |
| 25 | refetchOnWindowFocus: false, |
| 26 | }, |
| 27 | mutations: { |
| 28 | onError: (err) => { |
| 29 | if (isUnauthorizedError(err)) { |
| 30 | redirectToLogin(); |
| 31 | return; |
| 32 | } |
| 33 | const message = |
| 34 | (err && typeof err === "object" && "error" in err && isApiError(err) && err.error.message) || |
| 35 | (err instanceof Error && err.message) || |
| 36 | "Something went wrong."; |
| 37 | toast.error(message); |
| 38 | }, |
| 39 | }, |
| 40 | }, |
| 41 | }); |