Skip to content

Incorrect class split logic for SDK when asClass: true #2437

@imiatselski-cribl

Description

@imiatselski-cribl

Description

My configuration is the following:

export default defineConfig({
  input: 'openapi.json',
  output: 'src/generated',
  plugins: [
    {
      name: '@hey-api/sdk',
      asClass: true,
      auth: false, // handle auth on client level, not function level
      instance: true,
    },
  ],
});

When I have a set of operationId's like:

v1.domain1.fn1
v1.domain2.fn2
v2.domain1.fn3
v2.domain2.fn4

it generates separate classes for v1 and v2: V1 and V2, which contain classes Domain1 and Domain2, which is expected.

The problem is that it generates a single Domain1 class for v1 and v2, which contains fn1 and fn3 methods and the same logic for domain2.

So I can call v1.domain1.fn3 and it's incorrect because v1 doesn't have fn3, it exists for v2 only.

The generated code for the specification below:

class Domain1 extends _HeyApiClient {
    public fn1<ThrowOnError extends boolean = false>(options?: Options<V1Domain1Fn1Data, ThrowOnError>) {
        return (options?.client ?? this._client).get<V1Domain1Fn1Responses, unknown, ThrowOnError>({
            url: '/v1/domain1/fn1',
            ...options
        });
    }
    
    public fn3<ThrowOnError extends boolean = false>(options?: Options<V2Domain1Fn3Data, ThrowOnError>) {
        return (options?.client ?? this._client).get<V2Domain1Fn3Responses, unknown, ThrowOnError>({
            url: '/v2/domain1/fn3',
            ...options
        });
    }
}

class Domain2 extends _HeyApiClient {
    public fn2<ThrowOnError extends boolean = false>(options?: Options<V1Domain2Fn2Data, ThrowOnError>) {
        return (options?.client ?? this._client).get<V1Domain2Fn2Responses, unknown, ThrowOnError>({
            url: '/v1/domain2/fn2',
            ...options
        });
    }
    
    public fn4<ThrowOnError extends boolean = false>(options?: Options<V2Domain2Fn4Data, ThrowOnError>) {
        return (options?.client ?? this._client).get<V2Domain2Fn4Responses, unknown, ThrowOnError>({
            url: '/v2/domain2/fn4',
            ...options
        });
    }
}

class V1 extends _HeyApiClient {
    domain1 = new Domain1({ client: this._client });
    domain2 = new Domain2({ client: this._client });
}

class V2 extends _HeyApiClient {
    domain1 = new Domain1({ client: this._client });
    domain2 = new Domain2({ client: this._client });
}

export class Sdk extends _HeyApiClient {
    v1 = new V1({ client: this._client });
    v2 = new V2({ client: this._client });
}

Reproducible example or configuration

No response

OpenAPI specification (optional)

{
  "openapi": "3.0.0",
  "paths": {
    "/v1/domain1/fn1": {
      "get": {
        "operationId": "v1.domain1.fn1",
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/v1/domain2/fn2": {
      "get": {
        "operationId": "v1.domain2.fn2",
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/v2/domain1/fn3": {
      "get": {
        "operationId": "v2.domain1.fn3",
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
    "/v2/domain2/fn4": {
      "get": {
        "operationId": "v2.domain2.fn4",
        "responses": {
          "200": {
            "description": ""
          }
        }
      }
    },
  }
}

System information (optional)

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🔥Something isn't workingclientClient package related

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions