lukeautry / tsoa

Build OpenAPI-compliant REST APIs using TypeScript and Node
MIT License
3.33k stars 481 forks source link

tsoa spec-and-routes compatibility issue #1560

Closed falk-stefan closed 3 months ago

falk-stefan commented 5 months ago

I am using tsoa spec-and-routes in combination with openapi-generator-cli generate -g typescript-fetch in my react web app.

In short, the generated client code does send the payload, as expected, in the body. However, it seems like the endpoint I created does not expect the DTO, but the actual request object which contains the DTO.

// Simplified: This is what the client sends to the backend (correct and what I want):
{ body: { id: 1, name: "Ford" } as CarDto }
// Simplified: This is what the backend expects. During verification it looks if the field `carDto` is present in the payload
{ body: { carDto: { id: 1, name: "Ford" } as CarDto } as CreateCarRequest }

So, there appears to be a compatibility issue that could be solved in two ways.

I'd prefer to send just the CarDto in the payload, which means I need the endpoint to look like this (which it does):

@Post()
public async createCar(@Body() carDto: CarDto): Promise<Car> {
  return Promise.resolve({ id: 1337, name: 'Fake Car' });
}

But, as stated, the generated routes.ts it conflicting and expects the carDto attribute in the payload.

Please note that I cannot change the endpoint from

@Post()
public async createCar(@Body() carDto: CarDto): Promise<Car> {
  return Promise.resolve({ id: 1337, name: 'Fake Car' });
}

to

@Post()
public async createCar(@Body() { carDto }: { carDto: CarDto }): Promise<Car> {
  return Promise.resolve({ id: 1337, name: 'Fake Car' });
}

as this would just nest the entire thing on code-generation.

How can I fix this?

Note: I asked this question on stackoverflow

github-actions[bot] commented 5 months ago

Hello there falk-stefan 👋

Thank you for opening your very first issue in this project.

We will try to get back to you as soon as we can.👀

github-actions[bot] commented 4 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

jackey8616 commented 3 months ago

@falk-stefan You give tsoa this:

@Post()
public async createCar(@Body() carDto: CarDto): Promise<Car> {
  console.log(JSON.stringify(carDto));
  return Promise.resolve({ id: 1337, name: 'Fake Car' });
}

And the runtime behavior in console.log is this?

{ body: { carDto: { id: 1, name: "Ford" } } }

But I cannot reproduce this in tsoa@6.1.5. If you use @Body decorator, the parameter CarDto would be the whole body struct in request.

falk-stefan commented 3 months ago

@jackey8616 hey! Thanks for taking a look at this - the problem was on my side and a misunderstanding how the API works. Closing this issue :)