mrdannael / genum-openapi

Generate Typescript enums from the openapi schema
MIT License
3 stars 2 forks source link

Empty generated enum file #4

Open borzaka opened 1 month ago

borzaka commented 1 month ago

I have an api-docs.json which looks like this. I have stripped down some unrelated stuff.

{
  "openapi": "3.0.1",
  "components": {
    "schemas": {
      "TestlogResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "format": "int64" },
          "testType": {
            "type": "string",
            "enum": ["WEB", "MOBILE_ANDROID", "MOBILE_IOS"]
          },
          "testResult": {
            "type": "string",
            "enum": ["SUCCESSFUL", "ABORTED", "FAILED", "IN_PROGRESS"]
          }
        }
      }
    }
  }
}

Command line I used to generate the enums: genum-openapi docs/api/api-docs.json -o src/lib/api/enums.ts

But the enum.ts is an empty file.

mrdannael commented 1 month ago

Hi. Are you able to pinpoint the version of CLI where the conversion works properly for your file? or the version doesn't matter?

borzaka commented 1 month ago

No, this was my first time with this package.

mrdannael commented 1 month ago

I probably know what the issue is. There's notihing wrong with your file. When comparing to the shape of json within the test folder:

{
  "openapi": "3.0.3",
  "info": {
    "title": "Example of the API document",
    "version": "0.0.0",
    "description": "Description of the API document"
  },
  "components": {
    "schemas": {
      "AgencyStatus": {
        "enum": ["ACTIVE", "ARCHIVED"],
        "type": "string"
      }
    }
  }
}

I see that the enums are deeper than on the level one (in your case in the properties object). In the source code of the CLI, there's function which is looking for enum key (and some other conditional statements) only on the first level of object, right after TestLogResponse key in your case.

Well, given that the object with properties key is still a valid OpenAPI document, the CLI will need an improvement in this matter to properly handle enums placed deeper.

I'm thinking about the name of the enum i.e. for provided example by you.

export enum TestlogResponse__testType {
  WEB = "WEB",
  MOBILE_ANDROID = "MOBILE_ANDROID",
  MOBILE_IOS = "MOBILE_IOS",
}

export enum TestlogResponse__testResult {
  SUCCESSFUL = "SUCCESSFUL",
  ABORTED = "ABORTED",
  FAILED = "FAILED",
  IN_PROGRESS = "IN_PROGRESS"
}

or simply

export enum testType {
  WEB = "WEB",
  MOBILE_ANDROID = "MOBILE_ANDROID",
  MOBILE_IOS = "MOBILE_IOS",
}

export enum testResult {
  SUCCESSFUL = "SUCCESSFUL",
  ABORTED = "ABORTED",
  FAILED = "FAILED",
  IN_PROGRESS = "IN_PROGRESS"
}

Which one looks good to you? I will work on the improvement of the CLI in the coming days.

borzaka commented 1 month ago

I have the same enum keys in different object on the same level. This is for a request:

...
"TestlogRequest": {
  "type": "object",
  "properties": {
    "date": { "type": "string", "format": "date" },
    "testType": {
      "type": "string",
      "enum": ["WEB", "MOBILE_ANDROID", "MOBILE_IOS"]
    },
    "testResult": {
      "type": "string",
      "enum": ["SUCCESSFUL", "ABORTED", "FAILED", "IN_PROGRESS"]
    }
  }
},
...

Well, I'am fine with both of the enum names you provided. Maybe pick a default one, and add a CLI option for the other one?

mrdannael commented 1 month ago

Yeah, I'm considering adding an additional CLI option. By default, generated enums will follow the format of those in the second example. However, with the --with-parent option, the generated enums will adopt the format of the first example to prevent name collisions in such cases.

I'll let you know once the feature is implemented and the new package is released on npm.

mrdannael commented 1 month ago

Hi! I've just released 0.8.0-alpha.0 version of the package with the improved function for collecting deep nested enums along with the --with-parent option. Try it and let me know if the generated file is not empty and enums are collected properly :wink:

borzaka commented 1 month ago

Looking good:

enums.ts default

export enum testType {
  WEB = "WEB",
  MOBILE_ANDROID = "MOBILE_ANDROID",
  MOBILE_IOS = "MOBILE_IOS",
}

export enum testResult {
  SUCCESSFUL = "SUCCESSFUL",
  ABORTED = "ABORTED",
  FAILED = "FAILED",
  IN_PROGRESS = "IN_PROGRESS",
}

