Server Side Calls
You may need to call your procedure(s) directly from the server, createCaller()
function returns you an instance of RouterCaller
able to execute queries and mutations.
Create caller
With the router.createCaller({})
function (first argument is Context
) we retrieve an instance of RouterCaller
.
Input query example
We create the router with a input query and then we call the asynchronous greeting
procedure to get the result.
ts
import {initTRPC } from '@trpc/server';import {z } from 'zod';constt =initTRPC .create ();constrouter =t .router ({// Create procedure at path 'greeting'greeting :t .procedure .input (z .object ({name :z .string () })).query (({input }) => `Hello ${input .name }`),});constcaller =router .createCaller ({});constresult = awaitcaller .greeting ({name : 'tRPC' });
ts
import {initTRPC } from '@trpc/server';import {z } from 'zod';constt =initTRPC .create ();constrouter =t .router ({// Create procedure at path 'greeting'greeting :t .procedure .input (z .object ({name :z .string () })).query (({input }) => `Hello ${input .name }`),});constcaller =router .createCaller ({});constresult = awaitcaller .greeting ({name : 'tRPC' });
Mutation example
We create the router with a mutation and then we call the asynchronous post
procedure to get the result.
ts
import {initTRPC } from '@trpc/server';import {z } from 'zod';constposts = ['One', 'Two', 'Three'];constt =initTRPC .create ();constrouter =t .router ({post :t .router ({add :t .procedure .input (z .string ()).mutation (({input }) => {posts .push (input );returnposts ;}),}),});constcaller =router .createCaller ({});constresult = awaitcaller .post .add ('Four');
ts
import {initTRPC } from '@trpc/server';import {z } from 'zod';constposts = ['One', 'Two', 'Three'];constt =initTRPC .create ();constrouter =t .router ({post :t .router ({add :t .procedure .input (z .string ()).mutation (({input }) => {posts .push (input );returnposts ;}),}),});constcaller =router .createCaller ({});constresult = awaitcaller .post .add ('Four');
Context with middleware example
We create a middleware to check the context before execute secret
procedure.
Below two examples, the former fails because the context doesn't fit the middleware logic the latter works correctly.
Middlewares are performed before any procedure(s) are called.
ts
import {TRPCError ,initTRPC } from '@trpc/server';typeContext = {user ?: {id : string;};};constt =initTRPC .context <Context >().create ();constisAuthed =t .middleware (({next ,ctx }) => {if (!ctx .user ) {throw newTRPCError ({code : 'UNAUTHORIZED',message : 'You are not authorized',});}returnnext ({ctx : {// Infers that the `user` is non-nullableuser :ctx .user ,},});});constprotectedProcedure =t .procedure .use (isAuthed );constrouter =t .router ({secret :protectedProcedure .query (({ctx }) =>ctx .user ),});{// ❌ this will return an error because there isn't the right context paramconstcaller =router .createCaller ({});constresult = awaitcaller .secret ();}{// ✅ this will work because user property is present inside context paramconstauthorizedCaller =router .createCaller ({user : {id : 'KATT',},});constresult = awaitauthorizedCaller .secret ();}
ts
import {TRPCError ,initTRPC } from '@trpc/server';typeContext = {user ?: {id : string;};};constt =initTRPC .context <Context >().create ();constisAuthed =t .middleware (({next ,ctx }) => {if (!ctx .user ) {throw newTRPCError ({code : 'UNAUTHORIZED',message : 'You are not authorized',});}returnnext ({ctx : {// Infers that the `user` is non-nullableuser :ctx .user ,},});});constprotectedProcedure =t .procedure .use (isAuthed );constrouter =t .router ({secret :protectedProcedure .query (({ctx }) =>ctx .user ),});{// ❌ this will return an error because there isn't the right context paramconstcaller =router .createCaller ({});constresult = awaitcaller .secret ();}{// ✅ this will work because user property is present inside context paramconstauthorizedCaller =router .createCaller ({user : {id : 'KATT',},});constresult = awaitauthorizedCaller .secret ();}