Openstatus
www.openstatus.dev
1import "server-only";
2
3import type { AppRouter } from "@openstatus/api";
4
5import { HydrationBoundary } from "@tanstack/react-query";
6import { dehydrate } from "@tanstack/react-query";
7import { createTRPCClient, loggerLink } from "@trpc/client";
8import {
9 type TRPCQueryOptions,
10 createTRPCOptionsProxy,
11} from "@trpc/tanstack-react-query";
12import { cookies } from "next/headers";
13import { cache } from "react";
14import { makeQueryClient } from "./query-client";
15import { endingLink } from "./shared";
16
17// IMPORTANT: Create a stable getter for the query client that
18// will return the same client during the same request.
19export const getQueryClient = cache(makeQueryClient);
20
21export const trpc = createTRPCOptionsProxy<AppRouter>({
22 queryClient: getQueryClient,
23 client: createTRPCClient({
24 links: [
25 loggerLink({
26 enabled: (opts) =>
27 process.env.NODE_ENV === "development" ||
28 (opts.direction === "down" && opts.result instanceof Error),
29 }),
30 endingLink({
31 headers: {
32 "x-trpc-source": "server",
33 },
34 fetch: async (url, options) => {
35 const cookieStore = await cookies();
36 return fetch(url, {
37 ...options,
38 credentials: "include",
39 headers: {
40 ...options?.headers,
41 cookie: cookieStore.toString(),
42 },
43 });
44 },
45 }),
46 ],
47 }),
48});
49
50export function HydrateClient(props: { children: React.ReactNode }) {
51 const queryClient = getQueryClient();
52
53 return (
54 <HydrationBoundary state={dehydrate(queryClient)}>
55 {props.children}
56 </HydrationBoundary>
57 );
58}
59
60// biome-ignore lint/suspicious/noExplicitAny: FIXME: remove any
61export function prefetch<T extends ReturnType<TRPCQueryOptions<any>>>(
62 queryOptions: T,
63) {
64 const queryClient = getQueryClient();
65
66 if (queryOptions.queryKey[1]?.type === "infinite") {
67 // biome-ignore lint/suspicious/noExplicitAny: FIXME: remove any
68 void queryClient.prefetchInfiniteQuery(queryOptions as any);
69 } else {
70 void queryClient.prefetchQuery(queryOptions);
71 }
72}
73
74// biome-ignore lint/suspicious/noExplicitAny: FIXME: remove any
75export function batchPrefetch<T extends ReturnType<TRPCQueryOptions<any>>>(
76 queryOptionsArray: T[],
77) {
78 const queryClient = getQueryClient();
79
80 for (const queryOptions of queryOptionsArray) {
81 if (queryOptions.queryKey[1]?.type === "infinite") {
82 // biome-ignore lint/suspicious/noExplicitAny: FIXME: remove any
83 void queryClient.prefetchInfiniteQuery(queryOptions as any);
84 } else {
85 void queryClient.prefetchQuery(queryOptions);
86 }
87 }
88}