enums.ts with --with-parent

export enum TestlogResponse__testType {
  WEB = "WEB",
  MOBILE_ANDROID = "MOBILE_ANDROID",
  MOBILE_IOS = "MOBILE_IOS",
}

export enum TestlogResponse__testResult {
  SUCCESSFUL = "SUCCESSFUL",
  ABORTED = "ABORTED",
  FAILED = "FAILED",
  IN_PROGRESS = "IN_PROGRESS",
}

Probably I will use the --with-parent option, because I just saw an enum with a type name in my schema, which is not so self explanatory :) I got it from the backend.

Thank you for your work!

mrdannael commented 1 month ago

Awesome :tada: I'm glad it works. In the meantime I'll fix issues rised by linter and typescript and release it as a proper v0.8.0. Then close this issue. But for you nothing should change :wink:

borzaka commented 1 month ago

I might have found another example where the enum is not generated:

---
openapi: 3.0.0
components:
  schemas:
    PaymentMethod:
      required:
        - type
      description: "A Payment Method is a pure-virtual super-class that defines a specific method of payment such as Direct Debit, Cash, Digital Wallet,Tokenized Card, Bank Account Transfer, Bank Account Debit, Bank Card, Voucher, Check, Bucket PaymentMethod, Account PaymentMethod, and Loyalty PaymentMethod with all details associated. Use the @type attribute to specify the concrete type in the API calls."
      allOf:
        - $ref: '#/components/schemas/BaseObject'
        - type: object
          properties:
            type:
              type: string
              description: "Type of payment method (e.g.: bank card, cash, voucher, etc)."
              enum:
                - none
                - cash
                - online
                - bank-transfer
                - token-online
            period:
              $ref: '#/components/schemas/Quantity'

This is a YAML file, I have no control over it.

mrdannael commented 1 month ago

The problem might be similar to the previous one. I'll look on it and let you know.

mrdannael commented 4 weeks ago

Yep. Almost there, should be ready for tommorow :smile: Just doing some small improvements and typechecking fixes.

mrdannael commented 3 weeks ago

Hey @borzaka

As promised, I've released new version to the npm registry 0.8.0-alpha.1. Let me know if it resolves the issue with collecting enums from allOf properties. (allOf, oneOf, anyOf, and not should be supported :smiley: )

borzaka commented 3 weeks ago

Thank you!

More enums got generated as before, so it's definitely better! :)

I still found some enums which are missing from the generated file. Can you tell me that they should be included, or not?

This: PatchDocument / op

components:
  schemas:
    PatchDocument:
      required:
        - op
        - path
      properties:
        op:
          type: string
          description: Művelet kódja
          enum:
            - add
            - remove
            - replace
            - move
            - copy
            - test
        path:
          type: string
          description: "[JSON pointer](https://tools.ietf.org/html/rfc6901) arra az elemre, amire a művelet vonatkozik \\n"
        value:
          type: object
          description: A művelet adat része
        from:
          type: string
          description: "[JSON pointer](https://tools.ietf.org/html/rfc6901) arra a forrás elemre, amire a művelet vonatkozik  \\n"

And this: listShoppingCartLov / lovType

paths:
  /shopping-carts/{cartId}/lovs:
    get:
      tags:
        - ShoppingCart
      summary: Az adott kosáron érvényes LOV-ok lekérdezése
      description: Az adott kosáron érvényes LOV-ok lekérdezése
      operationId: listShoppingCartLov
      parameters:
        - name: lovType
          in: query
          description: LOV típus kódja
          required: false
          style: form
          explode: true
          schema:
            type: string
            enum:
              - PrimaryPersonIdCardTypeList
              - SecondaryPersonIdCardTypeList
              - MNPTimeWindowList
              - MNPOperatorList
              - SIMTypeList
              - TelcoBillingModeList
              - DeliveryModeList
              - DeliveryTimeWindowList
              - PickupPointList
              - ShopList
              - OrderPaymentModeList
              - BillingEntityList
              - MSISDNAssignmentModeList
              - DeliveryCarrierList
          example: PrimaryPersonIdCardTypeList
mrdannael commented 3 weeks ago

I've just released 0.8.0-alpha.2 to the npm. I was excessively checking if type === "object" property exists to fetch enums from properties. Now it should collect PatchDocument__op correctly.

As for the listShoppingCartLov the CLI is currently collecting enums only from the components object, not from the paths. I'll look into types definition and rethink if the CLI should also collect all enums from the paths object :thinking: