Reputation: 1
I created a new project with npm create-t3-app@latest
with trpc, typescript, tailwind, prisma, and clerk. The newest version invokes a caller function to create two api
definitions, one for the server and one for the client.
By default, it includes a publicProcedure
definition, I want to create a privateProcedure
which checks for authentication with clerk, meaning auth needs to be included in the context. So the change needs to be made to the create context function.
Here's what comes out of the box with create-t3-app
:
// ./src/server/api/trpc.ts
export const createTRPCContext = async (opts: { headers: Headers }) => {
return {
db,
...opts,
};
};
Here is what I thought I would be able to do to update it:
import { getAuth } from "@clerk/nextjs/server";
...
export const createTRPCContext = async (opts: { headers: Headers }) => {
const { userId } = getAuth(opts.headers);
return {
db,
userId,
...opts,
};
};
...
export const privateProcedure = t.procedure.use(async ({ ctx, next }) => {
if (!ctx.userId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You must be logged in to perform this action",
});
}
return next({
ctx: {
...ctx,
userId: ctx.userId,
},
});
});
The problem is, Typescript tells me the argument of type 'Headers' is not assignable to the type 'RequestLike'. To fix this I updated the type.
import type * as trpcNext from "@trpc/server/adapters/next";
...
export const createTRPCContext = async (opts: trpcNext.CreateNextContextOptions) => {
const { userId } = getAuth(opts.req);
return {
db,
userId,
...opts,
};
};
This works, but now the server-side api
definition is not happy. I am not sure how to fix it because I'm a little fuzzy on what exactly is going on in this definition anyhow.
// ./src/trpc/server.ts
import "server-only";
import { headers } from "next/headers";
import { cache } from "react";
import { createCaller } 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 tRPC call from a React Server Component.
*/
const createContext = cache(() => {
const heads = new Headers(headers());
heads.set("x-trpc-source", "rsc");
return createTRPCContext({
headers: heads,
});
});
export const api = createCaller(createContext);
The typescript error of course is in the invocation of createTRPCContext
, which no longer expects the same type of input.
Upvotes: 0
Views: 277
Reputation: 1
I ran into the same thing and was similarly confused at first.
if you look at https://trpc.io/docs/server/context they have a section on "inner and outer context" and it looks like create-t3-app
is ~sort of~ following this by having a createContext
in src/trpc/server
and another in api/trpc/[trpc]/route.ts
where the one in route.ts
would be the "outer" context where req is available. So, in order to add a protected/private procedure, you'll want to follow the pattern from the trpc docs and either adapt it to ct3a's structure, or just change your app's structure to match the docs.
I went with the latter, defining an inner context creator, and updating the type passed to initTRPC
to use the type of my inner context, and then using my inner context in trpc/server.ts
and outer context in api/trpc/[trpc]/route.ts
hope that's helpful!
Upvotes: 0