OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
22.03k stars 6.61k forks source link

[Feature] [TYPESCRIPT] Generator parses to Array instead of Set #8258

Open SchillingSebastian opened 3 years ago

SchillingSebastian commented 3 years ago

Bug Report Checklist

Description

If I generate a typescript-angular client with the latest 5.0 stable release, query the mentioned endpoint and try to use user.authority.has(UserAuthorityEnum.Admin) within a component I get the following error. (In Both Template/Component the Error occurs)

ERROR TypeError: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ɵɵpipeBind1(...).authority.has is not a function
    at DashboardComponent_Template (main.js:2043)
    at executeTemplate (vendor.js:65785)
    at refreshView (vendor.js:65654)
    at refreshComponent (vendor.js:66801)
    at refreshChildComponents (vendor.js:65460)
    at refreshView (vendor.js:65704)
    at refreshEmbeddedViews (vendor.js:66755)
    at refreshView (vendor.js:65678)
    at refreshComponent (vendor.js:66801)
    at refreshChildComponents (vendor.js:65460)
    at refreshView (vendor.js:65704)
    at refreshEmbeddedViews (vendor.js:66755)
    at refreshView (vendor.js:65678)
    at refreshComponent (vendor.js:66801)
    at refreshChildComponents (vendor.js:65460)

With further investigation it seems like the field authority is an Array instead of a Set. I am not sure if this is a bug or if this is a result of a faulty spec. I validated with the cli validator, as well as the swagger editor and the referenced validator. This behaviour was also present in the 5.0 beta 3 and I hoped it would be solved with the stable release.

Can anyone point me in the right direction? If there are any more specs/configs I can help you with, don't hesitate to ask for them.

openapi-generator version

Latest stable release (5.0.0)

OpenAPI declaration file content or url
openapi: 3.0.1
info:
  title: Some Api
  description: Some Desc
  version: 0.2.0
servers:
- url: https://sample.url.com
  description: Generated server url
security:
- bearerAuth: []
paths:
  /api/users/me:
    get:
      tags:
      - user-resource
      operationId: getMe
      responses:
        "200":
          description: OK
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/User'

components:
  schemas:
    User:
      required:
      - authority
      - firstName
      - id
      - lastName
      - userStatus
      type: object
      properties:
        id:
          type: integer
          format: int64
          example: 12
        firstName:
          type: string
          example: Average
        lastName:
          type: string
          example: Joe
        phoneNumber:
          type: string
          example: "01101001001"
        userStatus:
          type: string
          example: ACTIVATED
          enum:
          - UNUSED
          - ACTIVATED
          - BLOCKED
        facilityId:
          type: integer
          format: int64
          example: 13
        authority:
          uniqueItems: true
          type: array
          example: "[CUSTODIAN]"
          items:
            type: string
            example: "[CUSTODIAN]"
            enum:
            - CUSTODIAN
            - EDUCATOR
            - FACILITY_DIRECTOR
            - SUPPORT
            - ADMIN
        childIds:
          uniqueItems: true
          type: array
          example:
          - 1
          - 2
          - 3
          items:
            type: integer
            format: int64
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
Generation Details

