swagger-typescript-api icon indicating copy to clipboard operation
swagger-typescript-api copied to clipboard

[route generation] multiple response type cases

Open paztis opened this issue 2 years ago • 4 comments

I've got a request the has 2 different return types: one on status 200 and another one on status 201

paths:
  /hello:
    get:
      tags:
        - "Hello Api"
      operationId: sayHello
        
      responses:
        200:
          schema:
            $ref: "#/definitions/Hello"
        201:
          schema:
            $ref: "#/definitions/User"
        400:
          $ref: "#/responses/400-BadRequest"
        401:
          $ref: "#/responses/401-Unauthorized"
        404:
          $ref: "#/responses/404-NotFound"
        500:
          $ref: "#/responses/500-InternalServerError"
        default:
          $ref: "#/responses/500-InternalServerError"

It generated me this namespace


export namespace Hello {
  /**
   * @tags Hello Api
   * @name SayHello
   * @request GET:/hello
   * @response `200` `Hello`
   * @response `201` `User`
   * @response `400` `Error`
   * @response `401` `Error`
   * @response `404` `Error`
   * @response `500` `Error`
   * @response `default` `Error`
   */
  export namespace SayHello {
    export type RequestParams = {};
    export type RequestQuery = {};
    export type RequestBody = never;
    export type RequestHeaders = {};
    export type ResponseBody = Hello;
  }
}

I think the correct response body is ResponseBody = Hello | User; as we cans return the 2 types

Also in case want to return an error, how is it supposed to work ? the error cases are only refered in @response decorator

paztis avatar Nov 23 '21 10:11 paztis

problem came from route.js

const successResponse = responseInfos.find((response) => response.isSuccess);
...
success: {
      schema: successResponse,
      type: (successResponse && successResponse.type) || TS_KEYWORDS.ANY,
}

while it might be like the errors

const successResponses = responseInfos.filter(
      (response) => response.isSuccess,
  );
...
success: {
      schemas: successResponses,
      type: _.uniq(errorResponses.map((response) => response.type)).join(" | ") || TS_KEYWORDS.ANY,
    }

Problem if we do this is is the structure change

responseBodySchema: responseBodyInfo.success.schema,

is this change doable ?

paztis avatar Nov 23 '21 19:11 paztis

please generate each status response a seperate type, like ResponseBody200, ResponseBody400, and use a type alias type ResponseBody = ResponseBody200

chaoyangnz avatar Apr 29 '22 03:04 chaoyangnz

I encountered the same problem. I addressed it by creating template files as instructed in the README and modifying route-types.ejs as follows.

export namespace <%~ routeNamespace %> {
  export type RequestParams = <%~ (pathParams && pathParams.type) || '{}' %>;
  export type RequestQuery = <%~ (query && query.type) || '{}' %>;
  export type RequestBody = <%~ (payload && payload.type) || 'never' %>;
  export type RequestHeaders = <%~ (headers && headers.type) || '{}' %>;
  export type ResponseBody = <%~ route.response.type %>;
  /* new export statement for full response types */
  export type ResponseFull = <%~ route.response.fullTypes %>;
}

aki202 avatar Aug 13 '23 11:08 aki202

I came across the same issue where an API is documented to return multiple success responses, with different 2xx status codes. I addressed it by copying api.ejs and procedure-call.ejs and modified procedure-call.ejs. This is similar to https://github.com/acacode/swagger-typescript-api/issues/318#issuecomment-977029823 but is done in the template.

+ const getSuccessResponseTypes = () => {
+   const successResponses = responseBodyInfo.responses.filter(response => response.isSuccess);
+
+   return config.Ts.UnionType(successResponses.map((response) => response.type)) || this.config.Ts.Keyword.Any;
+ }

- <%~ config.singleHttpClient ? 'this.http.request' : 'this.request' %><<%~ type %>, <%~ errorType %>>
+ <%~ config.singleHttpClient ? 'this.http.request' : 'this.request' %><<%~ `${getSuccessResponseTypes()}` %>, <%~ errorType %>>

This generated all the success response types as a Union type.

avdkishore avatar Sep 11 '23 10:09 avdkishore