[HOW TO?] Call trpc endpoints from vanilla nextJs api routes

TLTrader Launchpad5/11/2023
Spinoff from an og thread here:
https://discordapp.com/channels/867764511159091230/1032301198990135347

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;
TLTrader Launchpad5/11/2023
i am getting a type error on
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>; }'.
TLTrader Launchpad5/11/2023
and when i load the page i get a json error:
{"error":{"code":"INTERNAL_SERVER_ERROR","name":"TRPCError"}}


Can someone assist me with the issue?
TLTrader Launchpad5/11/2023
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
TLTrader Launchpad5/11/2023
from what I can see, const caller = appRouter.createCaller({}); needs a ctx parameter.

my @acme/api/index.ts file has

export type { AppRouter } from "./src/router";
export { appRouter } from "./src/router";

export { createContext } from "./src/context";
export type { Context } from "./src/context";
Nnlucas5/11/2023
Have you looked at our nextjs docs?
TLTrader Launchpad5/11/2023
Nnlucas5/11/2023
You shouldn't need createCaller
Nnlucas5/11/2023
We have serverside helpers
Nnlucas5/11/2023
Problem looks like you're not actually creating the necessary ctx object
Nnlucas5/11/2023
but you shouldn't need to do it here
TLTrader Launchpad5/11/2023
the documentation explains using createCaller for nextjs api endpoints via that link above. Why wouldnt I need it?

I have used the SSG helper in a pages/post/[id].tsx page, but didnt think that was the correct way to use it in an API route per the trpc documentation
Nnlucas5/11/2023
Got it, I'm not really a user of next, but yes looks like we do recommend that in some situations
Nnlucas5/11/2023
You'll need to call your createContext function
Nnlucas5/11/2023
{} is not enough
TLTrader Launchpad5/11/2023
ok, and in that function it expects some parameters (auth). However isnt the context object already set up inside @acme/api somewhere?

Here is my pages/dashboard page where I load the posts into a flashlist:
import { HomeScreen as FeatureHomeScreen } from "@acme/app/features/home/screen";
import MainLayout from "@acme/app/layouts/MainLayout";
export default function HomeScreen() {
  return <FeatureHomeScreen />;
}
Nnlucas5/11/2023
createContext is called by the adapter, but createCaller makes your calling code into the adapter
Nnlucas5/11/2023
That first parameter is the context values
TLTrader Launchpad5/11/2023
screens are located in packages/app/features (@acme/app) and here is the Homescreen linked from above file

import React from "react";

import { Link } from "solito/link";
import { Button, TouchableOpacity } from "../../design/button";
import { Text } from "../../design/typography";
import { View, SafeAreaView } from "../../design/view";

import type { AppRouter } from "@acme/api";
import type { inferProcedureOutput } from "@trpc/server";

import { trpc } from "../../utils/trpc";
import { FlashList } from "@shopify/flash-list";


export function HomeScreen() {
  const { data: postData, isLoading, error } = trpc.lesson.all.useQuery();
  .........
TLTrader Launchpad5/11/2023
trpc works fine on this page and loads the posts. Do i need to re-import clerk modules on pages/api/post to rebuild context?
TLTrader Launchpad5/11/2023
i would think i could import context from @acme/api, then insert it into createCaller()
TLTrader Launchpad5/11/2023
and yes i do believe context is the issue with my code because of the error:
Argument of type '{}' is not assignable to parameter of type '{ auth: SignedInAuthObject | SignedOutAuthObject; prisma: PrismaClient<Prisma.PrismaClientOptions, never, Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined>; }'.
TLTrader Launchpad5/11/2023
but it is asking for ctx to have auth (clerk) and prisma, which id either have to import again or re-use from @acme/api
TLTrader Launchpad5/11/2023
here is another github I have also been looking at:
https://github.com/trpc/trpc/issues/1724

this is code for the openapi generator that we should be able to pull some code from to assist. This is where I got the understanding that createCaller needs a ctx object and that ceateContext probably needs to be imported...but this is as far as I have got
TLTrader Launchpad5/11/2023
so atm in my pages/api/posts.ts i have (shorted for brevity)

.....
import { createContext } from "@acme/api/";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseData>,
) {
  const { method } = req;

  switch (method) {
    case "GET":
      try {
        const ctx = await createContext({ req, res });
        const caller = appRouter.createCaller({ ctx });
        const data = await caller.post.all();
        console.log(data);
...
TLTrader Launchpad5/11/2023
and I am still getting error
Argument of type '{ ctx: { auth: SignedInAuthObject | SignedOutAuthObject; prisma: PrismaClient<Prisma.PrismaClientOptions, never, Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined>; }; }' is not assignable to parameter of type '{ auth: SignedInAuthObject | SignedOutAuthObject; prisma: PrismaClient<Prisma.PrismaClientOptions, never, Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined>; }'.