instantcommerce / next-api-decorators

Collection of decorators to create typed Next.js API routes, with easy request validation and transformation.
https://next-api-decorators.vercel.app
MIT License
409 stars 29 forks source link

Not understanding how to structure API files using this library #559

Closed alaughlin closed 1 year ago

alaughlin commented 1 year ago

Apologies if this maybe more related to NextJS itself, but I am struggling understanding how to get routing properly working using this library.

Here's what src/pages/api/address/[[...params]].ts looks like:

class AddressHandler {
    @Post('/:userId')
    create(
        @Param('userId') userId: string,
        @Body() address: Address
    ): Promise<Address> {
        return this.addressService.createAddress(address, userId);
    }

    @Patch('/:userId')
    updateAddress(
        @Param('userId') userId: string,
        @Body() address: Partial<Address>,
    ): Promise<Address> {
        return this.addressService.updateAddress(address, userId);
    }
}

export default createHandler(AddressHandler);

And when I try to POST some data to /api/address/randomUserId, it gives back a 404. I suspect I might have not structured my files correctly, is there something I am missing here?

jacekjagiello commented 1 year ago

The route matching depends on path-to-regexp package, make sure you have it installed.

alaughlin commented 1 year ago

@jacekjagiello I have the path-to-regexp package installed. Does it need to be imported anywhere first?

alaughlin commented 1 year ago

ok, things seem to be really confusing and not working as intended. I attempted to take the example from here: https://next-api-decorators.vercel.app/docs/routing/route-matching and use it in my own project as a sanity check, and it's not working.

src/pages/api/user/[[...params]].ts

import { createHandler, Get, Param } from 'next-api-decorators';

class UserHandler {
    @Get()
    public list() {
        return 'GET /';
    }

    @Get('/:id')
    public details(@Param('id') id: string) {
        return `GET /${id}`;
    }

    @Get('/:userId/comments')
    public comments(@Param('userId') userId: string) {
        return `GET /${userId}/comments`;
    }

    @Get('/:userId/comments/:commentId')
    public commentDetails(@Param('userId') userId: string, @Param('commentId') commentId: string) {
        return `GET /${userId}/comments/${commentId}`;
    }
}

export default createHandler(UserHandler);

If I GET any route under /api/user it seems to always match the first GET() and invoke list():

GET /api/user -> returns 'GET /'
GET /api/user/1 -> returns 'GET /'
GET /api/user/1/comments -> returns 'GET /'
GET /api/user/1/comments/1 -> returns 'GET /'

If I disable the first route, attempting to hit any of the nested routes results in a 404. Am I missing something here, or is something actually broken?

ggurkal commented 1 year ago

Hi @alaughlin

Can't replicate the issue you're having. Please provide a minimum reproducible repo.

alaughlin commented 1 year ago

I figured out the issue. My project was part of a monorepo that also had a nestjs project, which included its own version of path-to-regexp and was somehow conflicting with the one required by next-api-decorators. I actually didn't need that project anymore so removing it solved the problem.