TkDodo 🔮
TkDodo 🔮3y ago

calling trpc endpoints from vanilla nextJs api routes

I'm struggling to find what's the best way to call a trpc endpoint directly from the server. Basically, I have a nextjs api endpoint where I want to call another endpoin that lives in trpc. would I need to create a trpcProxyClient? If so, would it have access to the context?
18 Replies
TkDodo 🔮
TkDodo 🔮OP3y ago
oh, would I want something like this? https://github.com/trpc/trpc/issues/1724 appRouter.createCaller ?
GitHub
tRPC to OpenAPI generator · Issue #1724 · trpc/trpc
Note: I do not want to have this as part of the library itself, but an example would be good Overview With the addition of output parser (#1699), we should now have all the pieces to automatically ...
julius
julius3y ago
yes appRouter.createCaller is what you want
julius
julius3y ago
Server Side Calls | tRPC
You may need to call your procedure(s) directly from the server, createCaller() function returns you an instance of RouterCaller able to execute query(ies) and mutation(s).
TkDodo 🔮
TkDodo 🔮OP3y ago
Yep, this works. Thanks a lot ❤️ related follow-up question @julius : when I make a server-side call, and it errors (e.g. because of a zod validation error), I get a TRPCError. That has a code, which is a string and it says BAD_REQUEST. Is there a way to translate this to a proper status code like 400 in this case? Right now, all these errors are sent as 500 errors to the frontend and this is kinda suboptimal imo. Thanks 🙏
julius
julius3y ago
you might be able to by using a non-public function that grabs the code for you. not sure why we aren't exporting it publically 🤔 should we @alex / KATT?
import { TRPCError } from '@trpc/server';
import { getHTTPStatusCodeFromError } from '@trpc/server/src/http/internals/getHTTPStatusCode';
import { type NextApiRequest, type NextApiResponse } from 'next';
import { appRouter } from './trpc/[trpc]';

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const caller = appRouter.createCaller({});

try {
const result = await caller.greeting({ name: 2 });
res.status(200).json(result);
} catch (e) {
console.error(e);
const code = e instanceof TRPCError ? getHTTPStatusCodeFromError(e) : 500;
res.status(code).json({ error: e });
}
};

export default handler;
import { TRPCError } from '@trpc/server';
import { getHTTPStatusCodeFromError } from '@trpc/server/src/http/internals/getHTTPStatusCode';
import { type NextApiRequest, type NextApiResponse } from 'next';
import { appRouter } from './trpc/[trpc]';

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const caller = appRouter.createCaller({});

try {
const result = await caller.greeting({ name: 2 });
res.status(200).json(result);
} catch (e) {
console.error(e);
const code = e instanceof TRPCError ? getHTTPStatusCodeFromError(e) : 500;
res.status(code).json({ error: e });
}
};

export default handler;
TkDodo 🔮
TkDodo 🔮OP3y ago
getHTTPStatusCodeFromError would be sweet, I have now made my own mapping according to this table: https://trpc.io/docs/v9/error-handling#error-codes I don't really understand: why does TrpcClientError have a statusCode property, but TrpcError does not?
Alex / KATT 🐱
happy to expose that!
julius
julius3y ago
I was thinking, maybe calls made from createCaller should automatically return the status code? Given that its a server call you’d likely want the statuscode either way?
Alex / KATT 🐱
the trpc error that is returns will have the error code i don't want the status codes b/c that is a HTTP-standard and trpc isn't tied to http
Alex / KATT 🐱
I have this copy-pasted in an /api-fn helper so i would definitely use this functionality myself
TkDodo 🔮
TkDodo 🔮OP3y ago
Fine by me, let's expose the helper then?
TkDodo 🔮
TkDodo 🔮OP3y ago
Thx for merging ❤️
julius
julius3y ago
Needs a publish too, shöuldnt take too long. tRPC moving fast ⚡️☺️
TkDodo 🔮
TkDodo 🔮OP3y ago
And breaks nothing 😉
Unknown User
Unknown User3y ago
Message Not Public
Sign In & Join Server To View
Trader Launchpad
HI! I am wanting to do the same thing...call a trpc route from within a nextjs public api endpoint. I am using a fresh t3-turbo-with-clerk project which has trpc in packages/api (@acme/api) here is my apps/nextjs/src/pages/api/post.ts file
import { NextApiRequest, NextApiResponse } from "next";
import { appRouter } from "@acme/api";
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
import { TRPCError } from "@trpc/server";

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const caller = appRouter.createCaller({});

try {
const result = await caller.post.all();
res.status(200).json(result);
} catch (e) {
console.error(e);
const code = e instanceof TRPCError ? getHTTPStatusCodeFromError(e) : 500;
res.status(code).json({ error: e });
}
};

export default handler;
import { NextApiRequest, NextApiResponse } from "next";
import { appRouter } from "@acme/api";
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
import { TRPCError } from "@trpc/server";

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const caller = appRouter.createCaller({});

try {
const result = await caller.post.all();
res.status(200).json(result);
} catch (e) {
console.error(e);
const code = e instanceof TRPCError ? getHTTPStatusCodeFromError(e) : 500;
res.status(code).json({ error: e });
}
};

export default handler;
i am getting a type error on
const caller = appRouter.createCaller({});
const caller = appRouter.createCaller({});
Argument of type '{}' is not assignable to parameter of type '{ auth: SignedInAuthObject | SignedOutAuthObject; prisma: PrismaClient<Prisma.PrismaClientOptions, never, Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined>; }'.
Argument of type '{}' is not assignable to parameter of type '{ auth: SignedInAuthObject | SignedOutAuthObject; prisma: PrismaClient<Prisma.PrismaClientOptions, never, Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined>; }'.
and when i load the page i get a json error:
{"error":{"code":"INTERNAL_SERVER_ERROR","name":"TRPCError"}}
{"error":{"code":"INTERNAL_SERVER_ERROR","name":"TRPCError"}}
Can someone assist me with the issue? I know I could use https://github.com/jlalmes/trpc-openapi to expose routes, I just wanted to get a basic example working first and then look into that. I am only exposing routes atm for testing purposes
Nick
Nick2y ago
@Trader Launchpad this is an ancient thread, please could you start a new one? 🙂