Howard86 / next-api-handler

lightweight nextjs api handler wrapper, portable & configurable for serverless environment
https://next-api-handler.vercel.app
Other
49 stars 1 forks source link

Typed request body and allow any response #100

Closed gabrielmaldi closed 1 year ago

gabrielmaldi commented 1 year ago

Hi! Thanks for this project. Something I was expecting is to type the request, instead of it being any. Also, to be able to return just the status code or another type different from that of the request.

type User = {
  name: string;
  email: string;
  // many more
};

router.post<User>(async (req) => {
  req.body.email; // OK, body is of type User

  return 200;

  // or

  return {
    myResult: "code_200",
  };
})

Do you see this as something desirable for the builder?

Thanks!

Howard86 commented 1 year ago

Let me reply in different threads.

Something I was expecting is to type the request, instead of it being any

As api request could potentially come from any source in any format, it's safer to apply input validation instead of a declarative type definition.

For example, when req.body looks like {count: 2}, anyone who calls the api can still send {count: "2"} by accident.

Instead, with an example of Zod we could have it in api handler or as a middleware.

For example,

const shema = z.object({count: z.number()})

router.post(req => {
  const result = schema.safeParse(req.body)

  if (!result.success) throw new BadRequestException(JSON.stringify(result.error.format()))

  // now we can safely use `result.data.count` as `number`
})
Howard86 commented 1 year ago

to be able to return just the status code or another type different from that of the request.

Atm I tried to make this api builder as simple as possible by unifying the request response with default status code, so if you want to customise status code, think its quite a straightforward change and feel free to open a PR

Theoretically we don't have to specify the response format if we don't need, i.e. we only need success: true in api response

router.get(req => {
  // something and don't return any values
})

which is equivalent to the following

router.get<void>(req => {
    // something and don't return any values
})
gabrielmaldi commented 1 year ago

Thanks! I think I'll go with zod for request validation and typing. Regarding the response, if I find some time I'll try to open a PR. Thanks again!