Next.js app router with tRPC context and NextAuth

Hi. I'm trying to set up Next 13 with tRPC over a WebSocket and NextAuth. I got it mostly working with:
// route.ts
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
import { createContext } from '@/server/context';
import { appRouter } from '@/server/routers/app';

const handler = (req: Request) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext,
batching: {
enabled: true,
},
});

export { handler as GET, handler as POST };
// route.ts
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
import { createContext } from '@/server/context';
import { appRouter } from '@/server/routers/app';

const handler = (req: Request) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext,
batching: {
enabled: true,
},
});

export { handler as GET, handler as POST };
// context.ts
import * as trpc from '@trpc/server';
import * as trpcNext from '@trpc/server/adapters/fetch';
import { NodeHTTPCreateContextFnOptions } from '@trpc/server/adapters/node-http';
import { IncomingMessage } from 'node:http';
import ws from 'ws';
import { getSession } from 'next-auth/react';

export async function createContext(
opts:
| NodeHTTPCreateContextFnOptions<IncomingMessage, ws>
| trpcNext.FetchCreateContextFnOptions
) {
const req = opts?.req;

const session = req && (await getSession({ req }));

return {
req,
session,
};
}

export type Context = trpc.inferAsyncReturnType<typeof createContext>;
// context.ts
import * as trpc from '@trpc/server';
import * as trpcNext from '@trpc/server/adapters/fetch';
import { NodeHTTPCreateContextFnOptions } from '@trpc/server/adapters/node-http';
import { IncomingMessage } from 'node:http';
import ws from 'ws';
import { getSession } from 'next-auth/react';

export async function createContext(
opts:
| NodeHTTPCreateContextFnOptions<IncomingMessage, ws>
| trpcNext.FetchCreateContextFnOptions
) {
const req = opts?.req;

const session = req && (await getSession({ req }));

return {
req,
session,
};
}

export type Context = trpc.inferAsyncReturnType<typeof createContext>;
4 Replies
Tamás Soós
Tamás Soós8mo ago
and a provider component
Tamás Soós
Tamás Soós8mo ago
My issue is with the createContext call. The opts type isn't quite right. getSession is giving me:
Type 'IncomingMessage | Request' is not assignable to type '(Partial<IncomingMessage> & { body?: any; }) | undefined'.
Type 'Request' is not assignable to type 'Partial<IncomingMessage> & { body?: any; }'.
Type 'Request' is not assignable to type 'Partial<IncomingMessage>'.
Types of property 'headers' are incompatible.
Type 'Headers' is not assignable to type 'IncomingHttpHeaders'.
Index signature for type 'string' is missing in type 'Headers'.ts(2322)
(property) CtxOrReq.req?: (Partial<IncomingMessage> & {
body?: any;
}) | undefined
Type 'IncomingMessage | Request' is not assignable to type '(Partial<IncomingMessage> & { body?: any; }) | undefined'.
Type 'Request' is not assignable to type 'Partial<IncomingMessage> & { body?: any; }'.
Type 'Request' is not assignable to type 'Partial<IncomingMessage>'.
Types of property 'headers' are incompatible.
Type 'Headers' is not assignable to type 'IncomingHttpHeaders'.
Index signature for type 'string' is missing in type 'Headers'.ts(2322)
(property) CtxOrReq.req?: (Partial<IncomingMessage> & {
body?: any;
}) | undefined
even though it happens to be working for now. Btw getSession creates infinite reconnects on the ws client with any other inputs and getServerSession does the same except I couldn't find any arguments that work at all.
alan
alan3mo ago
when using a provider client component, doesn't that make everything from that point on a client component tree, which makes me wonder why even bother switch to the app router if doing that