Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are there plans to support the new Route Handlers API? #220

Open
jmikrut opened this issue Mar 16, 2023 · 14 comments
Open

Are there plans to support the new Route Handlers API? #220

jmikrut opened this issue Mar 16, 2023 · 14 comments

Comments

@jmikrut
Copy link

jmikrut commented Mar 16, 2023

Hey there - just found this package and it looks amazing.

Question - are there any plans to support the new route handlers API? Reviewing the documentation, it seems like there will be some incompatibilities as of now. But maybe they could be solved.

Thanks in advance!

@volnei
Copy link

volnei commented Mar 28, 2023

up

@Nicolab
Copy link

Nicolab commented Apr 24, 2023

Please, any news?

@hoangvvo
Copy link
Owner

The new route handler can almost replace this lib. However, it should still work if you use this if you want to take advantage of this lib's middleware setup.

const router = createEdgeRouter<NextRequest, NextFetchEvent>();
router.use(this);
router.use(that);
router.get(something);
router.post(something);

export async function GET(...params) {
  return router.run(...params);
}

export async function POST(...params) {
  return router.run(...params);
}

@volnei
Copy link

volnei commented Apr 24, 2023

Just curious, why the new route handler replaces this lib? How can I get the advantage of intercepting handlers?

@Nicolab
Copy link

Nicolab commented Apr 24, 2023

Thank you for your reply @hoangvvo

In fact it is to use passport.js which integrates as Express.js middleware. I haven't found a way to make it work directly in Next 13 (app folder). I'm hopeful it will work with next-connect.

By the way, good question from @volnei

@cordial
Copy link

cordial commented Apr 24, 2023

Thank you for your reply @hoangvvo

In fact it is to use passport.js which integrates as Express.js middleware. I haven't found a way to make it work directly in Next 13 (app folder). I'm hopeful it will work with next-connect.

By the way, good question from @volnei

I am also using passport/magic link and the bedrock framework which uses next-connect. @hoangvvo can you provide more details on how it can be 'almost' replaced? What part can't?

@volnei
Copy link

volnei commented Apr 24, 2023

@Nicolab,

Currently I'm using a proprietary solution to intercepting routes by creating an wrapper that do everything I need.

I just supose that it can help you with passport also.

Something like:

export function intercept(init: InteceptInit): (request: NextRequest, { params }?: any) => Promise<NextResponse> {
    return async function (request: NextRequest, { params }: any): Promise<NextResponse> {
        try {
            // resolve authentication (proprietary) from request.
            let auth = await resolve(request)
            if (init.secure && auth instanceof Anonymous) throw new AuthError(401, 'Not authenticated')

            // parse request input using Zod
            let body = await request.json().catch((e) => {})
            let parsed
            if (init.schema) {
                parsed = await init.schema.parseAsync({
                    params,
                    search: Object.fromEntries(new URL(request.url).searchParams.entries()),
                    body,
                })
            }
            // get a DB connections
            let db = await connect()
            return await init.handler({ request, parsed, auth, db })
        } catch (error) {
            if (error instanceof ZodError) return new ZodErrorHandler().handle(error)
            if (error instanceof AuthError) return new AuthErrorHandler().handle(error)
            return new InternalServerErrorHandler().handle(error as Error)
        }
    }
}

and

export const GET = intercept({
      handler: async () => {
          // api handler
      },
      schema: z.object({}) // my Zod schema,
      secure: true | false // if it required authentication or not
})

@jmikrut
Copy link
Author

jmikrut commented Apr 24, 2023

For me, the biggest inconsistency / expected trouble using this package in the app folder comes from the fact that the NextRequest / NextResponse are now quite a bit different from the typical Express-like req / res.

For example, headers are no longer able to be set via res.setHeader. Lots of existing Express middlewares are written expecting Express-like req / res and are broken no matter what I tried to do on my own in the app folder.

I will attempt to follow the instructions @hoangvvo has mentioned. We are interested in using this package to deploy Payload within a Next app seamlessly.

We are using Passport and many other Express middlewares, and so I don't think the app folder on its own can replace this package for us.

@hoangvvo
Copy link
Owner

For me, the biggest inconsistency / expected trouble using this package in the app folder comes from the fact that the NextRequest / NextResponse are now quite a bit different from the typical Express-like req / res.

