-
Notifications
You must be signed in to change notification settings - Fork 25
conditional rsc or trpc client #32
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
{ | ||
"typescript.tsdk": "./node_modules/typescript/lib", | ||
"typescript.enablePromptUseWorkspaceTsdk": true | ||
"typescript.enablePromptUseWorkspaceTsdk": true, | ||
"prettier.requireConfig": false | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { useQuery } from "@tanstack/react-query"; | ||
import { createTRPCClient, httpBatchLink } from "@trpc/client"; | ||
import { AnyRouter, ProcedureType } from "@trpc/server"; | ||
import { createRecursiveProxy } from "@trpc/server/shared"; | ||
import { createContext } from "react"; | ||
import { DecoratedProcedureRecord } from "./createTRPCNextLayout"; | ||
import superjson from "superjson"; | ||
export type TRPCSchemaContext = Record<string, ProcedureType>; | ||
export const TRPCSchemaContext = createContext<TRPCSchemaContext>(null as any); | ||
export const TRPCSchemaContextProvider = TRPCSchemaContext.Provider; | ||
|
||
export async function createTRPCNextClientLayout< | ||
TRouter extends AnyRouter | ||
>(): Promise<DecoratedProcedureRecord<TRouter["_def"]["record"]>> { | ||
const client = createTRPCClient({ | ||
links: [httpBatchLink({ url: "/api/trpc" })], | ||
transformer: superjson, | ||
}); | ||
|
||
return createRecursiveProxy((callOpts) => { | ||
const path = [...callOpts.path]; | ||
path.pop(); | ||
const flatPath = path.join("."); | ||
// const schema = useContext(TRPCSchemaContext); | ||
// const procedureType = schema[flatPath]; | ||
|
||
const { data } = useQuery([...path, callOpts.args[0]], () => { | ||
return client.query(flatPath, callOpts.args[0]); | ||
}); | ||
return data; | ||
}) as DecoratedProcedureRecord<TRouter["_def"]["record"]>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { createTRPCNextLayout } from "./createTRPCNextLayout"; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"name": "@trpc/next-layout", | ||
"exports": { | ||
"./client": "./client.ts", | ||
"./server": "./server.ts" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { createTRPCNextLayout as createTRPCNextServerLayout } from "./createTRPCNextLayout"; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,10 +2,15 @@ | |||||
|
||||||
import { useRouter } from "next/navigation"; | ||||||
import { trpc } from "~/client/trpcClient"; | ||||||
import { rsc } from "~/server-rsc/trpc/client"; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm
Suggested change
does this still work? |
||||||
import { Inputs } from "~/shared/utils"; | ||||||
|
||||||
export function CreatePostForm() { | ||||||
const addPost = trpc.post.add.useMutation(); | ||||||
// const a = rsc.health.healthz.use(); | ||||||
|
||||||
const data = rsc.health.healthz.use(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wat, this works? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, see my other comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahhhhhh, I missed that this was imported from the I think this isn't great as you'll have to keep track of which one you're using 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That was a mistake (auto import). |
||||||
console.log(data); | ||||||
|
||||||
const router = useRouter(); | ||||||
|
||||||
|
@@ -36,16 +41,16 @@ export function CreatePostForm() { | |||||
console.error({ cause }, "Failed to add post"); | ||||||
} | ||||||
}} | ||||||
className='space-y-2' | ||||||
className="space-y-2" | ||||||
> | ||||||
<fieldset> | ||||||
<label htmlFor='title' className='label'> | ||||||
<label htmlFor="title" className="label"> | ||||||
Title | ||||||
</label> | ||||||
<input | ||||||
id='title' | ||||||
name='title' | ||||||
type='text' | ||||||
id="title" | ||||||
name="title" | ||||||
type="text" | ||||||
disabled={addPost.isLoading} | ||||||
className={ | ||||||
"input" + (addPost.error?.data?.zod?.title ? " input--error" : "") | ||||||
|
@@ -57,13 +62,13 @@ export function CreatePostForm() { | |||||
</fieldset> | ||||||
|
||||||
<fieldset> | ||||||
<label htmlFor='text' className='label'> | ||||||
<label htmlFor="text" className="label"> | ||||||
Text | ||||||
</label> | ||||||
|
||||||
<textarea | ||||||
id='text' | ||||||
name='text' | ||||||
id="text" | ||||||
name="text" | ||||||
disabled={addPost.isLoading} | ||||||
className={ | ||||||
"input" + (addPost.error?.data?.zod?.text ? " input--error" : "") | ||||||
|
@@ -74,7 +79,7 @@ export function CreatePostForm() { | |||||
)} | ||||||
</fieldset> | ||||||
<fieldset> | ||||||
<input type='submit' disabled={addPost.isLoading} className='button' /> | ||||||
<input type="submit" disabled={addPost.isLoading} className="button" /> | ||||||
{addPost.error && !addPost.error.data?.zod && ( | ||||||
<p style={{ color: "red" }}> | ||||||
{addPost.error.message} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,17 @@ | ||
// @ts-check | ||
|
||
/* eslint-disable @typescript-eslint/no-var-requires */ | ||
const { env } = require('./server/env'); | ||
const { env } = require("./server/env"); | ||
|
||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
experimental: { | ||
appDir: true, | ||
}, | ||
webpack: (config, options) => { | ||
config.experiments = { ...config.experiments, ...{ topLevelAwait: true } }; | ||
return config; | ||
}, | ||
}; | ||
|
||
module.exports = nextConfig | ||
module.exports = nextConfig; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { createTRPCNextClientLayout } from "@trpc/next-layout/client"; | ||
import { AppRouter } from "~/server/routers/_app"; | ||
|
||
export const rsc = await createTRPCNextClientLayout<AppRouter>(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./server"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"exports": { | ||
".": { | ||
"react-server": "./server.ts", | ||
"default": "./client.ts" | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the server I think we'd need some sort of server-link?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wouldn't run on the server.
@trpc/next-layout/server.ts
is the one that runs on server components. Theserver-rsc
directory has apackage.json
with thereact-server
condition to switch between server and client automatically