sachinraja / trpc-playground

playground for running tRPC queries in the browser
MIT License
281 stars 19 forks source link

Next.js 13 app directory route handlers #53

Closed mrsafalpiya closed 8 months ago

mrsafalpiya commented 9 months ago

How do I define the proper route handlers in the Next.js 13 app directory?

sachinraja commented 9 months ago

I think you can use trpc-playground/handlers/fetch

mrsafalpiya commented 9 months ago

I have the following code in src/app/api/trpc-playground/route.ts:

import { fetchHandler } from "trpc-playground/handlers/fetch";
import { appRouter } from "@repo/trpc";

const handler = () =>
  fetchHandler({
    router: appRouter,
    trpcApiEndpoint: "/api/trpc",
    playgroundEndpoint: "/api/trpc-playground",
  });

export { handler as GET, handler as POST };

When accessing /api/trpc-playground in browser I get HTTP Error 500 with the following log in the Next.js console:

 ⨯ Error: No response is returned from route handler '/home/safal/work/web/src/app/api/trpc-playground/route.ts'. Ensure you return a `Response` or a `NextResponse` in all branches of your handler.
    at /home/safal/work/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:62526
 GET /api/trpc-playground 500 in 65ms
JacobWennebro commented 8 months ago

I have the following code in src/app/api/trpc-playground/route.ts:

import { fetchHandler } from "trpc-playground/handlers/fetch";
import { appRouter } from "@repo/trpc";

const handler = () =>
  fetchHandler({
    router: appRouter,
    trpcApiEndpoint: "/api/trpc",
    playgroundEndpoint: "/api/trpc-playground",
  });

export { handler as GET, handler as POST };

When accessing /api/trpc-playground in browser I get HTTP Error 500 with the following log in the Next.js console:

 ⨯ Error: No response is returned from route handler '/home/safal/work/web/src/app/api/trpc-playground/route.ts'. Ensure you return a `Response` or a `NextResponse` in all branches of your handler.
    at /home/safal/work/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:62526
 GET /api/trpc-playground 500 in 65ms

I'm having this same issue

noor-codes commented 8 months ago

I share the same issue and hope for its implementation soon. Switching between backend and frontend disrupts my workflow and productivity. I prefer completing one side before switching, and having a playground is crucial for me.

MatsDK commented 8 months ago

Hi, sorry for the late response. But after trying, I managed to get this working by doing this:

// src/app/api/trpc-playground/route.ts
import { appRouter } from "@/server";
import { fetchHandler } from "trpc-playground/handlers/fetch";

const handler = await fetchHandler({
    router: appRouter,
    trpcApiEndpoint: "/api/trpc",
    playgroundEndpoint: "/api/trpc-playground",
});

export { handler as GET, handler as POST };

This might give you a TypeScript error because top-level await is not supported in ES5. You can change the target in your tsconfig.json or just ignore the error.

mrsafalpiya commented 8 months ago

Hi, sorry for the late response. But after trying, I managed to get this working by doing this:

// src/app/api/trpc-playground/route.ts
import { appRouter } from "@/server";
import { fetchHandler } from "trpc-playground/handlers/fetch";

const handler = await fetchHandler({
    router: appRouter,
    trpcApiEndpoint: "/api/trpc",
    playgroundEndpoint: "/api/trpc-playground",
});

export { handler as GET, handler as POST };

This might give you a TypeScript error because top-level await is not supported in ES5. You can change the target in your tsconfig.json or just ignore the error.

Thanks! This was it.

nickplee commented 7 months ago

Here's what I did to avoid the top-level await:

import router from '< your router >';
import { TRPCError } from '@trpc/server';
import { type NextRequest } from 'next/server';
import { fetchHandler } from 'trpc-playground/handlers/fetch';

const PLAYGROUND_ENABLED =
  process.env.ENABLE_TRPC_PLAYGROUND?.toLowerCase() === 'true';

const handlerPromise = fetchHandler({
  playgroundEndpoint: '/api',
  router,
  trpcApiEndpoint: '/api',
});

const fn = async (req: NextRequest): Promise<Response> => {
  if (!PLAYGROUND_ENABLED) {
    throw new TRPCError({
      code: 'FORBIDDEN',
    });
  }

  const handler = await handlerPromise;
  return handler(req);
};

export { fn as GET, fn as POST };