Skip to content

Commit 9b2b9e2

Browse files
committed
feat: tRPC support
1 parent 7203366 commit 9b2b9e2

File tree

21 files changed

+187
-37
lines changed

21 files changed

+187
-37
lines changed

templates/react/add-on/start/assets/src/router.tsx.ejs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ export const createRouter = () => {
2424
},
2525
scrollRestoration: true,
2626
defaultPreloadStaleTime: 0,
27+
<% if (addOnEnabled.tRPC) { %>
28+
Wrap: (props: { children: React.ReactNode }) => {
29+
return (
30+
<TanstackQuery.Provider>
31+
{props.children}
32+
</TanstackQuery.Provider>
33+
);
34+
},
35+
<% } %>
2736
}), TanstackQuery.getContext().queryClient)
2837
<% } else { %>
2938
const router = createTanstackRouter({
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { initTRPC } from "@trpc/server";
2+
import superjson from "superjson";
3+
4+
const t = initTRPC.create({
5+
transformer: superjson,
6+
});
7+
8+
export const createTRPCRouter = t.router;
9+
export const publicProcedure = t.procedure;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { createTRPCContext } from "@trpc/tanstack-react-query";
2+
import type { TRPCRouter } from "@/trpc/router";
3+
4+
export const { TRPCProvider, useTRPC } = createTRPCContext<TRPCRouter>();
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { TRPCError } from '@trpc/server'
2+
import type { TRPCRouterRecord } from '@trpc/server'
3+
// import { z } from 'zod'
4+
5+
import { createTRPCRouter, publicProcedure } from './init'
6+
7+
const peopleRouter = {
8+
list: publicProcedure.query(async () =>
9+
fetch('https://swapi.dev/api/people')
10+
.then((res) => res.json())
11+
.then((d) => d.results as { name: string }[]),
12+
),
13+
} satisfies TRPCRouterRecord
14+
15+
export const trpcRouter = createTRPCRouter({
16+
people: peopleRouter,
17+
})
18+
export type TRPCRouter = typeof trpcRouter
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createAPIFileRoute } from '@tanstack/react-start/api'
2+
import { fetchRequestHandler } from '@trpc/server/adapters/fetch'
3+
import { trpcRouter } from '@/integrations/trpc/router'
4+
5+
function handler({ request }: { request: Request }) {
6+
return fetchRequestHandler({
7+
req: request,
8+
router: trpcRouter,
9+
endpoint: '/api/trpc',
10+
})
11+
}
12+
13+
export const APIRoute = createAPIFileRoute('/api/trpc/$')({
14+
GET: handler,
15+
POST: handler,
16+
})

templates/react/add-on/tRPC/info.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "tRPC",
3+
"description": "Integrate tRPC into your application.",
4+
"phase": "add-on",
5+
"templates": ["file-router"],
6+
"link": "https://trpc.io/",
7+
"routes": [],
8+
"dependsOn": ["tanstack-query", "start"]
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"dependencies": {
3+
"@trpc/client": "^11.0.0",
4+
"@trpc/server": "^11.0.0",
5+
"@trpc/tanstack-react-query": "^11.0.0",
6+
"superjson": "^2.2.2",
7+
"zod": "^3.24.2"
8+
}
9+
}

templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<% if (addOnEnabled.tRPC) { %>
2+
import { QueryClient } from "@tanstack/react-query";
3+
import superjson from "superjson";
4+
import { createTRPCClient, httpBatchStreamLink } from "@trpc/client";
5+
import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
6+
7+
import { TRPCProvider } from "@/integrations/trpc/react";
8+
9+
import type { TRPCRouter } from "@/integrations/trpc/router";
10+
11+
function getUrl() {
12+
const base = (() => {
13+
if (typeof window !== "undefined") return "";
14+
return `http://localhost:${process.env.PORT ?? 3000}`;
15+
})();
16+
return base + "/api/trpc";
17+
}
18+
19+
export const trpcClient = createTRPCClient<TRPCRouter>({
20+
links: [
21+
httpBatchStreamLink({
22+
transformer: superjson,
23+
url: getUrl(),
24+
}),
25+
],
26+
});
27+
28+
const queryClient = new QueryClient({
29+
defaultOptions: {
30+
dehydrate: { serializeData: superjson.serialize },
31+
hydrate: { deserializeData: superjson.deserialize },
32+
},
33+
});
34+
35+
const serverHelpers = createTRPCOptionsProxy({
36+
client: trpcClient,
37+
queryClient: queryClient,
38+
});
39+
40+
export function getContext() {
41+
return {
42+
queryClient,
43+
trpc: serverHelpers,
44+
};
45+
}
46+
47+
export function Provider({ children }: { children: React.ReactNode }) {
48+
return (
49+
<TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
50+
{children}
51+
</TRPCProvider>
52+
);
53+
}
54+
<% } else { %>
55+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
56+
57+
const queryClient = new QueryClient()
58+
59+
export function getContext() {
60+
return {
61+
queryClient,
62+
}
63+
}
64+
65+
export function Provider({ children }: { children: React.ReactNode }) {
66+
return (
67+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
68+
)
69+
}
70+
<% } %>

templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'
22
import { useQuery } from '@tanstack/react-query'
3+
<% if (addOnEnabled.tRPC) { %>
4+
import { useTRPC } from "@/integrations/trpc/react";
5+
<% } %>
36
<% if (codeRouter) { %>
47
import type { RootRoute } from '@tanstack/react-router'
58
<% } else { %>
69
export const Route = createFileRoute('/demo/tanstack-query')({
10+
<% if (addOnEnabled.tRPC) { %>
11+
loader: async ({ context }) => {
12+
await context.queryClient.prefetchQuery(
13+
context.trpc.people.list.queryOptions()
14+
);
15+
},
16+
<% } %>
717
component: TanStackQueryDemo,
818
})
919
<% } %>
1020
function TanStackQueryDemo() {
21+
<% if (addOnEnabled.tRPC) { %>
22+
const trpc = useTRPC();
23+
const { data } = useQuery(trpc.people.list.queryOptions());
24+
<% } else { %>
1125
const { data } = useQuery({
1226
queryKey: ['people'],
1327
queryFn: () =>
@@ -16,6 +30,7 @@ function TanStackQueryDemo() {
1630
.then((d) => d.results as { name: string }[]),
1731
initialData: [],
1832
})
33+
<% } %>
1934

2035
return (
2136
<div className="p-4">

0 commit comments

Comments
 (0)