1'use client';
2
3import { QueryClientProvider, type QueryClient } from '@tanstack/react-query';
4import {
5 httpBatchLink,
6 httpBatchStreamLink,
7 loggerLink,
8 splitLink,
9} from '@trpc/client';
10import { createTRPCReact } from '@trpc/react-query';
11import { type inferRouterInputs, type inferRouterOutputs } from '@trpc/server';
12import { useState } from 'react';
13import SuperJSON from 'superjson';
14
15import { type AppRouter } from '@/server/api/root';
16import { createQueryClient } from './query-client';
17
18let clientQueryClientSingleton: QueryClient | undefined = undefined;
19const getQueryClient = () => {
20 if (typeof window === 'undefined') {
21 // Server: always make a new query client
22 return createQueryClient();
23 }
24 // Browser: use singleton pattern to keep the same query client
25 return (clientQueryClientSingleton ??= createQueryClient());
26};
27
28export const api = createTRPCReact<AppRouter>();
29
30/**
31 * Inference helper for inputs.
32 *
33 * @example type HelloInput = RouterInputs['example']['hello']
34 */
35export type RouterInputs = inferRouterInputs<AppRouter>;
36
37/**
38 * Inference helper for outputs.
39 *
40 * @example type HelloOutput = RouterOutputs['example']['hello']
41 */
42export type RouterOutputs = inferRouterOutputs<AppRouter>;
43
44export function TRPCReactProvider(props: { children: React.ReactNode }) {
45 const queryClient = getQueryClient();
46
47 const [trpcClient] = useState(() =>
48 api.createClient({
49 links: [
50 loggerLink({
51 enabled: op =>
52 process.env.NODE_ENV === 'development' ||
53 (op.direction === 'down' && op.result instanceof Error),
54 }),
55 splitLink({
56 condition(op) {
57 return op.path.startsWith('auth.');
58 },
59 true: httpBatchLink({
60 transformer: SuperJSON,
61 url: getBaseUrl() + '/api/trpc',
62 headers() {
63 const headers = new Headers();
64 headers.set('x-trpc-source', 'react-no-stream');
65 return headers;
66 },
67 }),
68 false: httpBatchStreamLink({
69 transformer: SuperJSON,
70 url: getBaseUrl() + '/api/trpc',
71 headers() {
72 const headers = new Headers();
73 headers.set('x-trpc-source', 'react-stream');
74 return headers;
75 },
76 }),
77 }),
78 ],
79 })
80 );
81
82 return (
83 <QueryClientProvider client={queryClient}>
84 <api.Provider client={trpcClient} queryClient={queryClient}>
85 {props.children}
86 </api.Provider>
87 </QueryClientProvider>
88 );
89}
90
91function getBaseUrl() {
92 if (typeof window !== 'undefined') return window.location.origin;
93 if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
94 return `http://localhost:${process.env.PORT ?? 3000}`;
95}