lukeautry / tsoa

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

Multiple Examples with @Response Decorator not possible anymore #1570

Closed DaWoCX closed 4 months ago

DaWoCX commented 4 months ago

Looking for a way to add multiple examples with the @Response decorator, I think I found a bug. I've gathered all the info I could find and made my assumption where and how things go not as I expected them to. But I'm not quite sure how my suggested solution would work with other examples like the @Example-ones for the @SuccessResponse. So if I misunderstood something I hope you can help me out! If my solution would fit, I would be happy to create a pull request for it! Thanks in advance!

Sorting

Expected Behavior

The following example shows how I would define multiple examples for a e.g. response with status code 422 by defining an array of examples of ResponseType.

// Definition of the ResponseType 
export interface ResponseType {
  message: string;
}

  @Post("auth/device-key/establish")
  @SuccessResponse(200)
  @Response<ResponseType>("403", "Forbidden", {
    message: "Device Key is already established"
  })
  @Response<ResponseType[]>("422", "Validation Error", [{
    message: "Provided type is invalid"
   }, {
    message: "Challenge is invalid"
   }])
  public async establishPatientDeviceKey(
    @Body() body: EstablishDeviceKey) {
    return await establishDeviceKey(body);
  }

I would expect this to produce a swagger.json like this:

  "422": {
      "description": "Validation Error",
      "content": {
          "application/json": {
              "schema": {
                  "items": {
                      "$ref": "#/components/schemas/ResponseType"
                  },
                  "type": "array"
              },
              "examples": {
                  "Example 1": {
                      "value":   {
                              "message": "Provided type is invalid"
                       }
                  },
                  "Example 2": {
                      "value":  {
                              "message": "Challenge is invalid"
                      }
                  }
              }
          }
      }
  }

Current Behavior

Currently this does not work and only adds the two examples as value of "Example 1". While searching for a solution to my problem, I came across the issue (https://github.com/lukeautry/tsoa/issues/650) and the pull request (https://github.com/lukeautry/tsoa/pull/727) for it. As far as I understand it, this already removed the option to specify multiple examples with a @Responses Decorator. A later commit by @WoH (https://github.com/WoH/tsoa/commit/9c228a4346a3957c6dc6147bfd3ab15b5d4683d3) fixed a bug with undefined examples, but the passed example, if defined, was passed as a single entry in an array.

examples: example === undefined ? undefined : [example],

In my opinion, this leads to the above mentioned problem that several example-objects are set as the value of the first and only example in the swagger.json.

Possible Solution

If I have understood it correctly, a possible solution to the problem would be to check whether example is an array and, if so, to pass it directly:

examples: Array.isArray(example) && example.length > 0 ? example : (example === undefined ? undefined : [example]),

Steps to Reproduce

  1. Add a @Response decorator to a route and add multiple examples as third parameter
  2. Build and check swagger.json result. The multiple examples are all added as the value of one example for the response.

Context (Environment)

Version of the library: v6.0.1 Version of NodeJS: 20.9.0

Detailed Description

--

Breaking change?

--

Josefh90 commented 4 months ago

+1

nicoleWo commented 4 months ago

+1

EchseKuhTiere commented 4 months ago

+1

DaWoCX commented 3 months ago

@MiguelSavignano @WoH thank you very much!