Context
Your context holds data that all of your tRPC procedures will have access to, and is a great place to put things like database connections or authentication information.
Setting up the context is done in 2 steps, defining the type during initialization and then creating the runtime context for each request.
Defining the context type
When initializing tRPC using initTRPC, you should pipe .context<TContext>() to the initTRPC builder function before calling .create(). The type TContext can either be inferred from a function's return type or be explicitly defined.
This will make sure your context is properly typed in your procedures and middlewares.
tsinitTRPC } from '@trpc/server';import type {CreateNextContextOptions } from '@trpc/server/adapters/next';import {getSession } from 'next-auth/react';export constcreateContext = async (opts :CreateNextContextOptions ) => {constsession = awaitgetSession ({req :opts .req });return {session ,};};constt1 =initTRPC .context <typeofcreateContext >().create ();t1 .procedure .use (({ctx }) => { ... });typeContext =Awaited <ReturnType <typeofcreateContext >>;constt2 =initTRPC .context <Context >().create ();t2 .procedure .use (({ctx }) => { ... });
tsinitTRPC } from '@trpc/server';import type {CreateNextContextOptions } from '@trpc/server/adapters/next';import {getSession } from 'next-auth/react';export constcreateContext = async (opts :CreateNextContextOptions ) => {constsession = awaitgetSession ({req :opts .req });return {session ,};};constt1 =initTRPC .context <typeofcreateContext >().create ();t1 .procedure .use (({ctx }) => { ... });typeContext =Awaited <ReturnType <typeofcreateContext >>;constt2 =initTRPC .context <Context >().create ();t2 .procedure .use (({ctx }) => { ... });
Creating the context
The createContext() function must be passed to the handler that is mounting your appRouter, which may be via HTTP, a server-side call or our server-side helpers.
createContext() is called for each invocation of tRPC, so batched requests will share a context.
ts
ts
ts
ts
ts
ts
Example code
tsxCreateNextContextOptions } from '@trpc/server/adapters/next';import {getSession } from 'next-auth/react';/*** Creates context for an incoming request* @link https://trpc.io/docs/context*/export async functioncreateContext (opts :CreateNextContextOptions ) {constsession = awaitgetSession ({req :opts .req });return {session ,};}export typeContext =Awaited <ReturnType <typeofcreateContext >>;// -------------------------------------------------// @filename: trpc.ts// -------------------------------------------------import {initTRPC ,TRPCError } from '@trpc/server';import {Context } from './context';constt =initTRPC .context <Context >().create ();export constrouter =t .router ;/*** Unprotected procedure*/export constpublicProcedure =t .procedure ;/*** Protected procedure*/export constprotectedProcedure =t .procedure .use (functionisAuthed (opts ) {if (!opts .ctx .session ?.user ?.throw newTRPCError ({code : 'UNAUTHORIZED',});}returnopts .next ({ctx : {// Infers the `session` as non-nullablesession :opts .ctx .session ,},});});
tsxCreateNextContextOptions } from '@trpc/server/adapters/next';import {getSession } from 'next-auth/react';/*** Creates context for an incoming request* @link https://trpc.io/docs/context*/export async functioncreateContext (opts :CreateNextContextOptions ) {constsession = awaitgetSession ({req :opts .req });return {session ,};}export typeContext =Awaited <ReturnType <typeofcreateContext >>;// -------------------------------------------------// @filename: trpc.ts// -------------------------------------------------import {initTRPC ,TRPCError } from '@trpc/server';import {Context } from './context';constt =initTRPC .context <Context >().create ();export constrouter =t .router ;/*** Unprotected procedure*/export constpublicProcedure =t .procedure ;/*** Protected procedure*/export constprotectedProcedure =t .procedure .use (functionisAuthed (opts ) {if (!opts .ctx .session ?.user ?.throw newTRPCError ({code : 'UNAUTHORIZED',});}returnopts .next ({ctx : {// Infers the `session` as non-nullablesession :opts .ctx .session ,},});});
Inner and outer context
In some scenarios it could make sense to split up your context into "inner" and "outer" functions.
Inner context is where you define context which doesn’t depend on the request, e.g. your database connection. You can use this function for integration testing or server-side helpers, where you don’t have a request object. Whatever is defined here will always be available in your procedures.
Outer context is where you define context which depends on the request, e.g. for the user's session. Whatever is defined here is only available for procedures that are called via HTTP.
Example for inner & outer context
ts
ts
It is important to infer your Context from the inner context, as only what is defined there is really always available in your procedures.
If you don't want to check req or res for undefined in your procedures all the time, you could build a small reusable procedure for that:
ts
ts