102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
"use client"
|
|
|
|
import {
|
|
QueryCache,
|
|
QueryClient,
|
|
QueryClientProvider,
|
|
} from "@tanstack/react-query"
|
|
import { httpBatchLink, loggerLink, TRPCClientError } from "@trpc/client"
|
|
import { useState } from "react"
|
|
|
|
import { login } from "@/constants/routes/handleAuth"
|
|
import { env } from "@/env/client"
|
|
import { SessionExpiredError } from "@/server/errors/trpc"
|
|
import { transformer } from "@/server/transformer"
|
|
|
|
import useLang from "@/hooks/useLang"
|
|
|
|
import { trpc } from "./client"
|
|
|
|
import type { AnyTRPCRouter } from "@trpc/server"
|
|
|
|
function initializeTrpcClient() {
|
|
// Locally we set nextjs to run on port to 3000 so that we always guarantee
|
|
// that trpc and next are running on the same port.
|
|
return trpc.createClient({
|
|
links: [
|
|
loggerLink({
|
|
enabled: (opts) =>
|
|
(env.NEXT_PUBLIC_NODE_ENV === "development" &&
|
|
typeof window !== "undefined") ||
|
|
(opts.direction === "down" && opts.result instanceof Error),
|
|
}),
|
|
httpBatchLink({
|
|
fetch,
|
|
transformer,
|
|
/**
|
|
* This is locally in Next.js
|
|
*/
|
|
url: `/api/web/trpc`,
|
|
}),
|
|
],
|
|
})
|
|
}
|
|
|
|
export default function TrpcProvider({ children }: React.PropsWithChildren) {
|
|
const lang = useLang()
|
|
const [queryClient] = useState(
|
|
() =>
|
|
new QueryClient({
|
|
queryCache: new QueryCache({
|
|
async onError(error) {
|
|
if (error instanceof TRPCClientError) {
|
|
const appError: TRPCClientError<AnyTRPCRouter> = error
|
|
console.log({ appError })
|
|
if (appError.data?.code === "UNAUTHORIZED") {
|
|
if (appError.data?.cause instanceof SessionExpiredError) {
|
|
const loginUrl = login[lang]
|
|
window.location.assign(loginUrl)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
}),
|
|
defaultOptions: {
|
|
queries: {
|
|
staleTime: 60 * 1000,
|
|
retry(failureCount, error) {
|
|
if (error instanceof TRPCClientError) {
|
|
const appError: TRPCClientError<AnyTRPCRouter> = error
|
|
|
|
// Do not retry query requests that got UNAUTHORIZED error.
|
|
// It won't make a difference sending the same request again.
|
|
|
|
if (appError.data?.code) {
|
|
if (
|
|
[
|
|
"UNAUTHORIZED",
|
|
"INTERNAL_SERVER_ERROR",
|
|
"FORBIDDEN",
|
|
].includes(appError.data.code)
|
|
) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
// Retry all client requests that fail (and are not handled above)
|
|
// at most 3 times.
|
|
return failureCount < 3
|
|
},
|
|
},
|
|
},
|
|
})
|
|
)
|
|
const [trpcClient] = useState(() => initializeTrpcClient())
|
|
return (
|
|
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
</trpc.Provider>
|
|
)
|
|
}
|