For example, headers are no longer able to be set via res.setHeader. Lots of existing Express middlewares are written expecting Express-like req / res and are broken no matter what I tried to do on my own in the app folder.

I will attempt to follow the instructions @hoangvvo has mentioned. We are interested in using this package to deploy Payload within a Next app seamlessly.

We are using Passport and many other Express middlewares, and so I don't think the app folder on its own can replace this package for us.

I see. I think a shim package to make express middleware compatible with the new NextRequest instance would be interesting. I will look into it.

@jmikrut
Copy link
Author

jmikrut commented Apr 28, 2023

@hoangvvo you are a boss. If you are interested in this work, Payload will happily sponsor you!

@slongdotexe
Copy link

slongdotexe commented Apr 29, 2023

I've recently been working on something very much in the direction of @volnee's implementation. A high-level overview is that we'd implement a similar function pattern as above with a range of config options like Zod (probably other validation libraries over time) validation schemas, auth callback's for protected routes, middleware and other nice to haves like onErrorHandlers etc.

So far I've been able to successfully pass the types from the Zod Schemas into a context object that the router handler itself receives as a parameter. Hoping the below snippet of the function being utilised provides a little more context.

import { UserClass } from "lib";
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";

import { withRequestContext } from "../../factories/api";

const postQueryVal = z.object({
  lang: z.enum(["en", "es", "fr"]).default("en"),
});

type PostQueryVal = z.infer<typeof postQueryVal>;

export const POST = withRequestContext(
  {
    validation: {
      query: postQueryVal,
    },
  },
  async (request, ctx) => {
    // Will be handled by the provided validation object and be defaulted / processed as defined in the schema
    console.log(ctx.query.lang);
    // Body validation not provided, so type of body is assumed to be never
    console.log(ctx.body.foo);
    return NextResponse.json({ hello: "world" });
  }
);

export type { PostQueryVal };

I'm thinking I'll push the code to a repo once I've added in the relevant logic to receive callbacks for validating auth on protected routes as well as middleware functions. Would anyone be interested in collaborating on something like that?

@thgh
Copy link

thgh commented Jul 11, 2023

Would anyone like to try handleNextRequest from #232 ? (just copy the app-route.ts file to your project and run it like this:

// src/app/[[...rest]]/route.ts

import express from 'express'
import payload from 'payload'
import { AppRouteRequestHandler, handleNextRequest } from './app-route'

const app = express()
app.get(...)

export const GET: AppRouteRequestHandler = (req) => handleNextRequest(req, app)

@ziponia
Copy link

ziponia commented Sep 10, 2024

@Nicolab,

Currently I'm using a proprietary solution to intercepting routes by creating an wrapper that do everything I need.

I just supose that it can help you with passport also.

Something like:

export function intercept(init: InteceptInit): (request: NextRequest, { params }?: any) => Promise<NextResponse> {
    return async function (request: NextRequest, { params }: any): Promise<NextResponse> {
        try {
            // resolve authentication (proprietary) from request.
            let auth = await resolve(request)
            if (init.secure && auth instanceof Anonymous) throw new AuthError(401, 'Not authenticated')

            // parse request input using Zod
            let body = await request.json().catch((e) => {})
            let parsed
            if (init.schema) {
                parsed = await init.schema.parseAsync({
                    params,
                    search: Object.fromEntries(new URL(request.url).searchParams.entries()),
                    body,
                })
            }
            // get a DB connections
            let db = await connect()
            return await init.handler({ request, parsed, auth, db })
        } catch (error) {
            if (error instanceof ZodError) return new ZodErrorHandler().handle(error)
            if (error instanceof AuthError) return new AuthErrorHandler().handle(error)
            return new InternalServerErrorHandler().handle(error as Error)
        }
    }
}

and

export const GET = intercept({
      handler: async () => {
          // api handler
      },
      schema: z.object({}) // my Zod schema,
      secure: true | false // if it required authentication or not
})

ohh.....

It's such a wonderful model!!

It would be nice if the secure method could be a function that contains context.

Is there any possibility of adoption?

It's so annoying to use route.ts in 'appdir'

@Nicolab
Copy link

Nicolab commented Dec 26, 2024

@volnei Oh, I didn't see your great answer!
Thanks, fortunately it has been useful to many people.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants