Skip to content

Commit

Permalink
feat: skip http for trpc rsc calls (t3-oss#1670)
Browse files Browse the repository at this point in the history
  • Loading branch information
juliusmarminge committed Nov 21, 2023
1 parent 43cc10b commit 32e0747
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 139 deletions.
5 changes: 5 additions & 0 deletions .changeset/slimy-monkeys-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-t3-app": minor
---

feat: trpc server caller without http
1 change: 1 addition & 0 deletions cli/src/installers/dependencyVersionMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ export const dependencyVersionMap = {
"@trpc/next": "^10.43.6",
"@tanstack/react-query": "^4.36.1",
superjson: "^2.2.1",
"server-only": "^0.0.1",
} as const;
export type AvailableDependencies = keyof typeof dependencyVersionMap;
6 changes: 6 additions & 0 deletions cli/src/installers/trpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ export const trpcInstaller: Installer = ({
];

if (appRouter) {
addPackageDependency({
dependencies: ["server-only"],
devMode: false,
projectDir,
});

const trpcDir = path.join(extrasDir, "src/trpc");
copySrcDest.push(
[
Expand Down
1 change: 1 addition & 0 deletions cli/template/base/_eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const config = {
},
],
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
"@typescript-eslint/require-await": "off",
"@typescript-eslint/no-misused-promises": [
"error",
{
Expand Down
12 changes: 11 additions & 1 deletion cli/template/extras/src/app/api/trpc/[trpc]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@ import { env } from "~/env";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";

/**
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a HTTP request (e.g. when you make requests from Client Components).
*/
const createContext = async (req: NextRequest) => {
return createTRPCContext({
headers: req.headers,
});
};

const handler = (req: NextRequest) =>
fetchRequestHandler({
endpoint: "/api/trpc",
req,
router: appRouter,
createContext: () => createTRPCContext({ req }),
createContext: () => createContext(req),
onError:
env.NODE_ENV === "development"
? ({ path, error }) => {
Expand Down
36 changes: 5 additions & 31 deletions cli/template/extras/src/server/api/trpc-app/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* need to use are documented accordingly near the end.
*/
import { initTRPC } from "@trpc/server";
import { type NextRequest } from "next/server";
import superjson from "superjson";
import { ZodError } from "zod";

Expand All @@ -17,50 +16,25 @@ import { ZodError } from "zod";
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/

interface CreateContextOptions {
headers: Headers;
}

/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
* @see https://trpc.io/docs/server/context
*/
export const createInnerTRPCContext = (opts: CreateContextOptions) => {
export const createTRPCContext = async (opts: { headers: Headers }) => {
return {
headers: opts.headers,
...opts,
};
};

/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = (opts: { req: NextRequest }) => {
// Fetch stuff that depends on the request

return createInnerTRPCContext({
headers: opts.req.headers,
});
};

/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/

const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
Expand Down
38 changes: 6 additions & 32 deletions cli/template/extras/src/server/api/trpc-app/with-auth-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*/

import { initTRPC, TRPCError } from "@trpc/server";
import { type NextRequest } from "next/server";
import superjson from "superjson";
import { ZodError } from "zod";

Expand All @@ -21,54 +20,29 @@ import { db } from "~/server/db";
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/

interface CreateContextOptions {
headers: Headers;
}

/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
* @see https://trpc.io/docs/server/context
*/
export const createInnerTRPCContext = async (opts: CreateContextOptions) => {
export const createTRPCContext = async (opts: { headers: Headers }) => {
const session = await getServerAuthSession();

return {
session,
headers: opts.headers,
db,
session,
...opts,
};
};

/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = async (opts: { req: NextRequest }) => {
// Fetch stuff that depends on the request

return await createInnerTRPCContext({
headers: opts.req.headers,
});
};

/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/

const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
Expand Down
36 changes: 5 additions & 31 deletions cli/template/extras/src/server/api/trpc-app/with-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* need to use are documented accordingly near the end.
*/
import { initTRPC, TRPCError } from "@trpc/server";
import { type NextRequest } from "next/server";
import superjson from "superjson";
import { ZodError } from "zod";

Expand All @@ -19,53 +18,28 @@ import { getServerAuthSession } from "~/server/auth";
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/

interface CreateContextOptions {
headers: Headers;
}

/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
* @see https://trpc.io/docs/server/context
*/
export const createInnerTRPCContext = async (opts: CreateContextOptions) => {
export const createTRPCContext = async (opts: { headers: Headers }) => {
const session = await getServerAuthSession();

return {
session,
headers: opts.headers,
...opts,
};
};

/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = async (opts: { req: NextRequest }) => {
// Fetch stuff that depends on the request

return await createInnerTRPCContext({
headers: opts.req.headers,
});
};

/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/

const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
Expand Down
36 changes: 5 additions & 31 deletions cli/template/extras/src/server/api/trpc-app/with-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* need to use are documented accordingly near the end.
*/
import { initTRPC } from "@trpc/server";
import { type NextRequest } from "next/server";
import superjson from "superjson";
import { ZodError } from "zod";

Expand All @@ -19,51 +18,26 @@ import { db } from "~/server/db";
* This section defines the "contexts" that are available in the backend API.
*
* These allow you to access things when processing a request, like the database, the session, etc.
*/

interface CreateContextOptions {
headers: Headers;
}

/**
* This helper generates the "internals" for a tRPC context. If you need to use it, you can export
* it from here.
*
* Examples of things you may need it for:
* - testing, so we don't have to mock Next.js' req/res
* - tRPC's `createSSGHelpers`, where we don't have req/res
* This helper generates the "internals" for a tRPC context. The API handler and RSC clients each
* wrap this and provides the required context.
*
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
* @see https://trpc.io/docs/server/context
*/
export const createInnerTRPCContext = (opts: CreateContextOptions) => {
export const createTRPCContext = async (opts: { headers: Headers }) => {
return {
headers: opts.headers,
db,
...opts,
};
};

/**
* This is the actual context you will use in your router. It will be used to process every request
* that goes through your tRPC endpoint.
*
* @see https://trpc.io/docs/context
*/
export const createTRPCContext = (opts: { req: NextRequest }) => {
// Fetch stuff that depends on the request

return createInnerTRPCContext({
headers: opts.req.headers,
});
};

/**
* 2. INITIALIZATION
*
* This is where the tRPC API is initialized, connecting the context and transformer. We also parse
* ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
* errors on the backend.
*/

const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
Expand Down
Loading

0 comments on commit 32e0747

Please sign in to comment.