asyncapi / modelina

A library for generating typed models based on inputs such as AsyncAPI, OpenAPI, and JSON Schema documents with high customization
https://modelina.org
Apache License 2.0
313 stars 182 forks source link

Generation of enums in golang can't define the type name properly #1090

Closed lcc closed 1 year ago

lcc commented 1 year ago

Describe the bug

When generating models using the GoGenerator() if there are enums in the schemas definitions they are renamed to AnonymousSchema.

How to Reproduce

import { GoGenerator } from '../../src';

const generator = new GoGenerator()

const input = {
  "asyncapi": "2.4.0",
  "info": {
    "title": "FloorPlan service",
    "version": "1.0.0",
    "description": "This service is in charge of processing floorplan elements updates."
  },
  "defaultContentType": "application/json",
  "servers": {
    "development-kafka": {
      "url": "blahblah.com",
      "protocol": "kafka",
      "protocolVersion": "1.0.0",
      "description": "A longer description"
    }
  },
  "channels": {
    "event.order.created": {
      "description": "This event is issued by order-ms and notifys of an order creation",
      "servers": [
        "development-kafka"
      ],
      "bindings": {
        "kafka": {
          "topic": "blah",
          "partitions": 32,
          "replicas": "blah",
          "topicConfiguration": "blah",
          "bindingVersion": "1231"
        }
      },
      "publish": {
        "message": {
          "$ref": "#/components/messages/OrderCreated"
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BaseEvent": {
        "additionalProperties": false,
        "type": "object",
        "properties": {
          "orderID": {
            "type": "string",
            "description": "Unique ID that is able to discern between different order types"
          },
          "type": {
            "type": "string",
            "enum": [
              "event.waiter.called",
              "event.diner.added",
              "event.order.closed",
              "event.payment.added",
              "event.item.ordered",
              "event.item.delivered",
              "event.order.created"
            ]
          }
        }
      },
      "OrderCreated": {
        "additionalProperties": false,
        "allOf": [
          {
            "$ref": "#/components/schemas/BaseEvent"
          },
          {
            "type": "object",
            "properties": {
              "orderShortID": {
                "type": "string",
                "description": "Represents the order's short id"
              },
              "status": {
                "type": "string",
                "description": "Represents the status of the order",
                "enum": [
                  "waiting",
                  "dining",
                  "paying",
                  "paid",
                  "none"
                ]
              },
              "allDinnersAreCa": {
                "type": "boolean",
                "description": "Is true if all diners are ca"
              },
              "HasCaDiners": {
                "type": "boolean",
                "description": "Is true if at least one diner is ca"
              },
              "showNeedAssistanceIcon": {
                "type": "boolean",
                "description": "Is true if assistance was requested"
              },
              "notificationCount": {
                "type": "integer",
                "description": "Represents the number of notifications the order has"
              },
              "updatedAt": {
                "type": "string",
                "description": "Timestamp of the last time an update was made"
              },
              "createdAt": {
                "type": "string",
                "description": "Timestamp of the creation of order object"
              }
            }
          }
        ]
      }
    },
    "messages": {
      "OrderCreated": {
        "payload": {
          "$ref": "#/components/schemas/OrderCreated"
        }
      }
    }
  }
};

export async function generate() : Promise<void> {
  const models = await generator.generate(input)
  for (const model of models) {
    console.log(model.result);
  }
}
generate();

Expected behavior

The expected behavior would be for the models to appear with their proper names.

jonaslagoni commented 1 year ago

@lcc do you mind clarifying which exact names you would expect from the generator and what you received?

jonaslagoni commented 1 year ago

Inferring names for models from JSON Schema is no exact science, so it's not as easy as saying it should be A or B, but happy to have a conversation about how to improve the default naming strategy 🙂

You can explicitly define the names using $id so for example do:

              "status": {
                "$id": "BaseEventStatus",
                "type": "string",
                "description": "Represents the status of the order",
                "enum": [
                  "waiting",
                  "dining",
                  "paying",
                  "paid",
                  "none"
                ]
              },

If you have no control over the input data, you can remap the constrained names, but that should be a last resort IMO.

const generator = new GoGenerator({
  constraints: {
    modelName: ({modelName}) => {
      const constrainedModelName = goDefaultModelNameConstraints()({modelName});
      // Overwrite the name to use while still keeping the naming constraints for Go.
      if(constrainedModelName === 'AnonymousSchema_2') return 'BaseEventType';
      if(constrainedModelName === 'AnonymousSchema_5') return 'BaseEventStatus';
      return constrainedModelName;
    }
  }
});
lcc commented 1 year ago

You can explicitly define the names using $id so for example do:

That solved it, thanks.

Inferring names for models from JSON Schema is no exact science, so it's not as easy as saying it should be A or B, but happy to have a conversation about how to improve the default naming strategy 🙂

Well, all other names were the keys for their schemas, so I guessed it would be the same way to the schema.

Anyhow I am going to make this as solved because it fixed my issue. Do you happen to know if it's possible for the generated files to have their json annotation generated?

jonaslagoni commented 1 year ago

Do you happen to know if it's possible for the generated files to have their json annotation generated?

It is once I finish #639 😅