thiagobustamante / typescript-rest

This is a lightweight annotation-based expressjs extension for typescript.
MIT License
524 stars 108 forks source link

Proposal: Create @RegisterLast to force endpoints match last #114

Open jojokoro opened 4 years ago

jojokoro commented 4 years ago

As of today you can extend endpoints from a "base" class, which is useful for CRUDs like this example:

export default CRUD {
  @GET
  async readAllEntities() {
    //...
  }

  @POST
  async createEntity() {
    //...
  }

  @Path(':id')
  @GET
  async readEntity() {
    //...
  }

  @Path(':id') 
  @PATCH
  async updateEntity() {
    //...
  }

  @Path(':id') 
  @DELETE
  async deleteEntity() {
    //...
  }
}

And then I can use it on my other endpoints as follows:

@Path('cars')
export class CarsEndpoint extends CRUD {

}

But here comes the issue (related to #96): If I try to create another endpoint specific to CarsEndpoint, e.g.: /cars/featured:

@Path('cars')
export class CarsEndpoint extends CRUD {
  @Path('featured')
  @GET
  async readFeatured() {
    //...
  }
}

The above route will never get executed since we have a route inside CRUD with a param matching GET /cars/:id. So in /cars/featured the featured path will be read as an :id param.

This forces someone who extends endpoints to use not-so-elegant solutions (like putting CRUD endpoints inside a /crud/ path, etc). A nice solution would be enabling a way to force a route only be registered by typescript-rest after all other routes got registered, which prevent this issue.

So by doing this:

export default CRUD {
  @RegisterLast
  @GET
  async readAllEntities() {
    //...
  }

  @RegisterLast
  @POST
  async createEntity() {
    //...
  }

  @RegisterLast
  @Path(':id')
  @GET
  async readEntity() {
    //...
  }

  @RegisterLast
  @Path(':id') 
  @PATCH
  async updateEntity() {
    //...
  }

  @RegisterLast
  @Path(':id') 
  @DELETE
  async deleteEntity() {
    //...
  }
}

We make sure those routes will only execute after all other routes are tried for matching.

What do you think?

Vizzr commented 4 years ago

I also have this problem right now. It would be nice to have some kind of decorator or perhaps a startup option. Saying that it should match the full url or else go into the :id path.