config.yaml (string enum doesn't affect thus error, I tried it with the default value as well)

snapshot: true
npmName: '@repo/api-ts-client'
npmRepository: 'https://repo-url.com/repository/npm-internal/'
stringEnums: true
Steps to reproduce

generate client

java -jar openapi-generator-cli.jar validate -i api-docs.yaml
java -jar openapi-generator-cli.jar generate -o npm-client -g typescript-angular -c config.yaml -i api-docs.yaml
cd npm-client
npm install
npm run build
npm publish dist

install it within your angular project and try to call method and try to call user.authority.has(UserAuthorityEnum.Admin) on a fetched user. You can use this json for as it is my server response

{
"id":1,
"firstName":"Admin",
"lastName":"Admin",
"phoneNumber":"01101001001",
"userStatus":"ACTIVATED",
"facilityId":null,
"authority":["ADMIN"],
"childIds":[]
}

Look in the console and look for the mentioned problem.

Related issues/PRs

I didn't find any related PR/Issues

auto-labeler[bot] commented 3 years ago

👍 Thanks for opening this issue! 🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

macjohnny commented 3 years ago

@SchillingSebastian using Set when uniqueItems: true has not yet been implemented. would you want to do so?

SchillingSebastian commented 3 years ago

@macjohnny Thank you for you fast answer. I haven't had a look into the deeper inner workings of the generator. How much of a time investment would the implementation of that feature be (for me)? I am interested :)

macjohnny commented 3 years ago

@SchillingSebastian I guess this could be done in one or two days. in order to maintain backwards compatibility, an option would need to be introduced that enables this new behavior

SchillingSebastian commented 3 years ago

@macjohnny I am currently looking into it, but can't quite get the starting point. As this seems to be a problem during the deserialization from the http body to the model I tried finding the actual process but there doesn't seem to be (an obvious) one. My guess is I have to extend the ts generator config options and make changes/extend typescript-fetch. Is this correct? If I am missing something really obvious, please tell me 👍

macjohnny commented 3 years ago

I just noticed that for the typescript-angular generator, this would require implementing a deserialization logic. currently, the plain JSON object is returned, and since Set is not a JSON type, one would have to transform that object. I deleted my original time estimate, since this would require much more effort to implement. maybe it would be beneficial to adapt the current angular generator https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources/typescript-angular to the new typescript generator https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources/typescript https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptClientCodegen.java which has an object deserializer https://github.com/OpenAPITools/openapi-generator/blob/c3220848f24bbc5e5441f53846916eaa82e6673c/modules/openapi-generator/src/main/resources/typescript/model/ObjectSerializer.mustache#L141

felixfiskare commented 3 years ago

I think I've encountered the same error and that it is actually a bug. A small example: My openapi yaml has a training object, which has a audiences array, where every entry is supposed to be unique

    Training:
      type: object
      properties:
        audiences:
          uniqueItems: true
          type: array

I use openapi-generator-cli generate -g typescript-angular to generate a client to use in my angular application. This results in an interface called Training, which has an attribute audiences, which is of type Set. In my openapi yaml I also have a url defined, which returns a Training:

  /trainings/{id}:
    get:
      tags:
      - training
      description: get-training
      operationId: get-training
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            application/hal+json:
              schema:
                $ref: '#/components/schemas/Training'
        "404":
          description: Not Found

If I now use the generated method get-training I get a training object, but instead of an audiences attribute of type Set it is of type Array (because of no serialization, as @macjohnny pointed out).

Therefore either the generated model or the generated method is incorrect and I think this qualifies for this Issue to be a bug.

macjohnny commented 3 years ago

@felixfiskare due to the missing serialization/deserialization logic, we should ensure the resulting type is Array instead of Set

felixfiskare commented 3 years ago

I agree :+1:

macjohnny commented 3 years ago

As a current workaround, you could add a type mapping from set to array

macjohnny commented 3 years ago

related PR: https://github.com/OpenAPITools/openapi-generator/pull/6931

t-h-e commented 3 years ago

I had the same/similar issue with typescript-fetch. --type-mappings=set=Array worked as a workaround. I have created a PR for typescript-fetch. I wasn't sure if I should create a new issue. If referencing this one, was wrong, just let me know. As the different typescript generators all seem somewhat different, I have only fixed it for typescript-fetch so far.

xseman commented 3 years ago

I had the same/similar issue with typescript-fetch. --type-mappings=set=Array worked as a workaround. I have created a PR for typescript-fetch. I wasn't sure if I should create a new issue. If referencing this one, was wrong, just let me know. As the different typescript generators all seem somewhat different, I have only fixed it for typescript-fetch so far.

This will change the interface to Array but ..FromJSON function still tries to use Set, which leads to type mismatch error.

smainz commented 2 years ago

@macjohnny Why has this issue been closed? The bug was reported against the typescript-angular generator and it still exists in 5.4.0 I see fixes for the 'typescript generator' and 'typescript-fetch', but nothing has changed for 'typescript-angular'. In https://github.com/OpenAPITools/openapi-generator/issues/8258#issuecomment-749600830 you are talking about refactoring the typescript-angular generator.

macjohnny commented 2 years ago

oops, my bad

smainz commented 2 years ago

Is there anything I can contribute with my limited skills?

YBCoding commented 2 years ago

Shouldn't we share typescript models generation between all typescript generators and have something above for clients ? Does someone have an idea on how we could accomplish that ? I'm a bit new to this repos and all the generic mustache things ^^"

macjohnny commented 2 years ago

@YBCoding there is a unification approach in https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources/typescript

eliw00d commented 1 year ago

I had the same/similar issue with typescript-fetch. --type-mappings=set=Array worked as a workaround. I have created a PR for typescript-fetch. I wasn't sure if I should create a new issue. If referencing this one, was wrong, just let me know. As the different typescript generators all seem somewhat different, I have only fixed it for typescript-fetch so far.

This will change the interface to Array but ..FromJSON function still tries to use Set, which leads to type mismatch error.

I just ran into this with v6.6.0 of typescript-fetch and its ToJSON and FromJSON helpers. Is this intended or a bug?