hey-api / openapi-ts

✨ Turn your OpenAPI specification into a beautiful TypeScript client
https://heyapi.vercel.app
MIT License
639 stars 45 forks source link

Return types are not unique across services. They conflict. #637

Closed ianberdin closed 6 days ago

ianberdin commented 1 month ago

Description

Hi, thanks again for your huge contribution to Open Source with this package.

It seems like we're doing something wrong because the type in JSDoc doesn't match the actual return type. As a result, the return type, like CreateResponse, is the same for all services.

We're trying to make an SDK that works like this using tags (users, carts, bookings) and operationIds (create):

api.users.create() -> UsersCreateResponse
api.carts.create() -> CartsCreateResponse
api.bookings.create() -> BookingsCreateResponse

But what we get is (always CreateResponse and CreateData):

/**
 * Create
 * No description
 * @param data The data for the request.
 * @param data.requestBody
 * @returns UsersCreateResponseDto Created
 * @throws ApiError
 */
public create(data: CreateData): CancelablePromise<CreateResponse> {
    return this.httpRequest.request({
        method: 'POST',
        url: '/api/v1/users/create',
        body: data.requestBody,
        mediaType: 'application/json',
    });
}

OpenAPI specification (optional)

"/api/v1/users/create": {
      "post": {
        "operationId": "create",
        "summary": "Create",
        "description": "Create an user",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsersCreateRequestDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsersCreateResponseDto"
                }
              }
            }
          },
        },
        "tags": [
          "Users"
        ]
      }
    },

"/api/v1/carts/create": {
      "post": {
        "operationId": "create",
        "summary": "Create",
        "description": "Create a cart",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CartsCreateRequestDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CartsCreateResponseDto"
                }
              }
            }
          },
        },
        "tags": [
          "Carts"
        ]
      }
    }

Configuration

@hey-api/openapi-ts \
        --input "${swagger_url}" \
        --output "${output_dir}" \
        --client fetch \
        --name "Api"

System information (optional)

No response

ianberdin commented 1 month ago

If we don't specify an operationId, the API will look like this:

api.users.usersControllerCreate() -> UsersControllerCreateResponse
api.carts.cartsControllerCreate() -> CartsControllerCreateResponse
api.bookings.bookingsControllerCreate() -> BookingsControllerCreateResponse
mrlubos commented 1 month ago

Hey @ianberdin, is this a regression?

ianberdin commented 1 month ago

No, it's not. I can't use the next version 0.46.* because it breaks completely, so I'm using 0.45.3.

ianberdin commented 1 month ago

There is no this on root file, I see it does not use classes anymore (0.46.*):

image
mrlubos commented 1 month ago

Try https://heyapi.vercel.app/openapi-ts/migrating.html#v0-46-0

ianberdin commented 1 month ago

Thank you for your quick response. The issue with this has been resolved.

The main problem now is non-unique names when using a custom operationId. Is there a way to fix this?

image
ianberdin commented 1 month ago

And this, if I set new hey-api fetch client:

image
mrlubos commented 1 month ago

Not that I'm aware, will need to look at this. Thanks for reporting!

ianberdin commented 1 month ago

If I remove the operationId, it will look like this:

api.users.usersControllerCreate() - not very appealing for a customer-facing API :(

image
mrlubos commented 1 month ago

Are you on Discord @ianberdin? Would like to understand your use case better

ianberdin commented 1 month ago

I've sent you a request in Discord. @ianberdin mine username.

mrlubos commented 6 days ago

I think you can resolve this with services.methodNameBuilder(), let me know if not